View.java revision 35c6d6b08aa8fc6c9d59c066c9fb80b842f4de01
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     * |-------|-------|-------|-------|
2419     */
2420
2421    /**
2422     * Flag indicating that view has a transform animation set on it. This is used to track whether
2423     * an animation is cleared between successive frames, in order to tell the associated
2424     * DisplayList to clear its animation matrix.
2425     */
2426    static final int PFLAG3_VIEW_IS_ANIMATING_TRANSFORM = 0x1;
2427
2428    /**
2429     * Flag indicating that view has an alpha animation set on it. This is used to track whether an
2430     * animation is cleared between successive frames, in order to tell the associated
2431     * DisplayList to restore its alpha value.
2432     */
2433    static final int PFLAG3_VIEW_IS_ANIMATING_ALPHA = 0x2;
2434
2435    /**
2436     * Flag indicating that the view has been through at least one layout since it
2437     * was last attached to a window.
2438     */
2439    static final int PFLAG3_IS_LAID_OUT = 0x4;
2440
2441    /**
2442     * Flag indicating that a call to measure() was skipped and should be done
2443     * instead when layout() is invoked.
2444     */
2445    static final int PFLAG3_MEASURE_NEEDED_BEFORE_LAYOUT = 0x8;
2446
2447    /**
2448     * Flag indicating that an overridden method correctly called down to
2449     * the superclass implementation as required by the API spec.
2450     */
2451    static final int PFLAG3_CALLED_SUPER = 0x10;
2452
2453    /**
2454     * Flag indicating that we're in the process of applying window insets.
2455     */
2456    static final int PFLAG3_APPLYING_INSETS = 0x20;
2457
2458    /**
2459     * Flag indicating that we're in the process of fitting system windows using the old method.
2460     */
2461    static final int PFLAG3_FITTING_SYSTEM_WINDOWS = 0x40;
2462
2463    /**
2464     * Flag indicating that nested scrolling is enabled for this view.
2465     * The view will optionally cooperate with views up its parent chain to allow for
2466     * integrated nested scrolling along the same axis.
2467     */
2468    static final int PFLAG3_NESTED_SCROLLING_ENABLED = 0x80;
2469
2470    /**
2471     * Flag indicating that the bottom scroll indicator should be displayed
2472     * when this view can scroll up.
2473     */
2474    static final int PFLAG3_SCROLL_INDICATOR_TOP = 0x0100;
2475
2476    /**
2477     * Flag indicating that the bottom scroll indicator should be displayed
2478     * when this view can scroll down.
2479     */
2480    static final int PFLAG3_SCROLL_INDICATOR_BOTTOM = 0x0200;
2481
2482    /**
2483     * Flag indicating that the left scroll indicator should be displayed
2484     * when this view can scroll left.
2485     */
2486    static final int PFLAG3_SCROLL_INDICATOR_LEFT = 0x0400;
2487
2488    /**
2489     * Flag indicating that the right scroll indicator should be displayed
2490     * when this view can scroll right.
2491     */
2492    static final int PFLAG3_SCROLL_INDICATOR_RIGHT = 0x0800;
2493
2494    /**
2495     * Flag indicating that the start scroll indicator should be displayed
2496     * when this view can scroll in the start direction.
2497     */
2498    static final int PFLAG3_SCROLL_INDICATOR_START = 0x1000;
2499
2500    /**
2501     * Flag indicating that the end scroll indicator should be displayed
2502     * when this view can scroll in the end direction.
2503     */
2504    static final int PFLAG3_SCROLL_INDICATOR_END = 0x2000;
2505
2506    /* End of masks for mPrivateFlags3 */
2507
2508    static final int DRAG_MASK = PFLAG2_DRAG_CAN_ACCEPT | PFLAG2_DRAG_HOVERED;
2509
2510    static final int SCROLL_INDICATORS_NONE = 0x0000;
2511
2512    /**
2513     * Mask for use with setFlags indicating bits used for indicating which
2514     * scroll indicators are enabled.
2515     */
2516    static final int SCROLL_INDICATORS_PFLAG3_MASK = PFLAG3_SCROLL_INDICATOR_TOP
2517            | PFLAG3_SCROLL_INDICATOR_BOTTOM | PFLAG3_SCROLL_INDICATOR_LEFT
2518            | PFLAG3_SCROLL_INDICATOR_RIGHT | PFLAG3_SCROLL_INDICATOR_START
2519            | PFLAG3_SCROLL_INDICATOR_END;
2520
2521    /**
2522     * Left-shift required to translate between public scroll indicator flags
2523     * and internal PFLAGS3 flags. When used as a right-shift, translates
2524     * PFLAGS3 flags to public flags.
2525     */
2526    static final int SCROLL_INDICATORS_TO_PFLAGS3_LSHIFT = 8;
2527
2528    /** @hide */
2529    @Retention(RetentionPolicy.SOURCE)
2530    @IntDef(flag = true,
2531            value = {
2532                    SCROLL_INDICATOR_TOP,
2533                    SCROLL_INDICATOR_BOTTOM,
2534                    SCROLL_INDICATOR_LEFT,
2535                    SCROLL_INDICATOR_RIGHT,
2536                    SCROLL_INDICATOR_START,
2537                    SCROLL_INDICATOR_END,
2538            })
2539    public @interface ScrollIndicators {}
2540
2541    /**
2542     * Scroll indicator direction for the top edge of the view.
2543     *
2544     * @see #setScrollIndicators(int)
2545     * @see #setScrollIndicators(int, int)
2546     * @see #getScrollIndicators()
2547     */
2548    public static final int SCROLL_INDICATOR_TOP =
2549            PFLAG3_SCROLL_INDICATOR_TOP >> SCROLL_INDICATORS_TO_PFLAGS3_LSHIFT;
2550
2551    /**
2552     * Scroll indicator direction for the bottom edge of the view.
2553     *
2554     * @see #setScrollIndicators(int)
2555     * @see #setScrollIndicators(int, int)
2556     * @see #getScrollIndicators()
2557     */
2558    public static final int SCROLL_INDICATOR_BOTTOM =
2559            PFLAG3_SCROLL_INDICATOR_BOTTOM >> SCROLL_INDICATORS_TO_PFLAGS3_LSHIFT;
2560
2561    /**
2562     * Scroll indicator direction for the left edge of the view.
2563     *
2564     * @see #setScrollIndicators(int)
2565     * @see #setScrollIndicators(int, int)
2566     * @see #getScrollIndicators()
2567     */
2568    public static final int SCROLL_INDICATOR_LEFT =
2569            PFLAG3_SCROLL_INDICATOR_LEFT >> SCROLL_INDICATORS_TO_PFLAGS3_LSHIFT;
2570
2571    /**
2572     * Scroll indicator direction for the right edge of the view.
2573     *
2574     * @see #setScrollIndicators(int)
2575     * @see #setScrollIndicators(int, int)
2576     * @see #getScrollIndicators()
2577     */
2578    public static final int SCROLL_INDICATOR_RIGHT =
2579            PFLAG3_SCROLL_INDICATOR_RIGHT >> SCROLL_INDICATORS_TO_PFLAGS3_LSHIFT;
2580
2581    /**
2582     * Scroll indicator direction for the starting edge of the view.
2583     * <p>
2584     * Resolved according to the view's layout direction, see
2585     * {@link #getLayoutDirection()} for more information.
2586     *
2587     * @see #setScrollIndicators(int)
2588     * @see #setScrollIndicators(int, int)
2589     * @see #getScrollIndicators()
2590     */
2591    public static final int SCROLL_INDICATOR_START =
2592            PFLAG3_SCROLL_INDICATOR_START >> SCROLL_INDICATORS_TO_PFLAGS3_LSHIFT;
2593
2594    /**
2595     * Scroll indicator direction for the ending edge of the view.
2596     * <p>
2597     * Resolved according to the view's layout direction, see
2598     * {@link #getLayoutDirection()} for more information.
2599     *
2600     * @see #setScrollIndicators(int)
2601     * @see #setScrollIndicators(int, int)
2602     * @see #getScrollIndicators()
2603     */
2604    public static final int SCROLL_INDICATOR_END =
2605            PFLAG3_SCROLL_INDICATOR_END >> SCROLL_INDICATORS_TO_PFLAGS3_LSHIFT;
2606
2607    /**
2608     * <p>Indicates that we are allowing {@link ViewStructure} to traverse
2609     * into this view.<p>
2610     */
2611    static final int PFLAG3_ASSIST_BLOCKED = 0x4000;
2612
2613    /**
2614     * Always allow a user to over-scroll this view, provided it is a
2615     * view that can scroll.
2616     *
2617     * @see #getOverScrollMode()
2618     * @see #setOverScrollMode(int)
2619     */
2620    public static final int OVER_SCROLL_ALWAYS = 0;
2621
2622    /**
2623     * Allow a user to over-scroll this view only if the content is large
2624     * enough to meaningfully scroll, provided it is a view that can scroll.
2625     *
2626     * @see #getOverScrollMode()
2627     * @see #setOverScrollMode(int)
2628     */
2629    public static final int OVER_SCROLL_IF_CONTENT_SCROLLS = 1;
2630
2631    /**
2632     * Never allow a user to over-scroll this view.
2633     *
2634     * @see #getOverScrollMode()
2635     * @see #setOverScrollMode(int)
2636     */
2637    public static final int OVER_SCROLL_NEVER = 2;
2638
2639    /**
2640     * Special constant for {@link #setSystemUiVisibility(int)}: View has
2641     * requested the system UI (status bar) to be visible (the default).
2642     *
2643     * @see #setSystemUiVisibility(int)
2644     */
2645    public static final int SYSTEM_UI_FLAG_VISIBLE = 0;
2646
2647    /**
2648     * Flag for {@link #setSystemUiVisibility(int)}: View has requested the
2649     * system UI to enter an unobtrusive "low profile" mode.
2650     *
2651     * <p>This is for use in games, book readers, video players, or any other
2652     * "immersive" application where the usual system chrome is deemed too distracting.
2653     *
2654     * <p>In low profile mode, the status bar and/or navigation icons may dim.
2655     *
2656     * @see #setSystemUiVisibility(int)
2657     */
2658    public static final int SYSTEM_UI_FLAG_LOW_PROFILE = 0x00000001;
2659
2660    /**
2661     * Flag for {@link #setSystemUiVisibility(int)}: View has requested that the
2662     * system navigation be temporarily hidden.
2663     *
2664     * <p>This is an even less obtrusive state than that called for by
2665     * {@link #SYSTEM_UI_FLAG_LOW_PROFILE}; on devices that draw essential navigation controls
2666     * (Home, Back, and the like) on screen, <code>SYSTEM_UI_FLAG_HIDE_NAVIGATION</code> will cause
2667     * those to disappear. This is useful (in conjunction with the
2668     * {@link android.view.WindowManager.LayoutParams#FLAG_FULLSCREEN FLAG_FULLSCREEN} and
2669     * {@link android.view.WindowManager.LayoutParams#FLAG_LAYOUT_IN_SCREEN FLAG_LAYOUT_IN_SCREEN}
2670     * window flags) for displaying content using every last pixel on the display.
2671     *
2672     * <p>There is a limitation: because navigation controls are so important, the least user
2673     * interaction will cause them to reappear immediately.  When this happens, both
2674     * this flag and {@link #SYSTEM_UI_FLAG_FULLSCREEN} will be cleared automatically,
2675     * so that both elements reappear at the same time.
2676     *
2677     * @see #setSystemUiVisibility(int)
2678     */
2679    public static final int SYSTEM_UI_FLAG_HIDE_NAVIGATION = 0x00000002;
2680
2681    /**
2682     * Flag for {@link #setSystemUiVisibility(int)}: View has requested to go
2683     * into the normal fullscreen mode so that its content can take over the screen
2684     * while still allowing the user to interact with the application.
2685     *
2686     * <p>This has the same visual effect as
2687     * {@link android.view.WindowManager.LayoutParams#FLAG_FULLSCREEN
2688     * WindowManager.LayoutParams.FLAG_FULLSCREEN},
2689     * meaning that non-critical screen decorations (such as the status bar) will be
2690     * hidden while the user is in the View's window, focusing the experience on
2691     * that content.  Unlike the window flag, if you are using ActionBar in
2692     * overlay mode with {@link Window#FEATURE_ACTION_BAR_OVERLAY
2693     * Window.FEATURE_ACTION_BAR_OVERLAY}, then enabling this flag will also
2694     * hide the action bar.
2695     *
2696     * <p>This approach to going fullscreen is best used over the window flag when
2697     * it is a transient state -- that is, the application does this at certain
2698     * points in its user interaction where it wants to allow the user to focus
2699     * on content, but not as a continuous state.  For situations where the application
2700     * would like to simply stay full screen the entire time (such as a game that
2701     * wants to take over the screen), the
2702     * {@link android.view.WindowManager.LayoutParams#FLAG_FULLSCREEN window flag}
2703     * is usually a better approach.  The state set here will be removed by the system
2704     * in various situations (such as the user moving to another application) like
2705     * the other system UI states.
2706     *
2707     * <p>When using this flag, the application should provide some easy facility
2708     * for the user to go out of it.  A common example would be in an e-book
2709     * reader, where tapping on the screen brings back whatever screen and UI
2710     * decorations that had been hidden while the user was immersed in reading
2711     * the book.
2712     *
2713     * @see #setSystemUiVisibility(int)
2714     */
2715    public static final int SYSTEM_UI_FLAG_FULLSCREEN = 0x00000004;
2716
2717    /**
2718     * Flag for {@link #setSystemUiVisibility(int)}: When using other layout
2719     * flags, we would like a stable view of the content insets given to
2720     * {@link #fitSystemWindows(Rect)}.  This means that the insets seen there
2721     * will always represent the worst case that the application can expect
2722     * as a continuous state.  In the stock Android UI this is the space for
2723     * the system bar, nav bar, and status bar, but not more transient elements
2724     * such as an input method.
2725     *
2726     * The stable layout your UI sees is based on the system UI modes you can
2727     * switch to.  That is, if you specify {@link #SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN}
2728     * then you will get a stable layout for changes of the
2729     * {@link #SYSTEM_UI_FLAG_FULLSCREEN} mode; if you specify
2730     * {@link #SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN} and
2731     * {@link #SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION}, then you can transition
2732     * to {@link #SYSTEM_UI_FLAG_FULLSCREEN} and {@link #SYSTEM_UI_FLAG_HIDE_NAVIGATION}
2733     * with a stable layout.  (Note that you should avoid using
2734     * {@link #SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION} by itself.)
2735     *
2736     * If you have set the window flag {@link WindowManager.LayoutParams#FLAG_FULLSCREEN}
2737     * to hide the status bar (instead of using {@link #SYSTEM_UI_FLAG_FULLSCREEN}),
2738     * then a hidden status bar will be considered a "stable" state for purposes
2739     * here.  This allows your UI to continually hide the status bar, while still
2740     * using the system UI flags to hide the action bar while still retaining
2741     * a stable layout.  Note that changing the window fullscreen flag will never
2742     * provide a stable layout for a clean transition.
2743     *
2744     * <p>If you are using ActionBar in
2745     * overlay mode with {@link Window#FEATURE_ACTION_BAR_OVERLAY
2746     * Window.FEATURE_ACTION_BAR_OVERLAY}, this flag will also impact the
2747     * insets it adds to those given to the application.
2748     */
2749    public static final int SYSTEM_UI_FLAG_LAYOUT_STABLE = 0x00000100;
2750
2751    /**
2752     * Flag for {@link #setSystemUiVisibility(int)}: View would like its window
2753     * to be laid out as if it has requested
2754     * {@link #SYSTEM_UI_FLAG_HIDE_NAVIGATION}, even if it currently hasn't.  This
2755     * allows it to avoid artifacts when switching in and out of that mode, at
2756     * the expense that some of its user interface may be covered by screen
2757     * decorations when they are shown.  You can perform layout of your inner
2758     * UI elements to account for the navigation system UI through the
2759     * {@link #fitSystemWindows(Rect)} method.
2760     */
2761    public static final int SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION = 0x00000200;
2762
2763    /**
2764     * Flag for {@link #setSystemUiVisibility(int)}: View would like its window
2765     * to be laid out as if it has requested
2766     * {@link #SYSTEM_UI_FLAG_FULLSCREEN}, even if it currently hasn't.  This
2767     * allows it to avoid artifacts when switching in and out of that mode, at
2768     * the expense that some of its user interface may be covered by screen
2769     * decorations when they are shown.  You can perform layout of your inner
2770     * UI elements to account for non-fullscreen system UI through the
2771     * {@link #fitSystemWindows(Rect)} method.
2772     */
2773    public static final int SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN = 0x00000400;
2774
2775    /**
2776     * Flag for {@link #setSystemUiVisibility(int)}: View would like to remain interactive when
2777     * hiding the navigation bar with {@link #SYSTEM_UI_FLAG_HIDE_NAVIGATION}.  If this flag is
2778     * not set, {@link #SYSTEM_UI_FLAG_HIDE_NAVIGATION} will be force cleared by the system on any
2779     * user interaction.
2780     * <p>Since this flag is a modifier for {@link #SYSTEM_UI_FLAG_HIDE_NAVIGATION}, it only
2781     * has an effect when used in combination with that flag.</p>
2782     */
2783    public static final int SYSTEM_UI_FLAG_IMMERSIVE = 0x00000800;
2784
2785    /**
2786     * Flag for {@link #setSystemUiVisibility(int)}: View would like to remain interactive when
2787     * hiding the status bar with {@link #SYSTEM_UI_FLAG_FULLSCREEN} and/or hiding the navigation
2788     * bar with {@link #SYSTEM_UI_FLAG_HIDE_NAVIGATION}.  Use this flag to create an immersive
2789     * experience while also hiding the system bars.  If this flag is not set,
2790     * {@link #SYSTEM_UI_FLAG_HIDE_NAVIGATION} will be force cleared by the system on any user
2791     * interaction, and {@link #SYSTEM_UI_FLAG_FULLSCREEN} will be force-cleared by the system
2792     * if the user swipes from the top of the screen.
2793     * <p>When system bars are hidden in immersive mode, they can be revealed temporarily with
2794     * system gestures, such as swiping from the top of the screen.  These transient system bars
2795     * will overlay app’s content, may have some degree of transparency, and will automatically
2796     * hide after a short timeout.
2797     * </p><p>Since this flag is a modifier for {@link #SYSTEM_UI_FLAG_FULLSCREEN} and
2798     * {@link #SYSTEM_UI_FLAG_HIDE_NAVIGATION}, it only has an effect when used in combination
2799     * with one or both of those flags.</p>
2800     */
2801    public static final int SYSTEM_UI_FLAG_IMMERSIVE_STICKY = 0x00001000;
2802
2803    /**
2804     * Flag for {@link #setSystemUiVisibility(int)}: Requests the status bar to draw in a mode that
2805     * is compatible with light status bar backgrounds.
2806     *
2807     * <p>For this to take effect, the window must request
2808     * {@link android.view.WindowManager.LayoutParams#FLAG_DRAWS_SYSTEM_BAR_BACKGROUNDS
2809     *         FLAG_DRAWS_SYSTEM_BAR_BACKGROUNDS} but not
2810     * {@link android.view.WindowManager.LayoutParams#FLAG_TRANSLUCENT_STATUS
2811     *         FLAG_TRANSLUCENT_STATUS}.
2812     *
2813     * @see android.R.attr#windowLightStatusBar
2814     */
2815    public static final int SYSTEM_UI_FLAG_LIGHT_STATUS_BAR = 0x00002000;
2816
2817    /**
2818     * @deprecated Use {@link #SYSTEM_UI_FLAG_LOW_PROFILE} instead.
2819     */
2820    public static final int STATUS_BAR_HIDDEN = SYSTEM_UI_FLAG_LOW_PROFILE;
2821
2822    /**
2823     * @deprecated Use {@link #SYSTEM_UI_FLAG_VISIBLE} instead.
2824     */
2825    public static final int STATUS_BAR_VISIBLE = SYSTEM_UI_FLAG_VISIBLE;
2826
2827    /**
2828     * @hide
2829     *
2830     * NOTE: This flag may only be used in subtreeSystemUiVisibility. It is masked
2831     * out of the public fields to keep the undefined bits out of the developer's way.
2832     *
2833     * Flag to make the status bar not expandable.  Unless you also
2834     * set {@link #STATUS_BAR_DISABLE_NOTIFICATION_ICONS}, new notifications will continue to show.
2835     */
2836    public static final int STATUS_BAR_DISABLE_EXPAND = 0x00010000;
2837
2838    /**
2839     * @hide
2840     *
2841     * NOTE: This flag may only be used in subtreeSystemUiVisibility. It is masked
2842     * out of the public fields to keep the undefined bits out of the developer's way.
2843     *
2844     * Flag to hide notification icons and scrolling ticker text.
2845     */
2846    public static final int STATUS_BAR_DISABLE_NOTIFICATION_ICONS = 0x00020000;
2847
2848    /**
2849     * @hide
2850     *
2851     * NOTE: This flag may only be used in subtreeSystemUiVisibility. It is masked
2852     * out of the public fields to keep the undefined bits out of the developer's way.
2853     *
2854     * Flag to disable incoming notification alerts.  This will not block
2855     * icons, but it will block sound, vibrating and other visual or aural notifications.
2856     */
2857    public static final int STATUS_BAR_DISABLE_NOTIFICATION_ALERTS = 0x00040000;
2858
2859    /**
2860     * @hide
2861     *
2862     * NOTE: This flag may only be used in subtreeSystemUiVisibility. It is masked
2863     * out of the public fields to keep the undefined bits out of the developer's way.
2864     *
2865     * Flag to hide only the scrolling ticker.  Note that
2866     * {@link #STATUS_BAR_DISABLE_NOTIFICATION_ICONS} implies
2867     * {@link #STATUS_BAR_DISABLE_NOTIFICATION_TICKER}.
2868     */
2869    public static final int STATUS_BAR_DISABLE_NOTIFICATION_TICKER = 0x00080000;
2870
2871    /**
2872     * @hide
2873     *
2874     * NOTE: This flag may only be used in subtreeSystemUiVisibility. It is masked
2875     * out of the public fields to keep the undefined bits out of the developer's way.
2876     *
2877     * Flag to hide the center system info area.
2878     */
2879    public static final int STATUS_BAR_DISABLE_SYSTEM_INFO = 0x00100000;
2880
2881    /**
2882     * @hide
2883     *
2884     * NOTE: This flag may only be used in subtreeSystemUiVisibility. It is masked
2885     * out of the public fields to keep the undefined bits out of the developer's way.
2886     *
2887     * Flag to hide only the home button.  Don't use this
2888     * unless you're a special part of the system UI (i.e., setup wizard, keyguard).
2889     */
2890    public static final int STATUS_BAR_DISABLE_HOME = 0x00200000;
2891
2892    /**
2893     * @hide
2894     *
2895     * NOTE: This flag may only be used in subtreeSystemUiVisibility. It is masked
2896     * out of the public fields to keep the undefined bits out of the developer's way.
2897     *
2898     * Flag to hide only the back button. Don't use this
2899     * unless you're a special part of the system UI (i.e., setup wizard, keyguard).
2900     */
2901    public static final int STATUS_BAR_DISABLE_BACK = 0x00400000;
2902
2903    /**
2904     * @hide
2905     *
2906     * NOTE: This flag may only be used in subtreeSystemUiVisibility. It is masked
2907     * out of the public fields to keep the undefined bits out of the developer's way.
2908     *
2909     * Flag to hide only the clock.  You might use this if your activity has
2910     * its own clock making the status bar's clock redundant.
2911     */
2912    public static final int STATUS_BAR_DISABLE_CLOCK = 0x00800000;
2913
2914    /**
2915     * @hide
2916     *
2917     * NOTE: This flag may only be used in subtreeSystemUiVisibility. It is masked
2918     * out of the public fields to keep the undefined bits out of the developer's way.
2919     *
2920     * Flag to hide only the recent apps button. Don't use this
2921     * unless you're a special part of the system UI (i.e., setup wizard, keyguard).
2922     */
2923    public static final int STATUS_BAR_DISABLE_RECENT = 0x01000000;
2924
2925    /**
2926     * @hide
2927     *
2928     * NOTE: This flag may only be used in subtreeSystemUiVisibility. It is masked
2929     * out of the public fields to keep the undefined bits out of the developer's way.
2930     *
2931     * Flag to disable the global search gesture. Don't use this
2932     * unless you're a special part of the system UI (i.e., setup wizard, keyguard).
2933     */
2934    public static final int STATUS_BAR_DISABLE_SEARCH = 0x02000000;
2935
2936    /**
2937     * @hide
2938     *
2939     * NOTE: This flag may only be used in subtreeSystemUiVisibility. It is masked
2940     * out of the public fields to keep the undefined bits out of the developer's way.
2941     *
2942     * Flag to specify that the status bar is displayed in transient mode.
2943     */
2944    public static final int STATUS_BAR_TRANSIENT = 0x04000000;
2945
2946    /**
2947     * @hide
2948     *
2949     * NOTE: This flag may only be used in subtreeSystemUiVisibility. It is masked
2950     * out of the public fields to keep the undefined bits out of the developer's way.
2951     *
2952     * Flag to specify that the navigation bar is displayed in transient mode.
2953     */
2954    public static final int NAVIGATION_BAR_TRANSIENT = 0x08000000;
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 specify that the hidden status bar would like to be shown.
2963     */
2964    public static final int STATUS_BAR_UNHIDE = 0x10000000;
2965
2966    /**
2967     * @hide
2968     *
2969     * NOTE: This flag may only be used in subtreeSystemUiVisibility. It is masked
2970     * out of the public fields to keep the undefined bits out of the developer's way.
2971     *
2972     * Flag to specify that the hidden navigation bar would like to be shown.
2973     */
2974    public static final int NAVIGATION_BAR_UNHIDE = 0x20000000;
2975
2976    /**
2977     * @hide
2978     *
2979     * NOTE: This flag may only be used in subtreeSystemUiVisibility. It is masked
2980     * out of the public fields to keep the undefined bits out of the developer's way.
2981     *
2982     * Flag to specify that the status bar is displayed in translucent mode.
2983     */
2984    public static final int STATUS_BAR_TRANSLUCENT = 0x40000000;
2985
2986    /**
2987     * @hide
2988     *
2989     * NOTE: This flag may only be used in subtreeSystemUiVisibility. It is masked
2990     * out of the public fields to keep the undefined bits out of the developer's way.
2991     *
2992     * Flag to specify that the navigation bar is displayed in translucent mode.
2993     */
2994    public static final int NAVIGATION_BAR_TRANSLUCENT = 0x80000000;
2995
2996    /**
2997     * @hide
2998     *
2999     * Whether Recents is visible or not.
3000     */
3001    public static final int RECENT_APPS_VISIBLE = 0x00004000;
3002
3003    /**
3004     * @hide
3005     *
3006     * Makes system ui transparent.
3007     */
3008    public static final int SYSTEM_UI_TRANSPARENT = 0x00008000;
3009
3010    /**
3011     * @hide
3012     */
3013    public static final int PUBLIC_STATUS_BAR_VISIBILITY_MASK = 0x00003FFF;
3014
3015    /**
3016     * These are the system UI flags that can be cleared by events outside
3017     * of an application.  Currently this is just the ability to tap on the
3018     * screen while hiding the navigation bar to have it return.
3019     * @hide
3020     */
3021    public static final int SYSTEM_UI_CLEARABLE_FLAGS =
3022            SYSTEM_UI_FLAG_LOW_PROFILE | SYSTEM_UI_FLAG_HIDE_NAVIGATION
3023            | SYSTEM_UI_FLAG_FULLSCREEN;
3024
3025    /**
3026     * Flags that can impact the layout in relation to system UI.
3027     */
3028    public static final int SYSTEM_UI_LAYOUT_FLAGS =
3029            SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION
3030            | SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN;
3031
3032    /** @hide */
3033    @IntDef(flag = true,
3034            value = { FIND_VIEWS_WITH_TEXT, FIND_VIEWS_WITH_CONTENT_DESCRIPTION })
3035    @Retention(RetentionPolicy.SOURCE)
3036    public @interface FindViewFlags {}
3037
3038    /**
3039     * Find views that render the specified text.
3040     *
3041     * @see #findViewsWithText(ArrayList, CharSequence, int)
3042     */
3043    public static final int FIND_VIEWS_WITH_TEXT = 0x00000001;
3044
3045    /**
3046     * Find find views that contain the specified content description.
3047     *
3048     * @see #findViewsWithText(ArrayList, CharSequence, int)
3049     */
3050    public static final int FIND_VIEWS_WITH_CONTENT_DESCRIPTION = 0x00000002;
3051
3052    /**
3053     * Find views that contain {@link AccessibilityNodeProvider}. Such
3054     * a View is a root of virtual view hierarchy and may contain the searched
3055     * text. If this flag is set Views with providers are automatically
3056     * added and it is a responsibility of the client to call the APIs of
3057     * the provider to determine whether the virtual tree rooted at this View
3058     * contains the text, i.e. getting the list of {@link AccessibilityNodeInfo}s
3059     * representing the virtual views with this text.
3060     *
3061     * @see #findViewsWithText(ArrayList, CharSequence, int)
3062     *
3063     * @hide
3064     */
3065    public static final int FIND_VIEWS_WITH_ACCESSIBILITY_NODE_PROVIDERS = 0x00000004;
3066
3067    /**
3068     * The undefined cursor position.
3069     *
3070     * @hide
3071     */
3072    public static final int ACCESSIBILITY_CURSOR_POSITION_UNDEFINED = -1;
3073
3074    /**
3075     * Indicates that the screen has changed state and is now off.
3076     *
3077     * @see #onScreenStateChanged(int)
3078     */
3079    public static final int SCREEN_STATE_OFF = 0x0;
3080
3081    /**
3082     * Indicates that the screen has changed state and is now on.
3083     *
3084     * @see #onScreenStateChanged(int)
3085     */
3086    public static final int SCREEN_STATE_ON = 0x1;
3087
3088    /**
3089     * Indicates no axis of view scrolling.
3090     */
3091    public static final int SCROLL_AXIS_NONE = 0;
3092
3093    /**
3094     * Indicates scrolling along the horizontal axis.
3095     */
3096    public static final int SCROLL_AXIS_HORIZONTAL = 1 << 0;
3097
3098    /**
3099     * Indicates scrolling along the vertical axis.
3100     */
3101    public static final int SCROLL_AXIS_VERTICAL = 1 << 1;
3102
3103    /**
3104     * Controls the over-scroll mode for this view.
3105     * See {@link #overScrollBy(int, int, int, int, int, int, int, int, boolean)},
3106     * {@link #OVER_SCROLL_ALWAYS}, {@link #OVER_SCROLL_IF_CONTENT_SCROLLS},
3107     * and {@link #OVER_SCROLL_NEVER}.
3108     */
3109    private int mOverScrollMode;
3110
3111    /**
3112     * The parent this view is attached to.
3113     * {@hide}
3114     *
3115     * @see #getParent()
3116     */
3117    protected ViewParent mParent;
3118
3119    /**
3120     * {@hide}
3121     */
3122    AttachInfo mAttachInfo;
3123
3124    /**
3125     * {@hide}
3126     */
3127    @ViewDebug.ExportedProperty(flagMapping = {
3128        @ViewDebug.FlagToString(mask = PFLAG_FORCE_LAYOUT, equals = PFLAG_FORCE_LAYOUT,
3129                name = "FORCE_LAYOUT"),
3130        @ViewDebug.FlagToString(mask = PFLAG_LAYOUT_REQUIRED, equals = PFLAG_LAYOUT_REQUIRED,
3131                name = "LAYOUT_REQUIRED"),
3132        @ViewDebug.FlagToString(mask = PFLAG_DRAWING_CACHE_VALID, equals = PFLAG_DRAWING_CACHE_VALID,
3133            name = "DRAWING_CACHE_INVALID", outputIf = false),
3134        @ViewDebug.FlagToString(mask = PFLAG_DRAWN, equals = PFLAG_DRAWN, name = "DRAWN", outputIf = true),
3135        @ViewDebug.FlagToString(mask = PFLAG_DRAWN, equals = PFLAG_DRAWN, name = "NOT_DRAWN", outputIf = false),
3136        @ViewDebug.FlagToString(mask = PFLAG_DIRTY_MASK, equals = PFLAG_DIRTY_OPAQUE, name = "DIRTY_OPAQUE"),
3137        @ViewDebug.FlagToString(mask = PFLAG_DIRTY_MASK, equals = PFLAG_DIRTY, name = "DIRTY")
3138    }, formatToHexString = true)
3139    int mPrivateFlags;
3140    int mPrivateFlags2;
3141    int mPrivateFlags3;
3142
3143    /**
3144     * This view's request for the visibility of the status bar.
3145     * @hide
3146     */
3147    @ViewDebug.ExportedProperty(flagMapping = {
3148        @ViewDebug.FlagToString(mask = SYSTEM_UI_FLAG_LOW_PROFILE,
3149                                equals = SYSTEM_UI_FLAG_LOW_PROFILE,
3150                                name = "SYSTEM_UI_FLAG_LOW_PROFILE", outputIf = true),
3151        @ViewDebug.FlagToString(mask = SYSTEM_UI_FLAG_HIDE_NAVIGATION,
3152                                equals = SYSTEM_UI_FLAG_HIDE_NAVIGATION,
3153                                name = "SYSTEM_UI_FLAG_HIDE_NAVIGATION", outputIf = true),
3154        @ViewDebug.FlagToString(mask = PUBLIC_STATUS_BAR_VISIBILITY_MASK,
3155                                equals = SYSTEM_UI_FLAG_VISIBLE,
3156                                name = "SYSTEM_UI_FLAG_VISIBLE", outputIf = true)
3157    }, formatToHexString = true)
3158    int mSystemUiVisibility;
3159
3160    /**
3161     * Reference count for transient state.
3162     * @see #setHasTransientState(boolean)
3163     */
3164    int mTransientStateCount = 0;
3165
3166    /**
3167     * Count of how many windows this view has been attached to.
3168     */
3169    int mWindowAttachCount;
3170
3171    /**
3172     * The layout parameters associated with this view and used by the parent
3173     * {@link android.view.ViewGroup} to determine how this view should be
3174     * laid out.
3175     * {@hide}
3176     */
3177    protected ViewGroup.LayoutParams mLayoutParams;
3178
3179    /**
3180     * The view flags hold various views states.
3181     * {@hide}
3182     */
3183    @ViewDebug.ExportedProperty(formatToHexString = true)
3184    int mViewFlags;
3185
3186    static class TransformationInfo {
3187        /**
3188         * The transform matrix for the View. This transform is calculated internally
3189         * based on the translation, rotation, and scale properties.
3190         *
3191         * Do *not* use this variable directly; instead call getMatrix(), which will
3192         * load the value from the View's RenderNode.
3193         */
3194        private final Matrix mMatrix = new Matrix();
3195
3196        /**
3197         * The inverse transform matrix for the View. This transform is calculated
3198         * internally based on the translation, rotation, and scale properties.
3199         *
3200         * Do *not* use this variable directly; instead call getInverseMatrix(),
3201         * which will load the value from the View's RenderNode.
3202         */
3203        private Matrix mInverseMatrix;
3204
3205        /**
3206         * The opacity of the View. This is a value from 0 to 1, where 0 means
3207         * completely transparent and 1 means completely opaque.
3208         */
3209        @ViewDebug.ExportedProperty
3210        float mAlpha = 1f;
3211
3212        /**
3213         * The opacity of the view as manipulated by the Fade transition. This is a hidden
3214         * property only used by transitions, which is composited with the other alpha
3215         * values to calculate the final visual alpha value.
3216         */
3217        float mTransitionAlpha = 1f;
3218    }
3219
3220    TransformationInfo mTransformationInfo;
3221
3222    /**
3223     * Current clip bounds. to which all drawing of this view are constrained.
3224     */
3225    Rect mClipBounds = null;
3226
3227    private boolean mLastIsOpaque;
3228
3229    /**
3230     * The distance in pixels from the left edge of this view's parent
3231     * to the left edge of this view.
3232     * {@hide}
3233     */
3234    @ViewDebug.ExportedProperty(category = "layout")
3235    protected int mLeft;
3236    /**
3237     * The distance in pixels from the left edge of this view's parent
3238     * to the right edge of this view.
3239     * {@hide}
3240     */
3241    @ViewDebug.ExportedProperty(category = "layout")
3242    protected int mRight;
3243    /**
3244     * The distance in pixels from the top edge of this view's parent
3245     * to the top edge of this view.
3246     * {@hide}
3247     */
3248    @ViewDebug.ExportedProperty(category = "layout")
3249    protected int mTop;
3250    /**
3251     * The distance in pixels from the top edge of this view's parent
3252     * to the bottom edge of this view.
3253     * {@hide}
3254     */
3255    @ViewDebug.ExportedProperty(category = "layout")
3256    protected int mBottom;
3257
3258    /**
3259     * The offset, in pixels, by which the content of this view is scrolled
3260     * horizontally.
3261     * {@hide}
3262     */
3263    @ViewDebug.ExportedProperty(category = "scrolling")
3264    protected int mScrollX;
3265    /**
3266     * The offset, in pixels, by which the content of this view is scrolled
3267     * vertically.
3268     * {@hide}
3269     */
3270    @ViewDebug.ExportedProperty(category = "scrolling")
3271    protected int mScrollY;
3272
3273    /**
3274     * The left padding in pixels, that is the distance in pixels between the
3275     * left edge of this view and the left edge of its content.
3276     * {@hide}
3277     */
3278    @ViewDebug.ExportedProperty(category = "padding")
3279    protected int mPaddingLeft = 0;
3280    /**
3281     * The right padding in pixels, that is the distance in pixels between the
3282     * right edge of this view and the right edge of its content.
3283     * {@hide}
3284     */
3285    @ViewDebug.ExportedProperty(category = "padding")
3286    protected int mPaddingRight = 0;
3287    /**
3288     * The top padding in pixels, that is the distance in pixels between the
3289     * top edge of this view and the top edge of its content.
3290     * {@hide}
3291     */
3292    @ViewDebug.ExportedProperty(category = "padding")
3293    protected int mPaddingTop;
3294    /**
3295     * The bottom padding in pixels, that is the distance in pixels between the
3296     * bottom edge of this view and the bottom edge of its content.
3297     * {@hide}
3298     */
3299    @ViewDebug.ExportedProperty(category = "padding")
3300    protected int mPaddingBottom;
3301
3302    /**
3303     * The layout insets in pixels, that is the distance in pixels between the
3304     * visible edges of this view its bounds.
3305     */
3306    private Insets mLayoutInsets;
3307
3308    /**
3309     * Briefly describes the view and is primarily used for accessibility support.
3310     */
3311    private CharSequence mContentDescription;
3312
3313    /**
3314     * Specifies the id of a view for which this view serves as a label for
3315     * accessibility purposes.
3316     */
3317    private int mLabelForId = View.NO_ID;
3318
3319    /**
3320     * Predicate for matching labeled view id with its label for
3321     * accessibility purposes.
3322     */
3323    private MatchLabelForPredicate mMatchLabelForPredicate;
3324
3325    /**
3326     * Specifies a view before which this one is visited in accessibility traversal.
3327     */
3328    private int mAccessibilityTraversalBeforeId = NO_ID;
3329
3330    /**
3331     * Specifies a view after which this one is visited in accessibility traversal.
3332     */
3333    private int mAccessibilityTraversalAfterId = NO_ID;
3334
3335    /**
3336     * Predicate for matching a view by its id.
3337     */
3338    private MatchIdPredicate mMatchIdPredicate;
3339
3340    /**
3341     * Cache the paddingRight set by the user to append to the scrollbar's size.
3342     *
3343     * @hide
3344     */
3345    @ViewDebug.ExportedProperty(category = "padding")
3346    protected int mUserPaddingRight;
3347
3348    /**
3349     * Cache the paddingBottom set by the user to append to the scrollbar's size.
3350     *
3351     * @hide
3352     */
3353    @ViewDebug.ExportedProperty(category = "padding")
3354    protected int mUserPaddingBottom;
3355
3356    /**
3357     * Cache the paddingLeft set by the user to append to the scrollbar's size.
3358     *
3359     * @hide
3360     */
3361    @ViewDebug.ExportedProperty(category = "padding")
3362    protected int mUserPaddingLeft;
3363
3364    /**
3365     * Cache the paddingStart set by the user to append to the scrollbar's size.
3366     *
3367     */
3368    @ViewDebug.ExportedProperty(category = "padding")
3369    int mUserPaddingStart;
3370
3371    /**
3372     * Cache the paddingEnd set by the user to append to the scrollbar's size.
3373     *
3374     */
3375    @ViewDebug.ExportedProperty(category = "padding")
3376    int mUserPaddingEnd;
3377
3378    /**
3379     * Cache initial left padding.
3380     *
3381     * @hide
3382     */
3383    int mUserPaddingLeftInitial;
3384
3385    /**
3386     * Cache initial right padding.
3387     *
3388     * @hide
3389     */
3390    int mUserPaddingRightInitial;
3391
3392    /**
3393     * Default undefined padding
3394     */
3395    private static final int UNDEFINED_PADDING = Integer.MIN_VALUE;
3396
3397    /**
3398     * Cache if a left padding has been defined
3399     */
3400    private boolean mLeftPaddingDefined = false;
3401
3402    /**
3403     * Cache if a right padding has been defined
3404     */
3405    private boolean mRightPaddingDefined = false;
3406
3407    /**
3408     * @hide
3409     */
3410    int mOldWidthMeasureSpec = Integer.MIN_VALUE;
3411    /**
3412     * @hide
3413     */
3414    int mOldHeightMeasureSpec = Integer.MIN_VALUE;
3415
3416    private LongSparseLongArray mMeasureCache;
3417
3418    @ViewDebug.ExportedProperty(deepExport = true, prefix = "bg_")
3419    private Drawable mBackground;
3420    private TintInfo mBackgroundTint;
3421
3422    @ViewDebug.ExportedProperty(deepExport = true, prefix = "fg_")
3423    private ForegroundInfo mForegroundInfo;
3424
3425    private Drawable mScrollIndicatorDrawable;
3426
3427    /**
3428     * RenderNode used for backgrounds.
3429     * <p>
3430     * When non-null and valid, this is expected to contain an up-to-date copy
3431     * of the background drawable. It is cleared on temporary detach, and reset
3432     * on cleanup.
3433     */
3434    private RenderNode mBackgroundRenderNode;
3435
3436    private int mBackgroundResource;
3437    private boolean mBackgroundSizeChanged;
3438
3439    private String mTransitionName;
3440
3441    static class TintInfo {
3442        ColorStateList mTintList;
3443        PorterDuff.Mode mTintMode;
3444        boolean mHasTintMode;
3445        boolean mHasTintList;
3446    }
3447
3448    private static class ForegroundInfo {
3449        private Drawable mDrawable;
3450        private TintInfo mTintInfo;
3451        private int mGravity = Gravity.FILL;
3452        private boolean mInsidePadding = true;
3453        private boolean mBoundsChanged = true;
3454        private final Rect mSelfBounds = new Rect();
3455        private final Rect mOverlayBounds = new Rect();
3456    }
3457
3458    static class ListenerInfo {
3459        /**
3460         * Listener used to dispatch focus change events.
3461         * This field should be made private, so it is hidden from the SDK.
3462         * {@hide}
3463         */
3464        protected OnFocusChangeListener mOnFocusChangeListener;
3465
3466        /**
3467         * Listeners for layout change events.
3468         */
3469        private ArrayList<OnLayoutChangeListener> mOnLayoutChangeListeners;
3470
3471        protected OnScrollChangeListener mOnScrollChangeListener;
3472
3473        /**
3474         * Listeners for attach events.
3475         */
3476        private CopyOnWriteArrayList<OnAttachStateChangeListener> mOnAttachStateChangeListeners;
3477
3478        /**
3479         * Listener used to dispatch click events.
3480         * This field should be made private, so it is hidden from the SDK.
3481         * {@hide}
3482         */
3483        public OnClickListener mOnClickListener;
3484
3485        /**
3486         * Listener used to dispatch long click events.
3487         * This field should be made private, so it is hidden from the SDK.
3488         * {@hide}
3489         */
3490        protected OnLongClickListener mOnLongClickListener;
3491
3492        /**
3493         * Listener used to dispatch context click events. This field should be made private, so it
3494         * is hidden from the SDK.
3495         * {@hide}
3496         */
3497        protected OnContextClickListener mOnContextClickListener;
3498
3499        /**
3500         * Listener used to build the context menu.
3501         * This field should be made private, so it is hidden from the SDK.
3502         * {@hide}
3503         */
3504        protected OnCreateContextMenuListener mOnCreateContextMenuListener;
3505
3506        private OnKeyListener mOnKeyListener;
3507
3508        private OnTouchListener mOnTouchListener;
3509
3510        private OnHoverListener mOnHoverListener;
3511
3512        private OnGenericMotionListener mOnGenericMotionListener;
3513
3514        private OnDragListener mOnDragListener;
3515
3516        private OnSystemUiVisibilityChangeListener mOnSystemUiVisibilityChangeListener;
3517
3518        OnApplyWindowInsetsListener mOnApplyWindowInsetsListener;
3519    }
3520
3521    ListenerInfo mListenerInfo;
3522
3523    /**
3524     * The application environment this view lives in.
3525     * This field should be made private, so it is hidden from the SDK.
3526     * {@hide}
3527     */
3528    @ViewDebug.ExportedProperty(deepExport = true)
3529    protected Context mContext;
3530
3531    private final Resources mResources;
3532
3533    private ScrollabilityCache mScrollCache;
3534
3535    private int[] mDrawableState = null;
3536
3537    ViewOutlineProvider mOutlineProvider = ViewOutlineProvider.BACKGROUND;
3538
3539    /**
3540     * Animator that automatically runs based on state changes.
3541     */
3542    private StateListAnimator mStateListAnimator;
3543
3544    /**
3545     * When this view has focus and the next focus is {@link #FOCUS_LEFT},
3546     * the user may specify which view to go to next.
3547     */
3548    private int mNextFocusLeftId = View.NO_ID;
3549
3550    /**
3551     * When this view has focus and the next focus is {@link #FOCUS_RIGHT},
3552     * the user may specify which view to go to next.
3553     */
3554    private int mNextFocusRightId = View.NO_ID;
3555
3556    /**
3557     * When this view has focus and the next focus is {@link #FOCUS_UP},
3558     * the user may specify which view to go to next.
3559     */
3560    private int mNextFocusUpId = View.NO_ID;
3561
3562    /**
3563     * When this view has focus and the next focus is {@link #FOCUS_DOWN},
3564     * the user may specify which view to go to next.
3565     */
3566    private int mNextFocusDownId = View.NO_ID;
3567
3568    /**
3569     * When this view has focus and the next focus is {@link #FOCUS_FORWARD},
3570     * the user may specify which view to go to next.
3571     */
3572    int mNextFocusForwardId = View.NO_ID;
3573
3574    private CheckForLongPress mPendingCheckForLongPress;
3575    private CheckForTap mPendingCheckForTap = null;
3576    private PerformClick mPerformClick;
3577    private SendViewScrolledAccessibilityEvent mSendViewScrolledAccessibilityEvent;
3578
3579    private UnsetPressedState mUnsetPressedState;
3580
3581    /**
3582     * Whether the long press's action has been invoked.  The tap's action is invoked on the
3583     * up event while a long press is invoked as soon as the long press duration is reached, so
3584     * a long press could be performed before the tap is checked, in which case the tap's action
3585     * should not be invoked.
3586     */
3587    private boolean mHasPerformedLongPress;
3588
3589    /**
3590     * Whether a context click button is currently pressed down. This is true when the stylus is
3591     * touching the screen and the primary button has been pressed, or if a mouse's right button is
3592     * pressed. This is false once the button is released or if the stylus has been lifted.
3593     */
3594    private boolean mInContextButtonPress;
3595
3596    /**
3597     * Whether the next up event should be ignored for the purposes of gesture recognition. This is
3598     * true after a stylus button press has occured, when the next up event should not be recognized
3599     * as a tap.
3600     */
3601    private boolean mIgnoreNextUpEvent;
3602
3603    /**
3604     * The minimum height of the view. We'll try our best to have the height
3605     * of this view to at least this amount.
3606     */
3607    @ViewDebug.ExportedProperty(category = "measurement")
3608    private int mMinHeight;
3609
3610    /**
3611     * The minimum width of the view. We'll try our best to have the width
3612     * of this view to at least this amount.
3613     */
3614    @ViewDebug.ExportedProperty(category = "measurement")
3615    private int mMinWidth;
3616
3617    /**
3618     * The delegate to handle touch events that are physically in this view
3619     * but should be handled by another view.
3620     */
3621    private TouchDelegate mTouchDelegate = null;
3622
3623    /**
3624     * Solid color to use as a background when creating the drawing cache. Enables
3625     * the cache to use 16 bit bitmaps instead of 32 bit.
3626     */
3627    private int mDrawingCacheBackgroundColor = 0;
3628
3629    /**
3630     * Special tree observer used when mAttachInfo is null.
3631     */
3632    private ViewTreeObserver mFloatingTreeObserver;
3633
3634    /**
3635     * Cache the touch slop from the context that created the view.
3636     */
3637    private int mTouchSlop;
3638
3639    /**
3640     * Object that handles automatic animation of view properties.
3641     */
3642    private ViewPropertyAnimator mAnimator = null;
3643
3644    /**
3645     * Flag indicating that a drag can cross window boundaries.  When
3646     * {@link #startDrag(ClipData, DragShadowBuilder, Object, int)} is called
3647     * with this flag set, all visible applications will be able to participate
3648     * in the drag operation and receive the dragged content.
3649     *
3650     * If this is the only flag set, then the drag recipient will only have access to text data
3651     * and intents contained in the {@link ClipData} object. Access to URIs contained in the
3652     * {@link ClipData} is determined by other DRAG_FLAG_GLOBAL_* flags.
3653     */
3654    public static final int DRAG_FLAG_GLOBAL = 1 << 8;  // 256
3655
3656    /**
3657     * When this flag is used with {@link #DRAG_FLAG_GLOBAL}, the drag recipient will be able to
3658     * request read access to the content URI(s) contained in the {@link ClipData} object.
3659     * @see android.content.Intent.FLAG_GRANT_READ_URI_PERMISSION
3660     */
3661    public static final int DRAG_FLAG_GLOBAL_URI_READ = Intent.FLAG_GRANT_READ_URI_PERMISSION;
3662
3663    /**
3664     * When this flag is used with {@link #DRAG_FLAG_GLOBAL}, the drag recipient will be able to
3665     * request write access to the content URI(s) contained in the {@link ClipData} object.
3666     * @see android.content.Intent.FLAG_GRANT_WRITE_URI_PERMISSION
3667     */
3668    public static final int DRAG_FLAG_GLOBAL_URI_WRITE = Intent.FLAG_GRANT_WRITE_URI_PERMISSION;
3669
3670    /**
3671     * When this flag is used with {@link #DRAG_FLAG_GLOBAL_URI_READ} and/or {@link
3672     * #DRAG_FLAG_GLOBAL_URI_WRITE}, the URI permission grant can be persisted across device
3673     * reboots until explicitly revoked with
3674     * {@link android.content.Context#revokeUriPermission(Uri,int) Context.revokeUriPermission}.
3675     * @see android.content.Intent.FLAG_GRANT_PERSISTABLE_URI_PERMISSION
3676     */
3677    public static final int DRAG_FLAG_GLOBAL_PERSISTABLE_URI_PERMISSION =
3678            Intent.FLAG_GRANT_PERSISTABLE_URI_PERMISSION;
3679
3680    /**
3681     * When this flag is used with {@link #DRAG_FLAG_GLOBAL_URI_READ} and/or {@link
3682     * #DRAG_FLAG_GLOBAL_URI_WRITE}, the URI permission grant applies to any URI that is a prefix
3683     * match against the original granted URI.
3684     * @see android.content.Intent.FLAG_GRANT_PREFIX_URI_PERMISSION
3685     */
3686    public static final int DRAG_FLAG_GLOBAL_PREFIX_URI_PERMISSION =
3687            Intent.FLAG_GRANT_PREFIX_URI_PERMISSION;
3688
3689    /**
3690     * Flag indicating that the drag shadow will be opaque.  When
3691     * {@link #startDrag(ClipData, DragShadowBuilder, Object, int)} is called
3692     * with this flag set, the drag shadow will be opaque, otherwise, it will be semitransparent.
3693     */
3694    public static final int DRAG_FLAG_OPAQUE = 1 << 9;
3695
3696    /**
3697     * Vertical scroll factor cached by {@link #getVerticalScrollFactor}.
3698     */
3699    private float mVerticalScrollFactor;
3700
3701    /**
3702     * Position of the vertical scroll bar.
3703     */
3704    private int mVerticalScrollbarPosition;
3705
3706    /**
3707     * Position the scroll bar at the default position as determined by the system.
3708     */
3709    public static final int SCROLLBAR_POSITION_DEFAULT = 0;
3710
3711    /**
3712     * Position the scroll bar along the left edge.
3713     */
3714    public static final int SCROLLBAR_POSITION_LEFT = 1;
3715
3716    /**
3717     * Position the scroll bar along the right edge.
3718     */
3719    public static final int SCROLLBAR_POSITION_RIGHT = 2;
3720
3721    /**
3722     * Indicates that the view does not have a layer.
3723     *
3724     * @see #getLayerType()
3725     * @see #setLayerType(int, android.graphics.Paint)
3726     * @see #LAYER_TYPE_SOFTWARE
3727     * @see #LAYER_TYPE_HARDWARE
3728     */
3729    public static final int LAYER_TYPE_NONE = 0;
3730
3731    /**
3732     * <p>Indicates that the view has a software layer. A software layer is backed
3733     * by a bitmap and causes the view to be rendered using Android's software
3734     * rendering pipeline, even if hardware acceleration is enabled.</p>
3735     *
3736     * <p>Software layers have various usages:</p>
3737     * <p>When the application is not using hardware acceleration, a software layer
3738     * is useful to apply a specific color filter and/or blending mode and/or
3739     * translucency to a view and all its children.</p>
3740     * <p>When the application is using hardware acceleration, a software layer
3741     * is useful to render drawing primitives not supported by the hardware
3742     * accelerated pipeline. It can also be used to cache a complex view tree
3743     * into a texture and reduce the complexity of drawing operations. For instance,
3744     * when animating a complex view tree with a translation, a software layer can
3745     * be used to render the view tree only once.</p>
3746     * <p>Software layers should be avoided when the affected view tree updates
3747     * often. Every update will require to re-render the software layer, which can
3748     * potentially be slow (particularly when hardware acceleration is turned on
3749     * since the layer will have to be uploaded into a hardware texture after every
3750     * update.)</p>
3751     *
3752     * @see #getLayerType()
3753     * @see #setLayerType(int, android.graphics.Paint)
3754     * @see #LAYER_TYPE_NONE
3755     * @see #LAYER_TYPE_HARDWARE
3756     */
3757    public static final int LAYER_TYPE_SOFTWARE = 1;
3758
3759    /**
3760     * <p>Indicates that the view has a hardware layer. A hardware layer is backed
3761     * by a hardware specific texture (generally Frame Buffer Objects or FBO on
3762     * OpenGL hardware) and causes the view to be rendered using Android's hardware
3763     * rendering pipeline, but only if hardware acceleration is turned on for the
3764     * view hierarchy. When hardware acceleration is turned off, hardware layers
3765     * behave exactly as {@link #LAYER_TYPE_SOFTWARE software layers}.</p>
3766     *
3767     * <p>A hardware layer is useful to apply a specific color filter and/or
3768     * blending mode and/or translucency to a view and all its children.</p>
3769     * <p>A hardware layer can be used to cache a complex view tree into a
3770     * texture and reduce the complexity of drawing operations. For instance,
3771     * when animating a complex view tree with a translation, a hardware layer can
3772     * be used to render the view tree only once.</p>
3773     * <p>A hardware layer can also be used to increase the rendering quality when
3774     * rotation transformations are applied on a view. It can also be used to
3775     * prevent potential clipping issues when applying 3D transforms on a view.</p>
3776     *
3777     * @see #getLayerType()
3778     * @see #setLayerType(int, android.graphics.Paint)
3779     * @see #LAYER_TYPE_NONE
3780     * @see #LAYER_TYPE_SOFTWARE
3781     */
3782    public static final int LAYER_TYPE_HARDWARE = 2;
3783
3784    @ViewDebug.ExportedProperty(category = "drawing", mapping = {
3785            @ViewDebug.IntToString(from = LAYER_TYPE_NONE, to = "NONE"),
3786            @ViewDebug.IntToString(from = LAYER_TYPE_SOFTWARE, to = "SOFTWARE"),
3787            @ViewDebug.IntToString(from = LAYER_TYPE_HARDWARE, to = "HARDWARE")
3788    })
3789    int mLayerType = LAYER_TYPE_NONE;
3790    Paint mLayerPaint;
3791
3792    /**
3793     * Set to true when drawing cache is enabled and cannot be created.
3794     *
3795     * @hide
3796     */
3797    public boolean mCachingFailed;
3798    private Bitmap mDrawingCache;
3799    private Bitmap mUnscaledDrawingCache;
3800
3801    /**
3802     * RenderNode holding View properties, potentially holding a DisplayList of View content.
3803     * <p>
3804     * When non-null and valid, this is expected to contain an up-to-date copy
3805     * of the View content. Its DisplayList content is cleared on temporary detach and reset on
3806     * cleanup.
3807     */
3808    final RenderNode mRenderNode;
3809
3810    /**
3811     * Set to true when the view is sending hover accessibility events because it
3812     * is the innermost hovered view.
3813     */
3814    private boolean mSendingHoverAccessibilityEvents;
3815
3816    /**
3817     * Delegate for injecting accessibility functionality.
3818     */
3819    AccessibilityDelegate mAccessibilityDelegate;
3820
3821    /**
3822     * The view's overlay layer. Developers get a reference to the overlay via getOverlay()
3823     * and add/remove objects to/from the overlay directly through the Overlay methods.
3824     */
3825    ViewOverlay mOverlay;
3826
3827    /**
3828     * The currently active parent view for receiving delegated nested scrolling events.
3829     * This is set by {@link #startNestedScroll(int)} during a touch interaction and cleared
3830     * by {@link #stopNestedScroll()} at the same point where we clear
3831     * requestDisallowInterceptTouchEvent.
3832     */
3833    private ViewParent mNestedScrollingParent;
3834
3835    /**
3836     * Consistency verifier for debugging purposes.
3837     * @hide
3838     */
3839    protected final InputEventConsistencyVerifier mInputEventConsistencyVerifier =
3840            InputEventConsistencyVerifier.isInstrumentationEnabled() ?
3841                    new InputEventConsistencyVerifier(this, 0) : null;
3842
3843    private static final AtomicInteger sNextGeneratedId = new AtomicInteger(1);
3844
3845    private int[] mTempNestedScrollConsumed;
3846
3847    /**
3848     * An overlay is going to draw this View instead of being drawn as part of this
3849     * View's parent. mGhostView is the View in the Overlay that must be invalidated
3850     * when this view is invalidated.
3851     */
3852    GhostView mGhostView;
3853
3854    /**
3855     * Holds pairs of adjacent attribute data: attribute name followed by its value.
3856     * @hide
3857     */
3858    @ViewDebug.ExportedProperty(category = "attributes", hasAdjacentMapping = true)
3859    public String[] mAttributes;
3860
3861    /**
3862     * Maps a Resource id to its name.
3863     */
3864    private static SparseArray<String> mAttributeMap;
3865
3866    /**
3867     * Queue of pending runnables. Used to postpone calls to post() until this
3868     * view is attached and has a handler.
3869     */
3870    private HandlerActionQueue mRunQueue;
3871
3872    /**
3873     * @hide
3874     */
3875    String mStartActivityRequestWho;
3876
3877    /**
3878     * Simple constructor to use when creating a view from code.
3879     *
3880     * @param context The Context the view is running in, through which it can
3881     *        access the current theme, resources, etc.
3882     */
3883    public View(Context context) {
3884        mContext = context;
3885        mResources = context != null ? context.getResources() : null;
3886        mViewFlags = SOUND_EFFECTS_ENABLED | HAPTIC_FEEDBACK_ENABLED;
3887        // Set some flags defaults
3888        mPrivateFlags2 =
3889                (LAYOUT_DIRECTION_DEFAULT << PFLAG2_LAYOUT_DIRECTION_MASK_SHIFT) |
3890                (TEXT_DIRECTION_DEFAULT << PFLAG2_TEXT_DIRECTION_MASK_SHIFT) |
3891                (PFLAG2_TEXT_DIRECTION_RESOLVED_DEFAULT) |
3892                (TEXT_ALIGNMENT_DEFAULT << PFLAG2_TEXT_ALIGNMENT_MASK_SHIFT) |
3893                (PFLAG2_TEXT_ALIGNMENT_RESOLVED_DEFAULT) |
3894                (IMPORTANT_FOR_ACCESSIBILITY_DEFAULT << PFLAG2_IMPORTANT_FOR_ACCESSIBILITY_SHIFT);
3895        mTouchSlop = ViewConfiguration.get(context).getScaledTouchSlop();
3896        setOverScrollMode(OVER_SCROLL_IF_CONTENT_SCROLLS);
3897        mUserPaddingStart = UNDEFINED_PADDING;
3898        mUserPaddingEnd = UNDEFINED_PADDING;
3899        mRenderNode = RenderNode.create(getClass().getName(), this);
3900
3901        if (!sCompatibilityDone && context != null) {
3902            final int targetSdkVersion = context.getApplicationInfo().targetSdkVersion;
3903
3904            // Older apps may need this compatibility hack for measurement.
3905            sUseBrokenMakeMeasureSpec = targetSdkVersion <= JELLY_BEAN_MR1;
3906
3907            // Older apps expect onMeasure() to always be called on a layout pass, regardless
3908            // of whether a layout was requested on that View.
3909            sIgnoreMeasureCache = targetSdkVersion < KITKAT;
3910
3911            Canvas.sCompatibilityRestore = targetSdkVersion < M;
3912
3913            // In M and newer, our widgets can pass a "hint" value in the size
3914            // for UNSPECIFIED MeasureSpecs. This lets child views of scrolling containers
3915            // know what the expected parent size is going to be, so e.g. list items can size
3916            // themselves at 1/3 the size of their container. It breaks older apps though,
3917            // specifically apps that use some popular open source libraries.
3918            sUseZeroUnspecifiedMeasureSpec = targetSdkVersion < M;
3919
3920            // Old versions of the platform would give different results from
3921            // LinearLayout measurement passes using EXACTLY and non-EXACTLY
3922            // modes, so we always need to run an additional EXACTLY pass.
3923            sAlwaysRemeasureExactly = targetSdkVersion <= M;
3924
3925            sCompatibilityDone = true;
3926        }
3927    }
3928
3929    /**
3930     * Constructor that is called when inflating a view from XML. This is called
3931     * when a view is being constructed from an XML file, supplying attributes
3932     * that were specified in the XML file. This version uses a default style of
3933     * 0, so the only attribute values applied are those in the Context's Theme
3934     * and the given AttributeSet.
3935     *
3936     * <p>
3937     * The method onFinishInflate() will be called after all children have been
3938     * added.
3939     *
3940     * @param context The Context the view is running in, through which it can
3941     *        access the current theme, resources, etc.
3942     * @param attrs The attributes of the XML tag that is inflating the view.
3943     * @see #View(Context, AttributeSet, int)
3944     */
3945    public View(Context context, @Nullable AttributeSet attrs) {
3946        this(context, attrs, 0);
3947    }
3948
3949    /**
3950     * Perform inflation from XML and apply a class-specific base style from a
3951     * theme attribute. This constructor of View allows subclasses to use their
3952     * own base style when they are inflating. For example, a Button class's
3953     * constructor would call this version of the super class constructor and
3954     * supply <code>R.attr.buttonStyle</code> for <var>defStyleAttr</var>; this
3955     * allows the theme's button style to modify all of the base view attributes
3956     * (in particular its background) as well as the Button class's attributes.
3957     *
3958     * @param context The Context the view is running in, through which it can
3959     *        access the current theme, resources, etc.
3960     * @param attrs The attributes of the XML tag that is inflating the view.
3961     * @param defStyleAttr An attribute in the current theme that contains a
3962     *        reference to a style resource that supplies default values for
3963     *        the view. Can be 0 to not look for defaults.
3964     * @see #View(Context, AttributeSet)
3965     */
3966    public View(Context context, @Nullable AttributeSet attrs, int defStyleAttr) {
3967        this(context, attrs, defStyleAttr, 0);
3968    }
3969
3970    /**
3971     * Perform inflation from XML and apply a class-specific base style from a
3972     * theme attribute or style resource. This constructor of View allows
3973     * subclasses to use their own base style when they are inflating.
3974     * <p>
3975     * When determining the final value of a particular attribute, there are
3976     * four inputs that come into play:
3977     * <ol>
3978     * <li>Any attribute values in the given AttributeSet.
3979     * <li>The style resource specified in the AttributeSet (named "style").
3980     * <li>The default style specified by <var>defStyleAttr</var>.
3981     * <li>The default style specified by <var>defStyleRes</var>.
3982     * <li>The base values in this theme.
3983     * </ol>
3984     * <p>
3985     * Each of these inputs is considered in-order, with the first listed taking
3986     * precedence over the following ones. In other words, if in the
3987     * AttributeSet you have supplied <code>&lt;Button * textColor="#ff000000"&gt;</code>
3988     * , then the button's text will <em>always</em> be black, regardless of
3989     * what is specified in any of the styles.
3990     *
3991     * @param context The Context the view is running in, through which it can
3992     *        access the current theme, resources, etc.
3993     * @param attrs The attributes of the XML tag that is inflating the view.
3994     * @param defStyleAttr An attribute in the current theme that contains a
3995     *        reference to a style resource that supplies default values for
3996     *        the view. Can be 0 to not look for defaults.
3997     * @param defStyleRes A resource identifier of a style resource that
3998     *        supplies default values for the view, used only if
3999     *        defStyleAttr is 0 or can not be found in the theme. Can be 0
4000     *        to not look for defaults.
4001     * @see #View(Context, AttributeSet, int)
4002     */
4003    public View(Context context, @Nullable AttributeSet attrs, int defStyleAttr, int defStyleRes) {
4004        this(context);
4005
4006        final TypedArray a = context.obtainStyledAttributes(
4007                attrs, com.android.internal.R.styleable.View, defStyleAttr, defStyleRes);
4008
4009        if (mDebugViewAttributes) {
4010            saveAttributeData(attrs, a);
4011        }
4012
4013        Drawable background = null;
4014
4015        int leftPadding = -1;
4016        int topPadding = -1;
4017        int rightPadding = -1;
4018        int bottomPadding = -1;
4019        int startPadding = UNDEFINED_PADDING;
4020        int endPadding = UNDEFINED_PADDING;
4021
4022        int padding = -1;
4023
4024        int viewFlagValues = 0;
4025        int viewFlagMasks = 0;
4026
4027        boolean setScrollContainer = false;
4028
4029        int x = 0;
4030        int y = 0;
4031
4032        float tx = 0;
4033        float ty = 0;
4034        float tz = 0;
4035        float elevation = 0;
4036        float rotation = 0;
4037        float rotationX = 0;
4038        float rotationY = 0;
4039        float sx = 1f;
4040        float sy = 1f;
4041        boolean transformSet = false;
4042
4043        int scrollbarStyle = SCROLLBARS_INSIDE_OVERLAY;
4044        int overScrollMode = mOverScrollMode;
4045        boolean initializeScrollbars = false;
4046        boolean initializeScrollIndicators = false;
4047
4048        boolean startPaddingDefined = false;
4049        boolean endPaddingDefined = false;
4050        boolean leftPaddingDefined = false;
4051        boolean rightPaddingDefined = false;
4052
4053        final int targetSdkVersion = context.getApplicationInfo().targetSdkVersion;
4054
4055        final int N = a.getIndexCount();
4056        for (int i = 0; i < N; i++) {
4057            int attr = a.getIndex(i);
4058            switch (attr) {
4059                case com.android.internal.R.styleable.View_background:
4060                    background = a.getDrawable(attr);
4061                    break;
4062                case com.android.internal.R.styleable.View_padding:
4063                    padding = a.getDimensionPixelSize(attr, -1);
4064                    mUserPaddingLeftInitial = padding;
4065                    mUserPaddingRightInitial = padding;
4066                    leftPaddingDefined = true;
4067                    rightPaddingDefined = true;
4068                    break;
4069                 case com.android.internal.R.styleable.View_paddingLeft:
4070                    leftPadding = a.getDimensionPixelSize(attr, -1);
4071                    mUserPaddingLeftInitial = leftPadding;
4072                    leftPaddingDefined = true;
4073                    break;
4074                case com.android.internal.R.styleable.View_paddingTop:
4075                    topPadding = a.getDimensionPixelSize(attr, -1);
4076                    break;
4077                case com.android.internal.R.styleable.View_paddingRight:
4078                    rightPadding = a.getDimensionPixelSize(attr, -1);
4079                    mUserPaddingRightInitial = rightPadding;
4080                    rightPaddingDefined = true;
4081                    break;
4082                case com.android.internal.R.styleable.View_paddingBottom:
4083                    bottomPadding = a.getDimensionPixelSize(attr, -1);
4084                    break;
4085                case com.android.internal.R.styleable.View_paddingStart:
4086                    startPadding = a.getDimensionPixelSize(attr, UNDEFINED_PADDING);
4087                    startPaddingDefined = (startPadding != UNDEFINED_PADDING);
4088                    break;
4089                case com.android.internal.R.styleable.View_paddingEnd:
4090                    endPadding = a.getDimensionPixelSize(attr, UNDEFINED_PADDING);
4091                    endPaddingDefined = (endPadding != UNDEFINED_PADDING);
4092                    break;
4093                case com.android.internal.R.styleable.View_scrollX:
4094                    x = a.getDimensionPixelOffset(attr, 0);
4095                    break;
4096                case com.android.internal.R.styleable.View_scrollY:
4097                    y = a.getDimensionPixelOffset(attr, 0);
4098                    break;
4099                case com.android.internal.R.styleable.View_alpha:
4100                    setAlpha(a.getFloat(attr, 1f));
4101                    break;
4102                case com.android.internal.R.styleable.View_transformPivotX:
4103                    setPivotX(a.getDimensionPixelOffset(attr, 0));
4104                    break;
4105                case com.android.internal.R.styleable.View_transformPivotY:
4106                    setPivotY(a.getDimensionPixelOffset(attr, 0));
4107                    break;
4108                case com.android.internal.R.styleable.View_translationX:
4109                    tx = a.getDimensionPixelOffset(attr, 0);
4110                    transformSet = true;
4111                    break;
4112                case com.android.internal.R.styleable.View_translationY:
4113                    ty = a.getDimensionPixelOffset(attr, 0);
4114                    transformSet = true;
4115                    break;
4116                case com.android.internal.R.styleable.View_translationZ:
4117                    tz = a.getDimensionPixelOffset(attr, 0);
4118                    transformSet = true;
4119                    break;
4120                case com.android.internal.R.styleable.View_elevation:
4121                    elevation = a.getDimensionPixelOffset(attr, 0);
4122                    transformSet = true;
4123                    break;
4124                case com.android.internal.R.styleable.View_rotation:
4125                    rotation = a.getFloat(attr, 0);
4126                    transformSet = true;
4127                    break;
4128                case com.android.internal.R.styleable.View_rotationX:
4129                    rotationX = a.getFloat(attr, 0);
4130                    transformSet = true;
4131                    break;
4132                case com.android.internal.R.styleable.View_rotationY:
4133                    rotationY = a.getFloat(attr, 0);
4134                    transformSet = true;
4135                    break;
4136                case com.android.internal.R.styleable.View_scaleX:
4137                    sx = a.getFloat(attr, 1f);
4138                    transformSet = true;
4139                    break;
4140                case com.android.internal.R.styleable.View_scaleY:
4141                    sy = a.getFloat(attr, 1f);
4142                    transformSet = true;
4143                    break;
4144                case com.android.internal.R.styleable.View_id:
4145                    mID = a.getResourceId(attr, NO_ID);
4146                    break;
4147                case com.android.internal.R.styleable.View_tag:
4148                    mTag = a.getText(attr);
4149                    break;
4150                case com.android.internal.R.styleable.View_fitsSystemWindows:
4151                    if (a.getBoolean(attr, false)) {
4152                        viewFlagValues |= FITS_SYSTEM_WINDOWS;
4153                        viewFlagMasks |= FITS_SYSTEM_WINDOWS;
4154                    }
4155                    break;
4156                case com.android.internal.R.styleable.View_focusable:
4157                    if (a.getBoolean(attr, false)) {
4158                        viewFlagValues |= FOCUSABLE;
4159                        viewFlagMasks |= FOCUSABLE_MASK;
4160                    }
4161                    break;
4162                case com.android.internal.R.styleable.View_focusableInTouchMode:
4163                    if (a.getBoolean(attr, false)) {
4164                        viewFlagValues |= FOCUSABLE_IN_TOUCH_MODE | FOCUSABLE;
4165                        viewFlagMasks |= FOCUSABLE_IN_TOUCH_MODE | FOCUSABLE_MASK;
4166                    }
4167                    break;
4168                case com.android.internal.R.styleable.View_clickable:
4169                    if (a.getBoolean(attr, false)) {
4170                        viewFlagValues |= CLICKABLE;
4171                        viewFlagMasks |= CLICKABLE;
4172                    }
4173                    break;
4174                case com.android.internal.R.styleable.View_longClickable:
4175                    if (a.getBoolean(attr, false)) {
4176                        viewFlagValues |= LONG_CLICKABLE;
4177                        viewFlagMasks |= LONG_CLICKABLE;
4178                    }
4179                    break;
4180                case com.android.internal.R.styleable.View_contextClickable:
4181                    if (a.getBoolean(attr, false)) {
4182                        viewFlagValues |= CONTEXT_CLICKABLE;
4183                        viewFlagMasks |= CONTEXT_CLICKABLE;
4184                    }
4185                    break;
4186                case com.android.internal.R.styleable.View_saveEnabled:
4187                    if (!a.getBoolean(attr, true)) {
4188                        viewFlagValues |= SAVE_DISABLED;
4189                        viewFlagMasks |= SAVE_DISABLED_MASK;
4190                    }
4191                    break;
4192                case com.android.internal.R.styleable.View_duplicateParentState:
4193                    if (a.getBoolean(attr, false)) {
4194                        viewFlagValues |= DUPLICATE_PARENT_STATE;
4195                        viewFlagMasks |= DUPLICATE_PARENT_STATE;
4196                    }
4197                    break;
4198                case com.android.internal.R.styleable.View_visibility:
4199                    final int visibility = a.getInt(attr, 0);
4200                    if (visibility != 0) {
4201                        viewFlagValues |= VISIBILITY_FLAGS[visibility];
4202                        viewFlagMasks |= VISIBILITY_MASK;
4203                    }
4204                    break;
4205                case com.android.internal.R.styleable.View_layoutDirection:
4206                    // Clear any layout direction flags (included resolved bits) already set
4207                    mPrivateFlags2 &=
4208                            ~(PFLAG2_LAYOUT_DIRECTION_MASK | PFLAG2_LAYOUT_DIRECTION_RESOLVED_MASK);
4209                    // Set the layout direction flags depending on the value of the attribute
4210                    final int layoutDirection = a.getInt(attr, -1);
4211                    final int value = (layoutDirection != -1) ?
4212                            LAYOUT_DIRECTION_FLAGS[layoutDirection] : LAYOUT_DIRECTION_DEFAULT;
4213                    mPrivateFlags2 |= (value << PFLAG2_LAYOUT_DIRECTION_MASK_SHIFT);
4214                    break;
4215                case com.android.internal.R.styleable.View_drawingCacheQuality:
4216                    final int cacheQuality = a.getInt(attr, 0);
4217                    if (cacheQuality != 0) {
4218                        viewFlagValues |= DRAWING_CACHE_QUALITY_FLAGS[cacheQuality];
4219                        viewFlagMasks |= DRAWING_CACHE_QUALITY_MASK;
4220                    }
4221                    break;
4222                case com.android.internal.R.styleable.View_contentDescription:
4223                    setContentDescription(a.getString(attr));
4224                    break;
4225                case com.android.internal.R.styleable.View_accessibilityTraversalBefore:
4226                    setAccessibilityTraversalBefore(a.getResourceId(attr, NO_ID));
4227                    break;
4228                case com.android.internal.R.styleable.View_accessibilityTraversalAfter:
4229                    setAccessibilityTraversalAfter(a.getResourceId(attr, NO_ID));
4230                    break;
4231                case com.android.internal.R.styleable.View_labelFor:
4232                    setLabelFor(a.getResourceId(attr, NO_ID));
4233                    break;
4234                case com.android.internal.R.styleable.View_soundEffectsEnabled:
4235                    if (!a.getBoolean(attr, true)) {
4236                        viewFlagValues &= ~SOUND_EFFECTS_ENABLED;
4237                        viewFlagMasks |= SOUND_EFFECTS_ENABLED;
4238                    }
4239                    break;
4240                case com.android.internal.R.styleable.View_hapticFeedbackEnabled:
4241                    if (!a.getBoolean(attr, true)) {
4242                        viewFlagValues &= ~HAPTIC_FEEDBACK_ENABLED;
4243                        viewFlagMasks |= HAPTIC_FEEDBACK_ENABLED;
4244                    }
4245                    break;
4246                case R.styleable.View_scrollbars:
4247                    final int scrollbars = a.getInt(attr, SCROLLBARS_NONE);
4248                    if (scrollbars != SCROLLBARS_NONE) {
4249                        viewFlagValues |= scrollbars;
4250                        viewFlagMasks |= SCROLLBARS_MASK;
4251                        initializeScrollbars = true;
4252                    }
4253                    break;
4254                //noinspection deprecation
4255                case R.styleable.View_fadingEdge:
4256                    if (targetSdkVersion >= ICE_CREAM_SANDWICH) {
4257                        // Ignore the attribute starting with ICS
4258                        break;
4259                    }
4260                    // With builds < ICS, fall through and apply fading edges
4261                case R.styleable.View_requiresFadingEdge:
4262                    final int fadingEdge = a.getInt(attr, FADING_EDGE_NONE);
4263                    if (fadingEdge != FADING_EDGE_NONE) {
4264                        viewFlagValues |= fadingEdge;
4265                        viewFlagMasks |= FADING_EDGE_MASK;
4266                        initializeFadingEdgeInternal(a);
4267                    }
4268                    break;
4269                case R.styleable.View_scrollbarStyle:
4270                    scrollbarStyle = a.getInt(attr, SCROLLBARS_INSIDE_OVERLAY);
4271                    if (scrollbarStyle != SCROLLBARS_INSIDE_OVERLAY) {
4272                        viewFlagValues |= scrollbarStyle & SCROLLBARS_STYLE_MASK;
4273                        viewFlagMasks |= SCROLLBARS_STYLE_MASK;
4274                    }
4275                    break;
4276                case R.styleable.View_isScrollContainer:
4277                    setScrollContainer = true;
4278                    if (a.getBoolean(attr, false)) {
4279                        setScrollContainer(true);
4280                    }
4281                    break;
4282                case com.android.internal.R.styleable.View_keepScreenOn:
4283                    if (a.getBoolean(attr, false)) {
4284                        viewFlagValues |= KEEP_SCREEN_ON;
4285                        viewFlagMasks |= KEEP_SCREEN_ON;
4286                    }
4287                    break;
4288                case R.styleable.View_filterTouchesWhenObscured:
4289                    if (a.getBoolean(attr, false)) {
4290                        viewFlagValues |= FILTER_TOUCHES_WHEN_OBSCURED;
4291                        viewFlagMasks |= FILTER_TOUCHES_WHEN_OBSCURED;
4292                    }
4293                    break;
4294                case R.styleable.View_nextFocusLeft:
4295                    mNextFocusLeftId = a.getResourceId(attr, View.NO_ID);
4296                    break;
4297                case R.styleable.View_nextFocusRight:
4298                    mNextFocusRightId = a.getResourceId(attr, View.NO_ID);
4299                    break;
4300                case R.styleable.View_nextFocusUp:
4301                    mNextFocusUpId = a.getResourceId(attr, View.NO_ID);
4302                    break;
4303                case R.styleable.View_nextFocusDown:
4304                    mNextFocusDownId = a.getResourceId(attr, View.NO_ID);
4305                    break;
4306                case R.styleable.View_nextFocusForward:
4307                    mNextFocusForwardId = a.getResourceId(attr, View.NO_ID);
4308                    break;
4309                case R.styleable.View_minWidth:
4310                    mMinWidth = a.getDimensionPixelSize(attr, 0);
4311                    break;
4312                case R.styleable.View_minHeight:
4313                    mMinHeight = a.getDimensionPixelSize(attr, 0);
4314                    break;
4315                case R.styleable.View_onClick:
4316                    if (context.isRestricted()) {
4317                        throw new IllegalStateException("The android:onClick attribute cannot "
4318                                + "be used within a restricted context");
4319                    }
4320
4321                    final String handlerName = a.getString(attr);
4322                    if (handlerName != null) {
4323                        setOnClickListener(new DeclaredOnClickListener(this, handlerName));
4324                    }
4325                    break;
4326                case R.styleable.View_overScrollMode:
4327                    overScrollMode = a.getInt(attr, OVER_SCROLL_IF_CONTENT_SCROLLS);
4328                    break;
4329                case R.styleable.View_verticalScrollbarPosition:
4330                    mVerticalScrollbarPosition = a.getInt(attr, SCROLLBAR_POSITION_DEFAULT);
4331                    break;
4332                case R.styleable.View_layerType:
4333                    setLayerType(a.getInt(attr, LAYER_TYPE_NONE), null);
4334                    break;
4335                case R.styleable.View_textDirection:
4336                    // Clear any text direction flag already set
4337                    mPrivateFlags2 &= ~PFLAG2_TEXT_DIRECTION_MASK;
4338                    // Set the text direction flags depending on the value of the attribute
4339                    final int textDirection = a.getInt(attr, -1);
4340                    if (textDirection != -1) {
4341                        mPrivateFlags2 |= PFLAG2_TEXT_DIRECTION_FLAGS[textDirection];
4342                    }
4343                    break;
4344                case R.styleable.View_textAlignment:
4345                    // Clear any text alignment flag already set
4346                    mPrivateFlags2 &= ~PFLAG2_TEXT_ALIGNMENT_MASK;
4347                    // Set the text alignment flag depending on the value of the attribute
4348                    final int textAlignment = a.getInt(attr, TEXT_ALIGNMENT_DEFAULT);
4349                    mPrivateFlags2 |= PFLAG2_TEXT_ALIGNMENT_FLAGS[textAlignment];
4350                    break;
4351                case R.styleable.View_importantForAccessibility:
4352                    setImportantForAccessibility(a.getInt(attr,
4353                            IMPORTANT_FOR_ACCESSIBILITY_DEFAULT));
4354                    break;
4355                case R.styleable.View_accessibilityLiveRegion:
4356                    setAccessibilityLiveRegion(a.getInt(attr, ACCESSIBILITY_LIVE_REGION_DEFAULT));
4357                    break;
4358                case R.styleable.View_transitionName:
4359                    setTransitionName(a.getString(attr));
4360                    break;
4361                case R.styleable.View_nestedScrollingEnabled:
4362                    setNestedScrollingEnabled(a.getBoolean(attr, false));
4363                    break;
4364                case R.styleable.View_stateListAnimator:
4365                    setStateListAnimator(AnimatorInflater.loadStateListAnimator(context,
4366                            a.getResourceId(attr, 0)));
4367                    break;
4368                case R.styleable.View_backgroundTint:
4369                    // This will get applied later during setBackground().
4370                    if (mBackgroundTint == null) {
4371                        mBackgroundTint = new TintInfo();
4372                    }
4373                    mBackgroundTint.mTintList = a.getColorStateList(
4374                            R.styleable.View_backgroundTint);
4375                    mBackgroundTint.mHasTintList = true;
4376                    break;
4377                case R.styleable.View_backgroundTintMode:
4378                    // This will get applied later during setBackground().
4379                    if (mBackgroundTint == null) {
4380                        mBackgroundTint = new TintInfo();
4381                    }
4382                    mBackgroundTint.mTintMode = Drawable.parseTintMode(a.getInt(
4383                            R.styleable.View_backgroundTintMode, -1), null);
4384                    mBackgroundTint.mHasTintMode = true;
4385                    break;
4386                case R.styleable.View_outlineProvider:
4387                    setOutlineProviderFromAttribute(a.getInt(R.styleable.View_outlineProvider,
4388                            PROVIDER_BACKGROUND));
4389                    break;
4390                case R.styleable.View_foreground:
4391                    if (targetSdkVersion >= VERSION_CODES.M || this instanceof FrameLayout) {
4392                        setForeground(a.getDrawable(attr));
4393                    }
4394                    break;
4395                case R.styleable.View_foregroundGravity:
4396                    if (targetSdkVersion >= VERSION_CODES.M || this instanceof FrameLayout) {
4397                        setForegroundGravity(a.getInt(attr, Gravity.NO_GRAVITY));
4398                    }
4399                    break;
4400                case R.styleable.View_foregroundTintMode:
4401                    if (targetSdkVersion >= VERSION_CODES.M || this instanceof FrameLayout) {
4402                        setForegroundTintMode(Drawable.parseTintMode(a.getInt(attr, -1), null));
4403                    }
4404                    break;
4405                case R.styleable.View_foregroundTint:
4406                    if (targetSdkVersion >= VERSION_CODES.M || this instanceof FrameLayout) {
4407                        setForegroundTintList(a.getColorStateList(attr));
4408                    }
4409                    break;
4410                case R.styleable.View_foregroundInsidePadding:
4411                    if (targetSdkVersion >= VERSION_CODES.M || this instanceof FrameLayout) {
4412                        if (mForegroundInfo == null) {
4413                            mForegroundInfo = new ForegroundInfo();
4414                        }
4415                        mForegroundInfo.mInsidePadding = a.getBoolean(attr,
4416                                mForegroundInfo.mInsidePadding);
4417                    }
4418                    break;
4419                case R.styleable.View_scrollIndicators:
4420                    final int scrollIndicators =
4421                            (a.getInt(attr, 0) << SCROLL_INDICATORS_TO_PFLAGS3_LSHIFT)
4422                                    & SCROLL_INDICATORS_PFLAG3_MASK;
4423                    if (scrollIndicators != 0) {
4424                        mPrivateFlags3 |= scrollIndicators;
4425                        initializeScrollIndicators = true;
4426                    }
4427                    break;
4428            }
4429        }
4430
4431        setOverScrollMode(overScrollMode);
4432
4433        // Cache start/end user padding as we cannot fully resolve padding here (we dont have yet
4434        // the resolved layout direction). Those cached values will be used later during padding
4435        // resolution.
4436        mUserPaddingStart = startPadding;
4437        mUserPaddingEnd = endPadding;
4438
4439        if (background != null) {
4440            setBackground(background);
4441        }
4442
4443        // setBackground above will record that padding is currently provided by the background.
4444        // If we have padding specified via xml, record that here instead and use it.
4445        mLeftPaddingDefined = leftPaddingDefined;
4446        mRightPaddingDefined = rightPaddingDefined;
4447
4448        if (padding >= 0) {
4449            leftPadding = padding;
4450            topPadding = padding;
4451            rightPadding = padding;
4452            bottomPadding = padding;
4453            mUserPaddingLeftInitial = padding;
4454            mUserPaddingRightInitial = padding;
4455        }
4456
4457        if (isRtlCompatibilityMode()) {
4458            // RTL compatibility mode: pre Jelly Bean MR1 case OR no RTL support case.
4459            // left / right padding are used if defined (meaning here nothing to do). If they are not
4460            // defined and start / end padding are defined (e.g. in Frameworks resources), then we use
4461            // start / end and resolve them as left / right (layout direction is not taken into account).
4462            // Padding from the background drawable is stored at this point in mUserPaddingLeftInitial
4463            // and mUserPaddingRightInitial) so drawable padding will be used as ultimate default if
4464            // defined.
4465            if (!mLeftPaddingDefined && startPaddingDefined) {
4466                leftPadding = startPadding;
4467            }
4468            mUserPaddingLeftInitial = (leftPadding >= 0) ? leftPadding : mUserPaddingLeftInitial;
4469            if (!mRightPaddingDefined && endPaddingDefined) {
4470                rightPadding = endPadding;
4471            }
4472            mUserPaddingRightInitial = (rightPadding >= 0) ? rightPadding : mUserPaddingRightInitial;
4473        } else {
4474            // Jelly Bean MR1 and after case: if start/end defined, they will override any left/right
4475            // values defined. Otherwise, left /right values are used.
4476            // Padding from the background drawable is stored at this point in mUserPaddingLeftInitial
4477            // and mUserPaddingRightInitial) so drawable padding will be used as ultimate default if
4478            // defined.
4479            final boolean hasRelativePadding = startPaddingDefined || endPaddingDefined;
4480
4481            if (mLeftPaddingDefined && !hasRelativePadding) {
4482                mUserPaddingLeftInitial = leftPadding;
4483            }
4484            if (mRightPaddingDefined && !hasRelativePadding) {
4485                mUserPaddingRightInitial = rightPadding;
4486            }
4487        }
4488
4489        internalSetPadding(
4490                mUserPaddingLeftInitial,
4491                topPadding >= 0 ? topPadding : mPaddingTop,
4492                mUserPaddingRightInitial,
4493                bottomPadding >= 0 ? bottomPadding : mPaddingBottom);
4494
4495        if (viewFlagMasks != 0) {
4496            setFlags(viewFlagValues, viewFlagMasks);
4497        }
4498
4499        if (initializeScrollbars) {
4500            initializeScrollbarsInternal(a);
4501        }
4502
4503        if (initializeScrollIndicators) {
4504            initializeScrollIndicatorsInternal();
4505        }
4506
4507        a.recycle();
4508
4509        // Needs to be called after mViewFlags is set
4510        if (scrollbarStyle != SCROLLBARS_INSIDE_OVERLAY) {
4511            recomputePadding();
4512        }
4513
4514        if (x != 0 || y != 0) {
4515            scrollTo(x, y);
4516        }
4517
4518        if (transformSet) {
4519            setTranslationX(tx);
4520            setTranslationY(ty);
4521            setTranslationZ(tz);
4522            setElevation(elevation);
4523            setRotation(rotation);
4524            setRotationX(rotationX);
4525            setRotationY(rotationY);
4526            setScaleX(sx);
4527            setScaleY(sy);
4528        }
4529
4530        if (!setScrollContainer && (viewFlagValues&SCROLLBARS_VERTICAL) != 0) {
4531            setScrollContainer(true);
4532        }
4533
4534        computeOpaqueFlags();
4535    }
4536
4537    /**
4538     * An implementation of OnClickListener that attempts to lazily load a
4539     * named click handling method from a parent or ancestor context.
4540     */
4541    private static class DeclaredOnClickListener implements OnClickListener {
4542        private final View mHostView;
4543        private final String mMethodName;
4544
4545        private Method mResolvedMethod;
4546        private Context mResolvedContext;
4547
4548        public DeclaredOnClickListener(@NonNull View hostView, @NonNull String methodName) {
4549            mHostView = hostView;
4550            mMethodName = methodName;
4551        }
4552
4553        @Override
4554        public void onClick(@NonNull View v) {
4555            if (mResolvedMethod == null) {
4556                resolveMethod(mHostView.getContext(), mMethodName);
4557            }
4558
4559            try {
4560                mResolvedMethod.invoke(mResolvedContext, v);
4561            } catch (IllegalAccessException e) {
4562                throw new IllegalStateException(
4563                        "Could not execute non-public method for android:onClick", e);
4564            } catch (InvocationTargetException e) {
4565                throw new IllegalStateException(
4566                        "Could not execute method for android:onClick", e);
4567            }
4568        }
4569
4570        @NonNull
4571        private void resolveMethod(@Nullable Context context, @NonNull String name) {
4572            while (context != null) {
4573                try {
4574                    if (!context.isRestricted()) {
4575                        final Method method = context.getClass().getMethod(mMethodName, View.class);
4576                        if (method != null) {
4577                            mResolvedMethod = method;
4578                            mResolvedContext = context;
4579                            return;
4580                        }
4581                    }
4582                } catch (NoSuchMethodException e) {
4583                    // Failed to find method, keep searching up the hierarchy.
4584                }
4585
4586                if (context instanceof ContextWrapper) {
4587                    context = ((ContextWrapper) context).getBaseContext();
4588                } else {
4589                    // Can't search up the hierarchy, null out and fail.
4590                    context = null;
4591                }
4592            }
4593
4594            final int id = mHostView.getId();
4595            final String idText = id == NO_ID ? "" : " with id '"
4596                    + mHostView.getContext().getResources().getResourceEntryName(id) + "'";
4597            throw new IllegalStateException("Could not find method " + mMethodName
4598                    + "(View) in a parent or ancestor Context for android:onClick "
4599                    + "attribute defined on view " + mHostView.getClass() + idText);
4600        }
4601    }
4602
4603    /**
4604     * Non-public constructor for use in testing
4605     */
4606    View() {
4607        mResources = null;
4608        mRenderNode = RenderNode.create(getClass().getName(), this);
4609    }
4610
4611    private static SparseArray<String> getAttributeMap() {
4612        if (mAttributeMap == null) {
4613            mAttributeMap = new SparseArray<>();
4614        }
4615        return mAttributeMap;
4616    }
4617
4618    private void saveAttributeData(@Nullable AttributeSet attrs, @NonNull TypedArray t) {
4619        final int attrsCount = attrs == null ? 0 : attrs.getAttributeCount();
4620        final int indexCount = t.getIndexCount();
4621        final String[] attributes = new String[(attrsCount + indexCount) * 2];
4622
4623        int i = 0;
4624
4625        // Store raw XML attributes.
4626        for (int j = 0; j < attrsCount; ++j) {
4627            attributes[i] = attrs.getAttributeName(j);
4628            attributes[i + 1] = attrs.getAttributeValue(j);
4629            i += 2;
4630        }
4631
4632        // Store resolved styleable attributes.
4633        final Resources res = t.getResources();
4634        final SparseArray<String> attributeMap = getAttributeMap();
4635        for (int j = 0; j < indexCount; ++j) {
4636            final int index = t.getIndex(j);
4637            if (!t.hasValueOrEmpty(index)) {
4638                // Value is undefined. Skip it.
4639                continue;
4640            }
4641
4642            final int resourceId = t.getResourceId(index, 0);
4643            if (resourceId == 0) {
4644                // Value is not a reference. Skip it.
4645                continue;
4646            }
4647
4648            String resourceName = attributeMap.get(resourceId);
4649            if (resourceName == null) {
4650                try {
4651                    resourceName = res.getResourceName(resourceId);
4652                } catch (Resources.NotFoundException e) {
4653                    resourceName = "0x" + Integer.toHexString(resourceId);
4654                }
4655                attributeMap.put(resourceId, resourceName);
4656            }
4657
4658            attributes[i] = resourceName;
4659            attributes[i + 1] = t.getString(index);
4660            i += 2;
4661        }
4662
4663        // Trim to fit contents.
4664        final String[] trimmed = new String[i];
4665        System.arraycopy(attributes, 0, trimmed, 0, i);
4666        mAttributes = trimmed;
4667    }
4668
4669    public String toString() {
4670        StringBuilder out = new StringBuilder(128);
4671        out.append(getClass().getName());
4672        out.append('{');
4673        out.append(Integer.toHexString(System.identityHashCode(this)));
4674        out.append(' ');
4675        switch (mViewFlags&VISIBILITY_MASK) {
4676            case VISIBLE: out.append('V'); break;
4677            case INVISIBLE: out.append('I'); break;
4678            case GONE: out.append('G'); break;
4679            default: out.append('.'); break;
4680        }
4681        out.append((mViewFlags&FOCUSABLE_MASK) == FOCUSABLE ? 'F' : '.');
4682        out.append((mViewFlags&ENABLED_MASK) == ENABLED ? 'E' : '.');
4683        out.append((mViewFlags&DRAW_MASK) == WILL_NOT_DRAW ? '.' : 'D');
4684        out.append((mViewFlags&SCROLLBARS_HORIZONTAL) != 0 ? 'H' : '.');
4685        out.append((mViewFlags&SCROLLBARS_VERTICAL) != 0 ? 'V' : '.');
4686        out.append((mViewFlags&CLICKABLE) != 0 ? 'C' : '.');
4687        out.append((mViewFlags&LONG_CLICKABLE) != 0 ? 'L' : '.');
4688        out.append((mViewFlags&CONTEXT_CLICKABLE) != 0 ? 'X' : '.');
4689        out.append(' ');
4690        out.append((mPrivateFlags&PFLAG_IS_ROOT_NAMESPACE) != 0 ? 'R' : '.');
4691        out.append((mPrivateFlags&PFLAG_FOCUSED) != 0 ? 'F' : '.');
4692        out.append((mPrivateFlags&PFLAG_SELECTED) != 0 ? 'S' : '.');
4693        if ((mPrivateFlags&PFLAG_PREPRESSED) != 0) {
4694            out.append('p');
4695        } else {
4696            out.append((mPrivateFlags&PFLAG_PRESSED) != 0 ? 'P' : '.');
4697        }
4698        out.append((mPrivateFlags&PFLAG_HOVERED) != 0 ? 'H' : '.');
4699        out.append((mPrivateFlags&PFLAG_ACTIVATED) != 0 ? 'A' : '.');
4700        out.append((mPrivateFlags&PFLAG_INVALIDATED) != 0 ? 'I' : '.');
4701        out.append((mPrivateFlags&PFLAG_DIRTY_MASK) != 0 ? 'D' : '.');
4702        out.append(' ');
4703        out.append(mLeft);
4704        out.append(',');
4705        out.append(mTop);
4706        out.append('-');
4707        out.append(mRight);
4708        out.append(',');
4709        out.append(mBottom);
4710        final int id = getId();
4711        if (id != NO_ID) {
4712            out.append(" #");
4713            out.append(Integer.toHexString(id));
4714            final Resources r = mResources;
4715            if (id > 0 && Resources.resourceHasPackage(id) && r != null) {
4716                try {
4717                    String pkgname;
4718                    switch (id&0xff000000) {
4719                        case 0x7f000000:
4720                            pkgname="app";
4721                            break;
4722                        case 0x01000000:
4723                            pkgname="android";
4724                            break;
4725                        default:
4726                            pkgname = r.getResourcePackageName(id);
4727                            break;
4728                    }
4729                    String typename = r.getResourceTypeName(id);
4730                    String entryname = r.getResourceEntryName(id);
4731                    out.append(" ");
4732                    out.append(pkgname);
4733                    out.append(":");
4734                    out.append(typename);
4735                    out.append("/");
4736                    out.append(entryname);
4737                } catch (Resources.NotFoundException e) {
4738                }
4739            }
4740        }
4741        out.append("}");
4742        return out.toString();
4743    }
4744
4745    /**
4746     * <p>
4747     * Initializes the fading edges from a given set of styled attributes. This
4748     * method should be called by subclasses that need fading edges and when an
4749     * instance of these subclasses is created programmatically rather than
4750     * being inflated from XML. This method is automatically called when the XML
4751     * is inflated.
4752     * </p>
4753     *
4754     * @param a the styled attributes set to initialize the fading edges from
4755     *
4756     * @removed
4757     */
4758    protected void initializeFadingEdge(TypedArray a) {
4759        // This method probably shouldn't have been included in the SDK to begin with.
4760        // It relies on 'a' having been initialized using an attribute filter array that is
4761        // not publicly available to the SDK. The old method has been renamed
4762        // to initializeFadingEdgeInternal and hidden for framework use only;
4763        // this one initializes using defaults to make it safe to call for apps.
4764
4765        TypedArray arr = mContext.obtainStyledAttributes(com.android.internal.R.styleable.View);
4766
4767        initializeFadingEdgeInternal(arr);
4768
4769        arr.recycle();
4770    }
4771
4772    /**
4773     * <p>
4774     * Initializes the fading edges from a given set of styled attributes. This
4775     * method should be called by subclasses that need fading edges and when an
4776     * instance of these subclasses is created programmatically rather than
4777     * being inflated from XML. This method is automatically called when the XML
4778     * is inflated.
4779     * </p>
4780     *
4781     * @param a the styled attributes set to initialize the fading edges from
4782     * @hide This is the real method; the public one is shimmed to be safe to call from apps.
4783     */
4784    protected void initializeFadingEdgeInternal(TypedArray a) {
4785        initScrollCache();
4786
4787        mScrollCache.fadingEdgeLength = a.getDimensionPixelSize(
4788                R.styleable.View_fadingEdgeLength,
4789                ViewConfiguration.get(mContext).getScaledFadingEdgeLength());
4790    }
4791
4792    /**
4793     * Returns the size of the vertical faded edges used to indicate that more
4794     * content in this view is visible.
4795     *
4796     * @return The size in pixels of the vertical faded edge or 0 if vertical
4797     *         faded edges are not enabled for this view.
4798     * @attr ref android.R.styleable#View_fadingEdgeLength
4799     */
4800    public int getVerticalFadingEdgeLength() {
4801        if (isVerticalFadingEdgeEnabled()) {
4802            ScrollabilityCache cache = mScrollCache;
4803            if (cache != null) {
4804                return cache.fadingEdgeLength;
4805            }
4806        }
4807        return 0;
4808    }
4809
4810    /**
4811     * Set the size of the faded edge used to indicate that more content in this
4812     * view is available.  Will not change whether the fading edge is enabled; use
4813     * {@link #setVerticalFadingEdgeEnabled(boolean)} or
4814     * {@link #setHorizontalFadingEdgeEnabled(boolean)} to enable the fading edge
4815     * for the vertical or horizontal fading edges.
4816     *
4817     * @param length The size in pixels of the faded edge used to indicate that more
4818     *        content in this view is visible.
4819     */
4820    public void setFadingEdgeLength(int length) {
4821        initScrollCache();
4822        mScrollCache.fadingEdgeLength = length;
4823    }
4824
4825    /**
4826     * Returns the size of the horizontal faded edges used to indicate that more
4827     * content in this view is visible.
4828     *
4829     * @return The size in pixels of the horizontal faded edge or 0 if horizontal
4830     *         faded edges are not enabled for this view.
4831     * @attr ref android.R.styleable#View_fadingEdgeLength
4832     */
4833    public int getHorizontalFadingEdgeLength() {
4834        if (isHorizontalFadingEdgeEnabled()) {
4835            ScrollabilityCache cache = mScrollCache;
4836            if (cache != null) {
4837                return cache.fadingEdgeLength;
4838            }
4839        }
4840        return 0;
4841    }
4842
4843    /**
4844     * Returns the width of the vertical scrollbar.
4845     *
4846     * @return The width in pixels of the vertical scrollbar or 0 if there
4847     *         is no vertical scrollbar.
4848     */
4849    public int getVerticalScrollbarWidth() {
4850        ScrollabilityCache cache = mScrollCache;
4851        if (cache != null) {
4852            ScrollBarDrawable scrollBar = cache.scrollBar;
4853            if (scrollBar != null) {
4854                int size = scrollBar.getSize(true);
4855                if (size <= 0) {
4856                    size = cache.scrollBarSize;
4857                }
4858                return size;
4859            }
4860            return 0;
4861        }
4862        return 0;
4863    }
4864
4865    /**
4866     * Returns the height of the horizontal scrollbar.
4867     *
4868     * @return The height in pixels of the horizontal scrollbar or 0 if
4869     *         there is no horizontal scrollbar.
4870     */
4871    protected int getHorizontalScrollbarHeight() {
4872        ScrollabilityCache cache = mScrollCache;
4873        if (cache != null) {
4874            ScrollBarDrawable scrollBar = cache.scrollBar;
4875            if (scrollBar != null) {
4876                int size = scrollBar.getSize(false);
4877                if (size <= 0) {
4878                    size = cache.scrollBarSize;
4879                }
4880                return size;
4881            }
4882            return 0;
4883        }
4884        return 0;
4885    }
4886
4887    /**
4888     * <p>
4889     * Initializes the scrollbars from a given set of styled attributes. This
4890     * method should be called by subclasses that need scrollbars and when an
4891     * instance of these subclasses is created programmatically rather than
4892     * being inflated from XML. This method is automatically called when the XML
4893     * is inflated.
4894     * </p>
4895     *
4896     * @param a the styled attributes set to initialize the scrollbars from
4897     *
4898     * @removed
4899     */
4900    protected void initializeScrollbars(TypedArray a) {
4901        // It's not safe to use this method from apps. The parameter 'a' must have been obtained
4902        // using the View filter array which is not available to the SDK. As such, internal
4903        // framework usage now uses initializeScrollbarsInternal and we grab a default
4904        // TypedArray with the right filter instead here.
4905        TypedArray arr = mContext.obtainStyledAttributes(com.android.internal.R.styleable.View);
4906
4907        initializeScrollbarsInternal(arr);
4908
4909        // We ignored the method parameter. Recycle the one we actually did use.
4910        arr.recycle();
4911    }
4912
4913    /**
4914     * <p>
4915     * Initializes the scrollbars from a given set of styled attributes. This
4916     * method should be called by subclasses that need scrollbars and when an
4917     * instance of these subclasses is created programmatically rather than
4918     * being inflated from XML. This method is automatically called when the XML
4919     * is inflated.
4920     * </p>
4921     *
4922     * @param a the styled attributes set to initialize the scrollbars from
4923     * @hide
4924     */
4925    protected void initializeScrollbarsInternal(TypedArray a) {
4926        initScrollCache();
4927
4928        final ScrollabilityCache scrollabilityCache = mScrollCache;
4929
4930        if (scrollabilityCache.scrollBar == null) {
4931            scrollabilityCache.scrollBar = new ScrollBarDrawable();
4932            scrollabilityCache.scrollBar.setCallback(this);
4933            scrollabilityCache.scrollBar.setState(getDrawableState());
4934        }
4935
4936        final boolean fadeScrollbars = a.getBoolean(R.styleable.View_fadeScrollbars, true);
4937
4938        if (!fadeScrollbars) {
4939            scrollabilityCache.state = ScrollabilityCache.ON;
4940        }
4941        scrollabilityCache.fadeScrollBars = fadeScrollbars;
4942
4943
4944        scrollabilityCache.scrollBarFadeDuration = a.getInt(
4945                R.styleable.View_scrollbarFadeDuration, ViewConfiguration
4946                        .getScrollBarFadeDuration());
4947        scrollabilityCache.scrollBarDefaultDelayBeforeFade = a.getInt(
4948                R.styleable.View_scrollbarDefaultDelayBeforeFade,
4949                ViewConfiguration.getScrollDefaultDelay());
4950
4951
4952        scrollabilityCache.scrollBarSize = a.getDimensionPixelSize(
4953                com.android.internal.R.styleable.View_scrollbarSize,
4954                ViewConfiguration.get(mContext).getScaledScrollBarSize());
4955
4956        Drawable track = a.getDrawable(R.styleable.View_scrollbarTrackHorizontal);
4957        scrollabilityCache.scrollBar.setHorizontalTrackDrawable(track);
4958
4959        Drawable thumb = a.getDrawable(R.styleable.View_scrollbarThumbHorizontal);
4960        if (thumb != null) {
4961            scrollabilityCache.scrollBar.setHorizontalThumbDrawable(thumb);
4962        }
4963
4964        boolean alwaysDraw = a.getBoolean(R.styleable.View_scrollbarAlwaysDrawHorizontalTrack,
4965                false);
4966        if (alwaysDraw) {
4967            scrollabilityCache.scrollBar.setAlwaysDrawHorizontalTrack(true);
4968        }
4969
4970        track = a.getDrawable(R.styleable.View_scrollbarTrackVertical);
4971        scrollabilityCache.scrollBar.setVerticalTrackDrawable(track);
4972
4973        thumb = a.getDrawable(R.styleable.View_scrollbarThumbVertical);
4974        if (thumb != null) {
4975            scrollabilityCache.scrollBar.setVerticalThumbDrawable(thumb);
4976        }
4977
4978        alwaysDraw = a.getBoolean(R.styleable.View_scrollbarAlwaysDrawVerticalTrack,
4979                false);
4980        if (alwaysDraw) {
4981            scrollabilityCache.scrollBar.setAlwaysDrawVerticalTrack(true);
4982        }
4983
4984        // Apply layout direction to the new Drawables if needed
4985        final int layoutDirection = getLayoutDirection();
4986        if (track != null) {
4987            track.setLayoutDirection(layoutDirection);
4988        }
4989        if (thumb != null) {
4990            thumb.setLayoutDirection(layoutDirection);
4991        }
4992
4993        // Re-apply user/background padding so that scrollbar(s) get added
4994        resolvePadding();
4995    }
4996
4997    private void initializeScrollIndicatorsInternal() {
4998        // Some day maybe we'll break this into top/left/start/etc. and let the
4999        // client control it. Until then, you can have any scroll indicator you
5000        // want as long as it's a 1dp foreground-colored rectangle.
5001        if (mScrollIndicatorDrawable == null) {
5002            mScrollIndicatorDrawable = mContext.getDrawable(R.drawable.scroll_indicator_material);
5003        }
5004    }
5005
5006    /**
5007     * <p>
5008     * Initalizes the scrollability cache if necessary.
5009     * </p>
5010     */
5011    private void initScrollCache() {
5012        if (mScrollCache == null) {
5013            mScrollCache = new ScrollabilityCache(ViewConfiguration.get(mContext), this);
5014        }
5015    }
5016
5017    private ScrollabilityCache getScrollCache() {
5018        initScrollCache();
5019        return mScrollCache;
5020    }
5021
5022    /**
5023     * Set the position of the vertical scroll bar. Should be one of
5024     * {@link #SCROLLBAR_POSITION_DEFAULT}, {@link #SCROLLBAR_POSITION_LEFT} or
5025     * {@link #SCROLLBAR_POSITION_RIGHT}.
5026     *
5027     * @param position Where the vertical scroll bar should be positioned.
5028     */
5029    public void setVerticalScrollbarPosition(int position) {
5030        if (mVerticalScrollbarPosition != position) {
5031            mVerticalScrollbarPosition = position;
5032            computeOpaqueFlags();
5033            resolvePadding();
5034        }
5035    }
5036
5037    /**
5038     * @return The position where the vertical scroll bar will show, if applicable.
5039     * @see #setVerticalScrollbarPosition(int)
5040     */
5041    public int getVerticalScrollbarPosition() {
5042        return mVerticalScrollbarPosition;
5043    }
5044
5045    /**
5046     * Sets the state of all scroll indicators.
5047     * <p>
5048     * See {@link #setScrollIndicators(int, int)} for usage information.
5049     *
5050     * @param indicators a bitmask of indicators that should be enabled, or
5051     *                   {@code 0} to disable all indicators
5052     * @see #setScrollIndicators(int, int)
5053     * @see #getScrollIndicators()
5054     * @attr ref android.R.styleable#View_scrollIndicators
5055     */
5056    public void setScrollIndicators(@ScrollIndicators int indicators) {
5057        setScrollIndicators(indicators,
5058                SCROLL_INDICATORS_PFLAG3_MASK >>> SCROLL_INDICATORS_TO_PFLAGS3_LSHIFT);
5059    }
5060
5061    /**
5062     * Sets the state of the scroll indicators specified by the mask. To change
5063     * all scroll indicators at once, see {@link #setScrollIndicators(int)}.
5064     * <p>
5065     * When a scroll indicator is enabled, it will be displayed if the view
5066     * can scroll in the direction of the indicator.
5067     * <p>
5068     * Multiple indicator types may be enabled or disabled by passing the
5069     * logical OR of the desired types. If multiple types are specified, they
5070     * will all be set to the same enabled state.
5071     * <p>
5072     * For example, to enable the top scroll indicatorExample: {@code setScrollIndicators
5073     *
5074     * @param indicators the indicator direction, or the logical OR of multiple
5075     *             indicator directions. One or more of:
5076     *             <ul>
5077     *               <li>{@link #SCROLL_INDICATOR_TOP}</li>
5078     *               <li>{@link #SCROLL_INDICATOR_BOTTOM}</li>
5079     *               <li>{@link #SCROLL_INDICATOR_LEFT}</li>
5080     *               <li>{@link #SCROLL_INDICATOR_RIGHT}</li>
5081     *               <li>{@link #SCROLL_INDICATOR_START}</li>
5082     *               <li>{@link #SCROLL_INDICATOR_END}</li>
5083     *             </ul>
5084     * @see #setScrollIndicators(int)
5085     * @see #getScrollIndicators()
5086     * @attr ref android.R.styleable#View_scrollIndicators
5087     */
5088    public void setScrollIndicators(@ScrollIndicators int indicators, @ScrollIndicators int mask) {
5089        // Shift and sanitize mask.
5090        mask <<= SCROLL_INDICATORS_TO_PFLAGS3_LSHIFT;
5091        mask &= SCROLL_INDICATORS_PFLAG3_MASK;
5092
5093        // Shift and mask indicators.
5094        indicators <<= SCROLL_INDICATORS_TO_PFLAGS3_LSHIFT;
5095        indicators &= mask;
5096
5097        // Merge with non-masked flags.
5098        final int updatedFlags = indicators | (mPrivateFlags3 & ~mask);
5099
5100        if (mPrivateFlags3 != updatedFlags) {
5101            mPrivateFlags3 = updatedFlags;
5102
5103            if (indicators != 0) {
5104                initializeScrollIndicatorsInternal();
5105            }
5106            invalidate();
5107        }
5108    }
5109
5110    /**
5111     * Returns a bitmask representing the enabled scroll indicators.
5112     * <p>
5113     * For example, if the top and left scroll indicators are enabled and all
5114     * other indicators are disabled, the return value will be
5115     * {@code View.SCROLL_INDICATOR_TOP | View.SCROLL_INDICATOR_LEFT}.
5116     * <p>
5117     * To check whether the bottom scroll indicator is enabled, use the value
5118     * of {@code (getScrollIndicators() & View.SCROLL_INDICATOR_BOTTOM) != 0}.
5119     *
5120     * @return a bitmask representing the enabled scroll indicators
5121     */
5122    @ScrollIndicators
5123    public int getScrollIndicators() {
5124        return (mPrivateFlags3 & SCROLL_INDICATORS_PFLAG3_MASK)
5125                >>> SCROLL_INDICATORS_TO_PFLAGS3_LSHIFT;
5126    }
5127
5128    ListenerInfo getListenerInfo() {
5129        if (mListenerInfo != null) {
5130            return mListenerInfo;
5131        }
5132        mListenerInfo = new ListenerInfo();
5133        return mListenerInfo;
5134    }
5135
5136    /**
5137     * Register a callback to be invoked when the scroll X or Y positions of
5138     * this view change.
5139     * <p>
5140     * <b>Note:</b> Some views handle scrolling independently from View and may
5141     * have their own separate listeners for scroll-type events. For example,
5142     * {@link android.widget.ListView ListView} allows clients to register an
5143     * {@link android.widget.ListView#setOnScrollListener(android.widget.AbsListView.OnScrollListener) AbsListView.OnScrollListener}
5144     * to listen for changes in list scroll position.
5145     *
5146     * @param l The listener to notify when the scroll X or Y position changes.
5147     * @see android.view.View#getScrollX()
5148     * @see android.view.View#getScrollY()
5149     */
5150    public void setOnScrollChangeListener(OnScrollChangeListener l) {
5151        getListenerInfo().mOnScrollChangeListener = l;
5152    }
5153
5154    /**
5155     * Register a callback to be invoked when focus of this view changed.
5156     *
5157     * @param l The callback that will run.
5158     */
5159    public void setOnFocusChangeListener(OnFocusChangeListener l) {
5160        getListenerInfo().mOnFocusChangeListener = l;
5161    }
5162
5163    /**
5164     * Add a listener that will be called when the bounds of the view change due to
5165     * layout processing.
5166     *
5167     * @param listener The listener that will be called when layout bounds change.
5168     */
5169    public void addOnLayoutChangeListener(OnLayoutChangeListener listener) {
5170        ListenerInfo li = getListenerInfo();
5171        if (li.mOnLayoutChangeListeners == null) {
5172            li.mOnLayoutChangeListeners = new ArrayList<OnLayoutChangeListener>();
5173        }
5174        if (!li.mOnLayoutChangeListeners.contains(listener)) {
5175            li.mOnLayoutChangeListeners.add(listener);
5176        }
5177    }
5178
5179    /**
5180     * Remove a listener for layout changes.
5181     *
5182     * @param listener The listener for layout bounds change.
5183     */
5184    public void removeOnLayoutChangeListener(OnLayoutChangeListener listener) {
5185        ListenerInfo li = mListenerInfo;
5186        if (li == null || li.mOnLayoutChangeListeners == null) {
5187            return;
5188        }
5189        li.mOnLayoutChangeListeners.remove(listener);
5190    }
5191
5192    /**
5193     * Add a listener for attach state changes.
5194     *
5195     * This listener will be called whenever this view is attached or detached
5196     * from a window. Remove the listener using
5197     * {@link #removeOnAttachStateChangeListener(OnAttachStateChangeListener)}.
5198     *
5199     * @param listener Listener to attach
5200     * @see #removeOnAttachStateChangeListener(OnAttachStateChangeListener)
5201     */
5202    public void addOnAttachStateChangeListener(OnAttachStateChangeListener listener) {
5203        ListenerInfo li = getListenerInfo();
5204        if (li.mOnAttachStateChangeListeners == null) {
5205            li.mOnAttachStateChangeListeners
5206                    = new CopyOnWriteArrayList<OnAttachStateChangeListener>();
5207        }
5208        li.mOnAttachStateChangeListeners.add(listener);
5209    }
5210
5211    /**
5212     * Remove a listener for attach state changes. The listener will receive no further
5213     * notification of window attach/detach events.
5214     *
5215     * @param listener Listener to remove
5216     * @see #addOnAttachStateChangeListener(OnAttachStateChangeListener)
5217     */
5218    public void removeOnAttachStateChangeListener(OnAttachStateChangeListener listener) {
5219        ListenerInfo li = mListenerInfo;
5220        if (li == null || li.mOnAttachStateChangeListeners == null) {
5221            return;
5222        }
5223        li.mOnAttachStateChangeListeners.remove(listener);
5224    }
5225
5226    /**
5227     * Returns the focus-change callback registered for this view.
5228     *
5229     * @return The callback, or null if one is not registered.
5230     */
5231    public OnFocusChangeListener getOnFocusChangeListener() {
5232        ListenerInfo li = mListenerInfo;
5233        return li != null ? li.mOnFocusChangeListener : null;
5234    }
5235
5236    /**
5237     * Register a callback to be invoked when this view is clicked. If this view is not
5238     * clickable, it becomes clickable.
5239     *
5240     * @param l The callback that will run
5241     *
5242     * @see #setClickable(boolean)
5243     */
5244    public void setOnClickListener(@Nullable OnClickListener l) {
5245        if (!isClickable()) {
5246            setClickable(true);
5247        }
5248        getListenerInfo().mOnClickListener = l;
5249    }
5250
5251    /**
5252     * Return whether this view has an attached OnClickListener.  Returns
5253     * true if there is a listener, false if there is none.
5254     */
5255    public boolean hasOnClickListeners() {
5256        ListenerInfo li = mListenerInfo;
5257        return (li != null && li.mOnClickListener != null);
5258    }
5259
5260    /**
5261     * Register a callback to be invoked when this view is clicked and held. If this view is not
5262     * long clickable, it becomes long clickable.
5263     *
5264     * @param l The callback that will run
5265     *
5266     * @see #setLongClickable(boolean)
5267     */
5268    public void setOnLongClickListener(@Nullable OnLongClickListener l) {
5269        if (!isLongClickable()) {
5270            setLongClickable(true);
5271        }
5272        getListenerInfo().mOnLongClickListener = l;
5273    }
5274
5275    /**
5276     * Register a callback to be invoked when this view is context clicked. If the view is not
5277     * context clickable, it becomes context clickable.
5278     *
5279     * @param l The callback that will run
5280     * @see #setContextClickable(boolean)
5281     */
5282    public void setOnContextClickListener(@Nullable OnContextClickListener l) {
5283        if (!isContextClickable()) {
5284            setContextClickable(true);
5285        }
5286        getListenerInfo().mOnContextClickListener = l;
5287    }
5288
5289    /**
5290     * Register a callback to be invoked when the context menu for this view is
5291     * being built. If this view is not long clickable, it becomes long clickable.
5292     *
5293     * @param l The callback that will run
5294     *
5295     */
5296    public void setOnCreateContextMenuListener(OnCreateContextMenuListener l) {
5297        if (!isLongClickable()) {
5298            setLongClickable(true);
5299        }
5300        getListenerInfo().mOnCreateContextMenuListener = l;
5301    }
5302
5303    /**
5304     * Call this view's OnClickListener, if it is defined.  Performs all normal
5305     * actions associated with clicking: reporting accessibility event, playing
5306     * a sound, etc.
5307     *
5308     * @return True there was an assigned OnClickListener that was called, false
5309     *         otherwise is returned.
5310     */
5311    public boolean performClick() {
5312        final boolean result;
5313        final ListenerInfo li = mListenerInfo;
5314        if (li != null && li.mOnClickListener != null) {
5315            playSoundEffect(SoundEffectConstants.CLICK);
5316            li.mOnClickListener.onClick(this);
5317            result = true;
5318        } else {
5319            result = false;
5320        }
5321
5322        sendAccessibilityEvent(AccessibilityEvent.TYPE_VIEW_CLICKED);
5323        return result;
5324    }
5325
5326    /**
5327     * Directly call any attached OnClickListener.  Unlike {@link #performClick()},
5328     * this only calls the listener, and does not do any associated clicking
5329     * actions like reporting an accessibility event.
5330     *
5331     * @return True there was an assigned OnClickListener that was called, false
5332     *         otherwise is returned.
5333     */
5334    public boolean callOnClick() {
5335        ListenerInfo li = mListenerInfo;
5336        if (li != null && li.mOnClickListener != null) {
5337            li.mOnClickListener.onClick(this);
5338            return true;
5339        }
5340        return false;
5341    }
5342
5343    /**
5344     * Calls this view's OnLongClickListener, if it is defined. Invokes the
5345     * context menu if the OnLongClickListener did not consume the event.
5346     *
5347     * @return {@code true} if one of the above receivers consumed the event,
5348     *         {@code false} otherwise
5349     */
5350    public boolean performLongClick() {
5351        return performLongClickInternal(false, 0, 0);
5352    }
5353
5354    /**
5355     * Calls this view's OnLongClickListener, if it is defined. Invokes the
5356     * context menu if the OnLongClickListener did not consume the event,
5357     * anchoring it to an (x,y) coordinate.
5358     *
5359     * @param x x coordinate of the anchoring touch event
5360     * @param y y coordinate of the anchoring touch event
5361     * @return {@code true} if one of the above receivers consumed the event,
5362     *         {@code false} otherwise
5363     */
5364    public boolean performLongClick(float x, float y) {
5365        return performLongClickInternal(true, x, y);
5366    }
5367
5368    /**
5369     * Calls this view's OnLongClickListener, if it is defined. Invokes the
5370     * context menu if the OnLongClickListener did not consume the event,
5371     * optionally anchoring it to an (x,y) coordinate.
5372     *
5373     * @param isAnchored whether this long click is anchored to a touch event
5374     * @param x x coordinate of the anchoring touch event, ignored if
5375     *          {@code isAnchored} is set to {@code false}
5376     * @param y y coordinate of the anchoring touch event, ignored if
5377     *          {@code isAnchored} is set to {@code false}
5378     * @return {@code true} if one of the above receivers consumed the event,
5379     *         {@code false} otherwise
5380     */
5381    private boolean performLongClickInternal(boolean isAnchored, float x, float y) {
5382        sendAccessibilityEvent(AccessibilityEvent.TYPE_VIEW_LONG_CLICKED);
5383
5384        boolean handled = false;
5385        final ListenerInfo li = mListenerInfo;
5386        if (li != null && li.mOnLongClickListener != null) {
5387            handled = li.mOnLongClickListener.onLongClick(View.this);
5388        }
5389        if (!handled) {
5390            handled = isAnchored ? showContextMenu(x, y) : showContextMenu();
5391        }
5392        if (handled) {
5393            performHapticFeedback(HapticFeedbackConstants.LONG_PRESS);
5394        }
5395        return handled;
5396    }
5397
5398    /**
5399     * Call this view's OnContextClickListener, if it is defined.
5400     *
5401     * @return True if there was an assigned OnContextClickListener that consumed the event, false
5402     *         otherwise.
5403     */
5404    public boolean performContextClick() {
5405        sendAccessibilityEvent(AccessibilityEvent.TYPE_VIEW_CONTEXT_CLICKED);
5406
5407        boolean handled = false;
5408        ListenerInfo li = mListenerInfo;
5409        if (li != null && li.mOnContextClickListener != null) {
5410            handled = li.mOnContextClickListener.onContextClick(View.this);
5411        }
5412        if (handled) {
5413            performHapticFeedback(HapticFeedbackConstants.CONTEXT_CLICK);
5414        }
5415        return handled;
5416    }
5417
5418    /**
5419     * Performs button-related actions during a touch down event.
5420     *
5421     * @param event The event.
5422     * @return True if the down was consumed.
5423     *
5424     * @hide
5425     */
5426    protected boolean performButtonActionOnTouchDown(MotionEvent event) {
5427        if (event.getToolType(0) == MotionEvent.TOOL_TYPE_MOUSE &&
5428            (event.getButtonState() & MotionEvent.BUTTON_SECONDARY) != 0) {
5429            showContextMenu(event.getX(), event.getY());
5430            mPrivateFlags |= PFLAG_CANCEL_NEXT_UP_EVENT;
5431            return true;
5432        }
5433        return false;
5434    }
5435
5436    /**
5437     * Bring up the context menu for this view.
5438     *
5439     * @return Whether a context menu was displayed.
5440     */
5441    public boolean showContextMenu() {
5442        return getParent().showContextMenuForChild(this);
5443    }
5444
5445    /**
5446     * Bring up the context menu for this view, referring to the item under the specified point.
5447     *
5448     * @param x The referenced x coordinate.
5449     * @param y The referenced y coordinate.
5450     * @return Whether a context menu was displayed.
5451     */
5452    public boolean showContextMenu(float x, float y) {
5453        return getParent().showContextMenuForChild(this, x, y);
5454    }
5455
5456    /**
5457     * Start an action mode with the default type {@link ActionMode#TYPE_PRIMARY}.
5458     *
5459     * @param callback Callback that will control the lifecycle of the action mode
5460     * @return The new action mode if it is started, null otherwise
5461     *
5462     * @see ActionMode
5463     * @see #startActionMode(android.view.ActionMode.Callback, int)
5464     */
5465    public ActionMode startActionMode(ActionMode.Callback callback) {
5466        return startActionMode(callback, ActionMode.TYPE_PRIMARY);
5467    }
5468
5469    /**
5470     * Start an action mode with the given type.
5471     *
5472     * @param callback Callback that will control the lifecycle of the action mode
5473     * @param type One of {@link ActionMode#TYPE_PRIMARY} or {@link ActionMode#TYPE_FLOATING}.
5474     * @return The new action mode if it is started, null otherwise
5475     *
5476     * @see ActionMode
5477     */
5478    public ActionMode startActionMode(ActionMode.Callback callback, int type) {
5479        ViewParent parent = getParent();
5480        if (parent == null) return null;
5481        try {
5482            return parent.startActionModeForChild(this, callback, type);
5483        } catch (AbstractMethodError ame) {
5484            // Older implementations of custom views might not implement this.
5485            return parent.startActionModeForChild(this, callback);
5486        }
5487    }
5488
5489    /**
5490     * Call {@link Context#startActivityForResult(String, Intent, int, Bundle)} for the View's
5491     * Context, creating a unique View identifier to retrieve the result.
5492     *
5493     * @param intent The Intent to be started.
5494     * @param requestCode The request code to use.
5495     * @hide
5496     */
5497    public void startActivityForResult(Intent intent, int requestCode) {
5498        mStartActivityRequestWho = "@android:view:" + System.identityHashCode(this);
5499        getContext().startActivityForResult(mStartActivityRequestWho, intent, requestCode, null);
5500    }
5501
5502    /**
5503     * If this View corresponds to the calling who, dispatches the activity result.
5504     * @param who The identifier for the targeted View to receive the result.
5505     * @param requestCode The integer request code originally supplied to
5506     *                    startActivityForResult(), allowing you to identify who this
5507     *                    result came from.
5508     * @param resultCode The integer result code returned by the child activity
5509     *                   through its setResult().
5510     * @param data An Intent, which can return result data to the caller
5511     *               (various data can be attached to Intent "extras").
5512     * @return {@code true} if the activity result was dispatched.
5513     * @hide
5514     */
5515    public boolean dispatchActivityResult(
5516            String who, int requestCode, int resultCode, Intent data) {
5517        if (mStartActivityRequestWho != null && mStartActivityRequestWho.equals(who)) {
5518            onActivityResult(requestCode, resultCode, data);
5519            mStartActivityRequestWho = null;
5520            return true;
5521        }
5522        return false;
5523    }
5524
5525    /**
5526     * Receive the result from a previous call to {@link #startActivityForResult(Intent, int)}.
5527     *
5528     * @param requestCode The integer request code originally supplied to
5529     *                    startActivityForResult(), allowing you to identify who this
5530     *                    result came from.
5531     * @param resultCode The integer result code returned by the child activity
5532     *                   through its setResult().
5533     * @param data An Intent, which can return result data to the caller
5534     *               (various data can be attached to Intent "extras").
5535     * @hide
5536     */
5537    public void onActivityResult(int requestCode, int resultCode, Intent data) {
5538        // Do nothing.
5539    }
5540
5541    /**
5542     * Register a callback to be invoked when a hardware key is pressed in this view.
5543     * Key presses in software input methods will generally not trigger the methods of
5544     * this listener.
5545     * @param l the key listener to attach to this view
5546     */
5547    public void setOnKeyListener(OnKeyListener l) {
5548        getListenerInfo().mOnKeyListener = l;
5549    }
5550
5551    /**
5552     * Register a callback to be invoked when a touch event is sent to this view.
5553     * @param l the touch listener to attach to this view
5554     */
5555    public void setOnTouchListener(OnTouchListener l) {
5556        getListenerInfo().mOnTouchListener = l;
5557    }
5558
5559    /**
5560     * Register a callback to be invoked when a generic motion event is sent to this view.
5561     * @param l the generic motion listener to attach to this view
5562     */
5563    public void setOnGenericMotionListener(OnGenericMotionListener l) {
5564        getListenerInfo().mOnGenericMotionListener = l;
5565    }
5566
5567    /**
5568     * Register a callback to be invoked when a hover event is sent to this view.
5569     * @param l the hover listener to attach to this view
5570     */
5571    public void setOnHoverListener(OnHoverListener l) {
5572        getListenerInfo().mOnHoverListener = l;
5573    }
5574
5575    /**
5576     * Register a drag event listener callback object for this View. The parameter is
5577     * an implementation of {@link android.view.View.OnDragListener}. To send a drag event to a
5578     * View, the system calls the
5579     * {@link android.view.View.OnDragListener#onDrag(View,DragEvent)} method.
5580     * @param l An implementation of {@link android.view.View.OnDragListener}.
5581     */
5582    public void setOnDragListener(OnDragListener l) {
5583        getListenerInfo().mOnDragListener = l;
5584    }
5585
5586    /**
5587     * Give this view focus. This will cause
5588     * {@link #onFocusChanged(boolean, int, android.graphics.Rect)} to be called.
5589     *
5590     * Note: this does not check whether this {@link View} should get focus, it just
5591     * gives it focus no matter what.  It should only be called internally by framework
5592     * code that knows what it is doing, namely {@link #requestFocus(int, Rect)}.
5593     *
5594     * @param direction values are {@link View#FOCUS_UP}, {@link View#FOCUS_DOWN},
5595     *        {@link View#FOCUS_LEFT} or {@link View#FOCUS_RIGHT}. This is the direction which
5596     *        focus moved when requestFocus() is called. It may not always
5597     *        apply, in which case use the default View.FOCUS_DOWN.
5598     * @param previouslyFocusedRect The rectangle of the view that had focus
5599     *        prior in this View's coordinate system.
5600     */
5601    void handleFocusGainInternal(@FocusRealDirection int direction, Rect previouslyFocusedRect) {
5602        if (DBG) {
5603            System.out.println(this + " requestFocus()");
5604        }
5605
5606        if ((mPrivateFlags & PFLAG_FOCUSED) == 0) {
5607            mPrivateFlags |= PFLAG_FOCUSED;
5608
5609            View oldFocus = (mAttachInfo != null) ? getRootView().findFocus() : null;
5610
5611            if (mParent != null) {
5612                mParent.requestChildFocus(this, this);
5613            }
5614
5615            if (mAttachInfo != null) {
5616                mAttachInfo.mTreeObserver.dispatchOnGlobalFocusChange(oldFocus, this);
5617            }
5618
5619            onFocusChanged(true, direction, previouslyFocusedRect);
5620            refreshDrawableState();
5621        }
5622    }
5623
5624    /**
5625     * Populates <code>outRect</code> with the hotspot bounds. By default,
5626     * the hotspot bounds are identical to the screen bounds.
5627     *
5628     * @param outRect rect to populate with hotspot bounds
5629     * @hide Only for internal use by views and widgets.
5630     */
5631    public void getHotspotBounds(Rect outRect) {
5632        final Drawable background = getBackground();
5633        if (background != null) {
5634            background.getHotspotBounds(outRect);
5635        } else {
5636            getBoundsOnScreen(outRect);
5637        }
5638    }
5639
5640    /**
5641     * Request that a rectangle of this view be visible on the screen,
5642     * scrolling if necessary just enough.
5643     *
5644     * <p>A View should call this if it maintains some notion of which part
5645     * of its content is interesting.  For example, a text editing view
5646     * should call this when its cursor moves.
5647     *
5648     * @param rectangle The rectangle.
5649     * @return Whether any parent scrolled.
5650     */
5651    public boolean requestRectangleOnScreen(Rect rectangle) {
5652        return requestRectangleOnScreen(rectangle, false);
5653    }
5654
5655    /**
5656     * Request that a rectangle of this view be visible on the screen,
5657     * scrolling if necessary just enough.
5658     *
5659     * <p>A View should call this if it maintains some notion of which part
5660     * of its content is interesting.  For example, a text editing view
5661     * should call this when its cursor moves.
5662     *
5663     * <p>When <code>immediate</code> is set to true, scrolling will not be
5664     * animated.
5665     *
5666     * @param rectangle The rectangle.
5667     * @param immediate True to forbid animated scrolling, false otherwise
5668     * @return Whether any parent scrolled.
5669     */
5670    public boolean requestRectangleOnScreen(Rect rectangle, boolean immediate) {
5671        if (mParent == null) {
5672            return false;
5673        }
5674
5675        View child = this;
5676
5677        RectF position = (mAttachInfo != null) ? mAttachInfo.mTmpTransformRect : new RectF();
5678        position.set(rectangle);
5679
5680        ViewParent parent = mParent;
5681        boolean scrolled = false;
5682        while (parent != null) {
5683            rectangle.set((int) position.left, (int) position.top,
5684                    (int) position.right, (int) position.bottom);
5685
5686            scrolled |= parent.requestChildRectangleOnScreen(child,
5687                    rectangle, immediate);
5688
5689            if (!child.hasIdentityMatrix()) {
5690                child.getMatrix().mapRect(position);
5691            }
5692
5693            position.offset(child.mLeft, child.mTop);
5694
5695            if (!(parent instanceof View)) {
5696                break;
5697            }
5698
5699            View parentView = (View) parent;
5700
5701            position.offset(-parentView.getScrollX(), -parentView.getScrollY());
5702
5703            child = parentView;
5704            parent = child.getParent();
5705        }
5706
5707        return scrolled;
5708    }
5709
5710    /**
5711     * Called when this view wants to give up focus. If focus is cleared
5712     * {@link #onFocusChanged(boolean, int, android.graphics.Rect)} is called.
5713     * <p>
5714     * <strong>Note:</strong> When a View clears focus the framework is trying
5715     * to give focus to the first focusable View from the top. Hence, if this
5716     * View is the first from the top that can take focus, then all callbacks
5717     * related to clearing focus will be invoked after which the framework will
5718     * give focus to this view.
5719     * </p>
5720     */
5721    public void clearFocus() {
5722        if (DBG) {
5723            System.out.println(this + " clearFocus()");
5724        }
5725
5726        clearFocusInternal(null, true, true);
5727    }
5728
5729    /**
5730     * Clears focus from the view, optionally propagating the change up through
5731     * the parent hierarchy and requesting that the root view place new focus.
5732     *
5733     * @param propagate whether to propagate the change up through the parent
5734     *            hierarchy
5735     * @param refocus when propagate is true, specifies whether to request the
5736     *            root view place new focus
5737     */
5738    void clearFocusInternal(View focused, boolean propagate, boolean refocus) {
5739        if ((mPrivateFlags & PFLAG_FOCUSED) != 0) {
5740            mPrivateFlags &= ~PFLAG_FOCUSED;
5741
5742            if (propagate && mParent != null) {
5743                mParent.clearChildFocus(this);
5744            }
5745
5746            onFocusChanged(false, 0, null);
5747            refreshDrawableState();
5748
5749            if (propagate && (!refocus || !rootViewRequestFocus())) {
5750                notifyGlobalFocusCleared(this);
5751            }
5752        }
5753    }
5754
5755    void notifyGlobalFocusCleared(View oldFocus) {
5756        if (oldFocus != null && mAttachInfo != null) {
5757            mAttachInfo.mTreeObserver.dispatchOnGlobalFocusChange(oldFocus, null);
5758        }
5759    }
5760
5761    boolean rootViewRequestFocus() {
5762        final View root = getRootView();
5763        return root != null && root.requestFocus();
5764    }
5765
5766    /**
5767     * Called internally by the view system when a new view is getting focus.
5768     * This is what clears the old focus.
5769     * <p>
5770     * <b>NOTE:</b> The parent view's focused child must be updated manually
5771     * after calling this method. Otherwise, the view hierarchy may be left in
5772     * an inconstent state.
5773     */
5774    void unFocus(View focused) {
5775        if (DBG) {
5776            System.out.println(this + " unFocus()");
5777        }
5778
5779        clearFocusInternal(focused, false, false);
5780    }
5781
5782    /**
5783     * Returns true if this view has focus itself, or is the ancestor of the
5784     * view that has focus.
5785     *
5786     * @return True if this view has or contains focus, false otherwise.
5787     */
5788    @ViewDebug.ExportedProperty(category = "focus")
5789    public boolean hasFocus() {
5790        return (mPrivateFlags & PFLAG_FOCUSED) != 0;
5791    }
5792
5793    /**
5794     * Returns true if this view is focusable or if it contains a reachable View
5795     * for which {@link #hasFocusable()} returns true. A "reachable hasFocusable()"
5796     * is a View whose parents do not block descendants focus.
5797     *
5798     * Only {@link #VISIBLE} views are considered focusable.
5799     *
5800     * @return True if the view is focusable or if the view contains a focusable
5801     *         View, false otherwise.
5802     *
5803     * @see ViewGroup#FOCUS_BLOCK_DESCENDANTS
5804     * @see ViewGroup#getTouchscreenBlocksFocus()
5805     */
5806    public boolean hasFocusable() {
5807        if (!isFocusableInTouchMode()) {
5808            for (ViewParent p = mParent; p instanceof ViewGroup; p = p.getParent()) {
5809                final ViewGroup g = (ViewGroup) p;
5810                if (g.shouldBlockFocusForTouchscreen()) {
5811                    return false;
5812                }
5813            }
5814        }
5815        return (mViewFlags & VISIBILITY_MASK) == VISIBLE && isFocusable();
5816    }
5817
5818    /**
5819     * Called by the view system when the focus state of this view changes.
5820     * When the focus change event is caused by directional navigation, direction
5821     * and previouslyFocusedRect provide insight into where the focus is coming from.
5822     * When overriding, be sure to call up through to the super class so that
5823     * the standard focus handling will occur.
5824     *
5825     * @param gainFocus True if the View has focus; false otherwise.
5826     * @param direction The direction focus has moved when requestFocus()
5827     *                  is called to give this view focus. Values are
5828     *                  {@link #FOCUS_UP}, {@link #FOCUS_DOWN}, {@link #FOCUS_LEFT},
5829     *                  {@link #FOCUS_RIGHT}, {@link #FOCUS_FORWARD}, or {@link #FOCUS_BACKWARD}.
5830     *                  It may not always apply, in which case use the default.
5831     * @param previouslyFocusedRect The rectangle, in this view's coordinate
5832     *        system, of the previously focused view.  If applicable, this will be
5833     *        passed in as finer grained information about where the focus is coming
5834     *        from (in addition to direction).  Will be <code>null</code> otherwise.
5835     */
5836    @CallSuper
5837    protected void onFocusChanged(boolean gainFocus, @FocusDirection int direction,
5838            @Nullable Rect previouslyFocusedRect) {
5839        if (gainFocus) {
5840            sendAccessibilityEvent(AccessibilityEvent.TYPE_VIEW_FOCUSED);
5841        } else {
5842            notifyViewAccessibilityStateChangedIfNeeded(
5843                    AccessibilityEvent.CONTENT_CHANGE_TYPE_UNDEFINED);
5844        }
5845
5846        InputMethodManager imm = InputMethodManager.peekInstance();
5847        if (!gainFocus) {
5848            if (isPressed()) {
5849                setPressed(false);
5850            }
5851            if (imm != null && mAttachInfo != null
5852                    && mAttachInfo.mHasWindowFocus) {
5853                imm.focusOut(this);
5854            }
5855            onFocusLost();
5856        } else if (imm != null && mAttachInfo != null
5857                && mAttachInfo.mHasWindowFocus) {
5858            imm.focusIn(this);
5859        }
5860
5861        invalidate(true);
5862        ListenerInfo li = mListenerInfo;
5863        if (li != null && li.mOnFocusChangeListener != null) {
5864            li.mOnFocusChangeListener.onFocusChange(this, gainFocus);
5865        }
5866
5867        if (mAttachInfo != null) {
5868            mAttachInfo.mKeyDispatchState.reset(this);
5869        }
5870    }
5871
5872    /**
5873     * Sends an accessibility event of the given type. If accessibility is
5874     * not enabled this method has no effect. The default implementation calls
5875     * {@link #onInitializeAccessibilityEvent(AccessibilityEvent)} first
5876     * to populate information about the event source (this View), then calls
5877     * {@link #dispatchPopulateAccessibilityEvent(AccessibilityEvent)} to
5878     * populate the text content of the event source including its descendants,
5879     * and last calls
5880     * {@link ViewParent#requestSendAccessibilityEvent(View, AccessibilityEvent)}
5881     * on its parent to request sending of the event to interested parties.
5882     * <p>
5883     * If an {@link AccessibilityDelegate} has been specified via calling
5884     * {@link #setAccessibilityDelegate(AccessibilityDelegate)} its
5885     * {@link AccessibilityDelegate#sendAccessibilityEvent(View, int)} is
5886     * responsible for handling this call.
5887     * </p>
5888     *
5889     * @param eventType The type of the event to send, as defined by several types from
5890     * {@link android.view.accessibility.AccessibilityEvent}, such as
5891     * {@link android.view.accessibility.AccessibilityEvent#TYPE_VIEW_CLICKED} or
5892     * {@link android.view.accessibility.AccessibilityEvent#TYPE_VIEW_HOVER_ENTER}.
5893     *
5894     * @see #onInitializeAccessibilityEvent(AccessibilityEvent)
5895     * @see #dispatchPopulateAccessibilityEvent(AccessibilityEvent)
5896     * @see ViewParent#requestSendAccessibilityEvent(View, AccessibilityEvent)
5897     * @see AccessibilityDelegate
5898     */
5899    public void sendAccessibilityEvent(int eventType) {
5900        if (mAccessibilityDelegate != null) {
5901            mAccessibilityDelegate.sendAccessibilityEvent(this, eventType);
5902        } else {
5903            sendAccessibilityEventInternal(eventType);
5904        }
5905    }
5906
5907    /**
5908     * Convenience method for sending a {@link AccessibilityEvent#TYPE_ANNOUNCEMENT}
5909     * {@link AccessibilityEvent} to make an announcement which is related to some
5910     * sort of a context change for which none of the events representing UI transitions
5911     * is a good fit. For example, announcing a new page in a book. If accessibility
5912     * is not enabled this method does nothing.
5913     *
5914     * @param text The announcement text.
5915     */
5916    public void announceForAccessibility(CharSequence text) {
5917        if (AccessibilityManager.getInstance(mContext).isEnabled() && mParent != null) {
5918            AccessibilityEvent event = AccessibilityEvent.obtain(
5919                    AccessibilityEvent.TYPE_ANNOUNCEMENT);
5920            onInitializeAccessibilityEvent(event);
5921            event.getText().add(text);
5922            event.setContentDescription(null);
5923            mParent.requestSendAccessibilityEvent(this, event);
5924        }
5925    }
5926
5927    /**
5928     * @see #sendAccessibilityEvent(int)
5929     *
5930     * Note: Called from the default {@link AccessibilityDelegate}.
5931     *
5932     * @hide
5933     */
5934    public void sendAccessibilityEventInternal(int eventType) {
5935        if (AccessibilityManager.getInstance(mContext).isEnabled()) {
5936            sendAccessibilityEventUnchecked(AccessibilityEvent.obtain(eventType));
5937        }
5938    }
5939
5940    /**
5941     * This method behaves exactly as {@link #sendAccessibilityEvent(int)} but
5942     * takes as an argument an empty {@link AccessibilityEvent} and does not
5943     * perform a check whether accessibility is enabled.
5944     * <p>
5945     * If an {@link AccessibilityDelegate} has been specified via calling
5946     * {@link #setAccessibilityDelegate(AccessibilityDelegate)} its
5947     * {@link AccessibilityDelegate#sendAccessibilityEventUnchecked(View, AccessibilityEvent)}
5948     * is responsible for handling this call.
5949     * </p>
5950     *
5951     * @param event The event to send.
5952     *
5953     * @see #sendAccessibilityEvent(int)
5954     */
5955    public void sendAccessibilityEventUnchecked(AccessibilityEvent event) {
5956        if (mAccessibilityDelegate != null) {
5957            mAccessibilityDelegate.sendAccessibilityEventUnchecked(this, event);
5958        } else {
5959            sendAccessibilityEventUncheckedInternal(event);
5960        }
5961    }
5962
5963    /**
5964     * @see #sendAccessibilityEventUnchecked(AccessibilityEvent)
5965     *
5966     * Note: Called from the default {@link AccessibilityDelegate}.
5967     *
5968     * @hide
5969     */
5970    public void sendAccessibilityEventUncheckedInternal(AccessibilityEvent event) {
5971        if (!isShown()) {
5972            return;
5973        }
5974        onInitializeAccessibilityEvent(event);
5975        // Only a subset of accessibility events populates text content.
5976        if ((event.getEventType() & POPULATING_ACCESSIBILITY_EVENT_TYPES) != 0) {
5977            dispatchPopulateAccessibilityEvent(event);
5978        }
5979        // In the beginning we called #isShown(), so we know that getParent() is not null.
5980        getParent().requestSendAccessibilityEvent(this, event);
5981    }
5982
5983    /**
5984     * Dispatches an {@link AccessibilityEvent} to the {@link View} first and then
5985     * to its children for adding their text content to the event. Note that the
5986     * event text is populated in a separate dispatch path since we add to the
5987     * event not only the text of the source but also the text of all its descendants.
5988     * A typical implementation will call
5989     * {@link #onPopulateAccessibilityEvent(AccessibilityEvent)} on the this view
5990     * and then call the {@link #dispatchPopulateAccessibilityEvent(AccessibilityEvent)}
5991     * on each child. Override this method if custom population of the event text
5992     * content is required.
5993     * <p>
5994     * If an {@link AccessibilityDelegate} has been specified via calling
5995     * {@link #setAccessibilityDelegate(AccessibilityDelegate)} its
5996     * {@link AccessibilityDelegate#dispatchPopulateAccessibilityEvent(View, AccessibilityEvent)}
5997     * is responsible for handling this call.
5998     * </p>
5999     * <p>
6000     * <em>Note:</em> Accessibility events of certain types are not dispatched for
6001     * populating the event text via this method. For details refer to {@link AccessibilityEvent}.
6002     * </p>
6003     *
6004     * @param event The event.
6005     *
6006     * @return True if the event population was completed.
6007     */
6008    public boolean dispatchPopulateAccessibilityEvent(AccessibilityEvent event) {
6009        if (mAccessibilityDelegate != null) {
6010            return mAccessibilityDelegate.dispatchPopulateAccessibilityEvent(this, event);
6011        } else {
6012            return dispatchPopulateAccessibilityEventInternal(event);
6013        }
6014    }
6015
6016    /**
6017     * @see #dispatchPopulateAccessibilityEvent(AccessibilityEvent)
6018     *
6019     * Note: Called from the default {@link AccessibilityDelegate}.
6020     *
6021     * @hide
6022     */
6023    public boolean dispatchPopulateAccessibilityEventInternal(AccessibilityEvent event) {
6024        onPopulateAccessibilityEvent(event);
6025        return false;
6026    }
6027
6028    /**
6029     * Called from {@link #dispatchPopulateAccessibilityEvent(AccessibilityEvent)}
6030     * giving a chance to this View to populate the accessibility event with its
6031     * text content. While this method is free to modify event
6032     * attributes other than text content, doing so should normally be performed in
6033     * {@link #onInitializeAccessibilityEvent(AccessibilityEvent)}.
6034     * <p>
6035     * Example: Adding formatted date string to an accessibility event in addition
6036     *          to the text added by the super implementation:
6037     * <pre> public void onPopulateAccessibilityEvent(AccessibilityEvent event) {
6038     *     super.onPopulateAccessibilityEvent(event);
6039     *     final int flags = DateUtils.FORMAT_SHOW_DATE | DateUtils.FORMAT_SHOW_WEEKDAY;
6040     *     String selectedDateUtterance = DateUtils.formatDateTime(mContext,
6041     *         mCurrentDate.getTimeInMillis(), flags);
6042     *     event.getText().add(selectedDateUtterance);
6043     * }</pre>
6044     * <p>
6045     * If an {@link AccessibilityDelegate} has been specified via calling
6046     * {@link #setAccessibilityDelegate(AccessibilityDelegate)} its
6047     * {@link AccessibilityDelegate#onPopulateAccessibilityEvent(View, AccessibilityEvent)}
6048     * is responsible for handling this call.
6049     * </p>
6050     * <p class="note"><strong>Note:</strong> Always call the super implementation before adding
6051     * information to the event, in case the default implementation has basic information to add.
6052     * </p>
6053     *
6054     * @param event The accessibility event which to populate.
6055     *
6056     * @see #sendAccessibilityEvent(int)
6057     * @see #dispatchPopulateAccessibilityEvent(AccessibilityEvent)
6058     */
6059    @CallSuper
6060    public void onPopulateAccessibilityEvent(AccessibilityEvent event) {
6061        if (mAccessibilityDelegate != null) {
6062            mAccessibilityDelegate.onPopulateAccessibilityEvent(this, event);
6063        } else {
6064            onPopulateAccessibilityEventInternal(event);
6065        }
6066    }
6067
6068    /**
6069     * @see #onPopulateAccessibilityEvent(AccessibilityEvent)
6070     *
6071     * Note: Called from the default {@link AccessibilityDelegate}.
6072     *
6073     * @hide
6074     */
6075    public void onPopulateAccessibilityEventInternal(AccessibilityEvent event) {
6076    }
6077
6078    /**
6079     * Initializes an {@link AccessibilityEvent} with information about
6080     * this View which is the event source. In other words, the source of
6081     * an accessibility event is the view whose state change triggered firing
6082     * the event.
6083     * <p>
6084     * Example: Setting the password property of an event in addition
6085     *          to properties set by the super implementation:
6086     * <pre> public void onInitializeAccessibilityEvent(AccessibilityEvent event) {
6087     *     super.onInitializeAccessibilityEvent(event);
6088     *     event.setPassword(true);
6089     * }</pre>
6090     * <p>
6091     * If an {@link AccessibilityDelegate} has been specified via calling
6092     * {@link #setAccessibilityDelegate(AccessibilityDelegate)} its
6093     * {@link AccessibilityDelegate#onInitializeAccessibilityEvent(View, AccessibilityEvent)}
6094     * is responsible for handling this call.
6095     * </p>
6096     * <p class="note"><strong>Note:</strong> Always call the super implementation before adding
6097     * information to the event, in case the default implementation has basic information to add.
6098     * </p>
6099     * @param event The event to initialize.
6100     *
6101     * @see #sendAccessibilityEvent(int)
6102     * @see #dispatchPopulateAccessibilityEvent(AccessibilityEvent)
6103     */
6104    @CallSuper
6105    public void onInitializeAccessibilityEvent(AccessibilityEvent event) {
6106        if (mAccessibilityDelegate != null) {
6107            mAccessibilityDelegate.onInitializeAccessibilityEvent(this, event);
6108        } else {
6109            onInitializeAccessibilityEventInternal(event);
6110        }
6111    }
6112
6113    /**
6114     * @see #onInitializeAccessibilityEvent(AccessibilityEvent)
6115     *
6116     * Note: Called from the default {@link AccessibilityDelegate}.
6117     *
6118     * @hide
6119     */
6120    public void onInitializeAccessibilityEventInternal(AccessibilityEvent event) {
6121        event.setSource(this);
6122        event.setClassName(getAccessibilityClassName());
6123        event.setPackageName(getContext().getPackageName());
6124        event.setEnabled(isEnabled());
6125        event.setContentDescription(mContentDescription);
6126
6127        switch (event.getEventType()) {
6128            case AccessibilityEvent.TYPE_VIEW_FOCUSED: {
6129                ArrayList<View> focusablesTempList = (mAttachInfo != null)
6130                        ? mAttachInfo.mTempArrayList : new ArrayList<View>();
6131                getRootView().addFocusables(focusablesTempList, View.FOCUS_FORWARD, FOCUSABLES_ALL);
6132                event.setItemCount(focusablesTempList.size());
6133                event.setCurrentItemIndex(focusablesTempList.indexOf(this));
6134                if (mAttachInfo != null) {
6135                    focusablesTempList.clear();
6136                }
6137            } break;
6138            case AccessibilityEvent.TYPE_VIEW_TEXT_SELECTION_CHANGED: {
6139                CharSequence text = getIterableTextForAccessibility();
6140                if (text != null && text.length() > 0) {
6141                    event.setFromIndex(getAccessibilitySelectionStart());
6142                    event.setToIndex(getAccessibilitySelectionEnd());
6143                    event.setItemCount(text.length());
6144                }
6145            } break;
6146        }
6147    }
6148
6149    /**
6150     * Returns an {@link AccessibilityNodeInfo} representing this view from the
6151     * point of view of an {@link android.accessibilityservice.AccessibilityService}.
6152     * This method is responsible for obtaining an accessibility node info from a
6153     * pool of reusable instances and calling
6154     * {@link #onInitializeAccessibilityNodeInfo(AccessibilityNodeInfo)} on this view to
6155     * initialize the former.
6156     * <p>
6157     * Note: The client is responsible for recycling the obtained instance by calling
6158     *       {@link AccessibilityNodeInfo#recycle()} to minimize object creation.
6159     * </p>
6160     *
6161     * @return A populated {@link AccessibilityNodeInfo}.
6162     *
6163     * @see AccessibilityNodeInfo
6164     */
6165    public AccessibilityNodeInfo createAccessibilityNodeInfo() {
6166        if (mAccessibilityDelegate != null) {
6167            return mAccessibilityDelegate.createAccessibilityNodeInfo(this);
6168        } else {
6169            return createAccessibilityNodeInfoInternal();
6170        }
6171    }
6172
6173    /**
6174     * @see #createAccessibilityNodeInfo()
6175     *
6176     * @hide
6177     */
6178    public AccessibilityNodeInfo createAccessibilityNodeInfoInternal() {
6179        AccessibilityNodeProvider provider = getAccessibilityNodeProvider();
6180        if (provider != null) {
6181            return provider.createAccessibilityNodeInfo(AccessibilityNodeProvider.HOST_VIEW_ID);
6182        } else {
6183            AccessibilityNodeInfo info = AccessibilityNodeInfo.obtain(this);
6184            onInitializeAccessibilityNodeInfo(info);
6185            return info;
6186        }
6187    }
6188
6189    /**
6190     * Initializes an {@link AccessibilityNodeInfo} with information about this view.
6191     * The base implementation sets:
6192     * <ul>
6193     *   <li>{@link AccessibilityNodeInfo#setParent(View)},</li>
6194     *   <li>{@link AccessibilityNodeInfo#setBoundsInParent(Rect)},</li>
6195     *   <li>{@link AccessibilityNodeInfo#setBoundsInScreen(Rect)},</li>
6196     *   <li>{@link AccessibilityNodeInfo#setPackageName(CharSequence)},</li>
6197     *   <li>{@link AccessibilityNodeInfo#setClassName(CharSequence)},</li>
6198     *   <li>{@link AccessibilityNodeInfo#setContentDescription(CharSequence)},</li>
6199     *   <li>{@link AccessibilityNodeInfo#setEnabled(boolean)},</li>
6200     *   <li>{@link AccessibilityNodeInfo#setClickable(boolean)},</li>
6201     *   <li>{@link AccessibilityNodeInfo#setFocusable(boolean)},</li>
6202     *   <li>{@link AccessibilityNodeInfo#setFocused(boolean)},</li>
6203     *   <li>{@link AccessibilityNodeInfo#setLongClickable(boolean)},</li>
6204     *   <li>{@link AccessibilityNodeInfo#setSelected(boolean)},</li>
6205     *   <li>{@link AccessibilityNodeInfo#setContextClickable(boolean)}</li>
6206     * </ul>
6207     * <p>
6208     * Subclasses should override this method, call the super implementation,
6209     * and set additional attributes.
6210     * </p>
6211     * <p>
6212     * If an {@link AccessibilityDelegate} has been specified via calling
6213     * {@link #setAccessibilityDelegate(AccessibilityDelegate)} its
6214     * {@link AccessibilityDelegate#onInitializeAccessibilityNodeInfo(View, AccessibilityNodeInfo)}
6215     * is responsible for handling this call.
6216     * </p>
6217     *
6218     * @param info The instance to initialize.
6219     */
6220    @CallSuper
6221    public void onInitializeAccessibilityNodeInfo(AccessibilityNodeInfo info) {
6222        if (mAccessibilityDelegate != null) {
6223            mAccessibilityDelegate.onInitializeAccessibilityNodeInfo(this, info);
6224        } else {
6225            onInitializeAccessibilityNodeInfoInternal(info);
6226        }
6227    }
6228
6229    /**
6230     * Gets the location of this view in screen coordinates.
6231     *
6232     * @param outRect The output location
6233     * @hide
6234     */
6235    public void getBoundsOnScreen(Rect outRect) {
6236        getBoundsOnScreen(outRect, false);
6237    }
6238
6239    /**
6240     * Gets the location of this view in screen coordinates.
6241     *
6242     * @param outRect The output location
6243     * @param clipToParent Whether to clip child bounds to the parent ones.
6244     * @hide
6245     */
6246    public void getBoundsOnScreen(Rect outRect, boolean clipToParent) {
6247        if (mAttachInfo == null) {
6248            return;
6249        }
6250
6251        RectF position = mAttachInfo.mTmpTransformRect;
6252        position.set(0, 0, mRight - mLeft, mBottom - mTop);
6253
6254        if (!hasIdentityMatrix()) {
6255            getMatrix().mapRect(position);
6256        }
6257
6258        position.offset(mLeft, mTop);
6259
6260        ViewParent parent = mParent;
6261        while (parent instanceof View) {
6262            View parentView = (View) parent;
6263
6264            position.offset(-parentView.mScrollX, -parentView.mScrollY);
6265
6266            if (clipToParent) {
6267                position.left = Math.max(position.left, 0);
6268                position.top = Math.max(position.top, 0);
6269                position.right = Math.min(position.right, parentView.getWidth());
6270                position.bottom = Math.min(position.bottom, parentView.getHeight());
6271            }
6272
6273            if (!parentView.hasIdentityMatrix()) {
6274                parentView.getMatrix().mapRect(position);
6275            }
6276
6277            position.offset(parentView.mLeft, parentView.mTop);
6278
6279            parent = parentView.mParent;
6280        }
6281
6282        if (parent instanceof ViewRootImpl) {
6283            ViewRootImpl viewRootImpl = (ViewRootImpl) parent;
6284            position.offset(0, -viewRootImpl.mCurScrollY);
6285        }
6286
6287        position.offset(mAttachInfo.mWindowLeft, mAttachInfo.mWindowTop);
6288
6289        outRect.set((int) (position.left + 0.5f), (int) (position.top + 0.5f),
6290                (int) (position.right + 0.5f), (int) (position.bottom + 0.5f));
6291    }
6292
6293    /**
6294     * Return the class name of this object to be used for accessibility purposes.
6295     * Subclasses should only override this if they are implementing something that
6296     * should be seen as a completely new class of view when used by accessibility,
6297     * unrelated to the class it is deriving from.  This is used to fill in
6298     * {@link AccessibilityNodeInfo#setClassName AccessibilityNodeInfo.setClassName}.
6299     */
6300    public CharSequence getAccessibilityClassName() {
6301        return View.class.getName();
6302    }
6303
6304    /**
6305     * Called when assist structure is being retrieved from a view as part of
6306     * {@link android.app.Activity#onProvideAssistData Activity.onProvideAssistData}.
6307     * @param structure Fill in with structured view data.  The default implementation
6308     * fills in all data that can be inferred from the view itself.
6309     */
6310    public void onProvideStructure(ViewStructure structure) {
6311        final int id = mID;
6312        if (id > 0 && (id&0xff000000) != 0 && (id&0x00ff0000) != 0
6313                && (id&0x0000ffff) != 0) {
6314            String pkg, type, entry;
6315            try {
6316                final Resources res = getResources();
6317                entry = res.getResourceEntryName(id);
6318                type = res.getResourceTypeName(id);
6319                pkg = res.getResourcePackageName(id);
6320            } catch (Resources.NotFoundException e) {
6321                entry = type = pkg = null;
6322            }
6323            structure.setId(id, pkg, type, entry);
6324        } else {
6325            structure.setId(id, null, null, null);
6326        }
6327        structure.setDimens(mLeft, mTop, mScrollX, mScrollY, mRight - mLeft, mBottom - mTop);
6328        if (!hasIdentityMatrix()) {
6329            structure.setTransformation(getMatrix());
6330        }
6331        structure.setElevation(getZ());
6332        structure.setVisibility(getVisibility());
6333        structure.setEnabled(isEnabled());
6334        if (isClickable()) {
6335            structure.setClickable(true);
6336        }
6337        if (isFocusable()) {
6338            structure.setFocusable(true);
6339        }
6340        if (isFocused()) {
6341            structure.setFocused(true);
6342        }
6343        if (isAccessibilityFocused()) {
6344            structure.setAccessibilityFocused(true);
6345        }
6346        if (isSelected()) {
6347            structure.setSelected(true);
6348        }
6349        if (isActivated()) {
6350            structure.setActivated(true);
6351        }
6352        if (isLongClickable()) {
6353            structure.setLongClickable(true);
6354        }
6355        if (this instanceof Checkable) {
6356            structure.setCheckable(true);
6357            if (((Checkable)this).isChecked()) {
6358                structure.setChecked(true);
6359            }
6360        }
6361        if (isContextClickable()) {
6362            structure.setContextClickable(true);
6363        }
6364        structure.setClassName(getAccessibilityClassName().toString());
6365        structure.setContentDescription(getContentDescription());
6366    }
6367
6368    /**
6369     * Called when assist structure is being retrieved from a view as part of
6370     * {@link android.app.Activity#onProvideAssistData Activity.onProvideAssistData} to
6371     * generate additional virtual structure under this view.  The defaullt implementation
6372     * uses {@link #getAccessibilityNodeProvider()} to try to generate this from the
6373     * view's virtual accessibility nodes, if any.  You can override this for a more
6374     * optimal implementation providing this data.
6375     */
6376    public void onProvideVirtualStructure(ViewStructure structure) {
6377        AccessibilityNodeProvider provider = getAccessibilityNodeProvider();
6378        if (provider != null) {
6379            AccessibilityNodeInfo info = createAccessibilityNodeInfo();
6380            structure.setChildCount(1);
6381            ViewStructure root = structure.newChild(0);
6382            populateVirtualStructure(root, provider, info);
6383            info.recycle();
6384        }
6385    }
6386
6387    private void populateVirtualStructure(ViewStructure structure,
6388            AccessibilityNodeProvider provider, AccessibilityNodeInfo info) {
6389        structure.setId(AccessibilityNodeInfo.getVirtualDescendantId(info.getSourceNodeId()),
6390                null, null, null);
6391        Rect rect = structure.getTempRect();
6392        info.getBoundsInParent(rect);
6393        structure.setDimens(rect.left, rect.top, 0, 0, rect.width(), rect.height());
6394        structure.setVisibility(VISIBLE);
6395        structure.setEnabled(info.isEnabled());
6396        if (info.isClickable()) {
6397            structure.setClickable(true);
6398        }
6399        if (info.isFocusable()) {
6400            structure.setFocusable(true);
6401        }
6402        if (info.isFocused()) {
6403            structure.setFocused(true);
6404        }
6405        if (info.isAccessibilityFocused()) {
6406            structure.setAccessibilityFocused(true);
6407        }
6408        if (info.isSelected()) {
6409            structure.setSelected(true);
6410        }
6411        if (info.isLongClickable()) {
6412            structure.setLongClickable(true);
6413        }
6414        if (info.isCheckable()) {
6415            structure.setCheckable(true);
6416            if (info.isChecked()) {
6417                structure.setChecked(true);
6418            }
6419        }
6420        if (info.isContextClickable()) {
6421            structure.setContextClickable(true);
6422        }
6423        CharSequence cname = info.getClassName();
6424        structure.setClassName(cname != null ? cname.toString() : null);
6425        structure.setContentDescription(info.getContentDescription());
6426        if (info.getText() != null || info.getError() != null) {
6427            structure.setText(info.getText(), info.getTextSelectionStart(),
6428                    info.getTextSelectionEnd());
6429        }
6430        final int NCHILDREN = info.getChildCount();
6431        if (NCHILDREN > 0) {
6432            structure.setChildCount(NCHILDREN);
6433            for (int i=0; i<NCHILDREN; i++) {
6434                AccessibilityNodeInfo cinfo = provider.createAccessibilityNodeInfo(
6435                        AccessibilityNodeInfo.getVirtualDescendantId(info.getChildId(i)));
6436                ViewStructure child = structure.newChild(i);
6437                populateVirtualStructure(child, provider, cinfo);
6438                cinfo.recycle();
6439            }
6440        }
6441    }
6442
6443    /**
6444     * Dispatch creation of {@link ViewStructure} down the hierarchy.  The default
6445     * implementation calls {@link #onProvideStructure} and
6446     * {@link #onProvideVirtualStructure}.
6447     */
6448    public void dispatchProvideStructure(ViewStructure structure) {
6449        if (!isAssistBlocked()) {
6450            onProvideStructure(structure);
6451            onProvideVirtualStructure(structure);
6452        } else {
6453            structure.setClassName(getAccessibilityClassName().toString());
6454            structure.setAssistBlocked(true);
6455        }
6456    }
6457
6458    /**
6459     * @see #onInitializeAccessibilityNodeInfo(AccessibilityNodeInfo)
6460     *
6461     * Note: Called from the default {@link AccessibilityDelegate}.
6462     *
6463     * @hide
6464     */
6465    public void onInitializeAccessibilityNodeInfoInternal(AccessibilityNodeInfo info) {
6466        if (mAttachInfo == null) {
6467            return;
6468        }
6469
6470        Rect bounds = mAttachInfo.mTmpInvalRect;
6471
6472        getDrawingRect(bounds);
6473        info.setBoundsInParent(bounds);
6474
6475        getBoundsOnScreen(bounds, true);
6476        info.setBoundsInScreen(bounds);
6477
6478        ViewParent parent = getParentForAccessibility();
6479        if (parent instanceof View) {
6480            info.setParent((View) parent);
6481        }
6482
6483        if (mID != View.NO_ID) {
6484            View rootView = getRootView();
6485            if (rootView == null) {
6486                rootView = this;
6487            }
6488
6489            View label = rootView.findLabelForView(this, mID);
6490            if (label != null) {
6491                info.setLabeledBy(label);
6492            }
6493
6494            if ((mAttachInfo.mAccessibilityFetchFlags
6495                    & AccessibilityNodeInfo.FLAG_REPORT_VIEW_IDS) != 0
6496                    && Resources.resourceHasPackage(mID)) {
6497                try {
6498                    String viewId = getResources().getResourceName(mID);
6499                    info.setViewIdResourceName(viewId);
6500                } catch (Resources.NotFoundException nfe) {
6501                    /* ignore */
6502                }
6503            }
6504        }
6505
6506        if (mLabelForId != View.NO_ID) {
6507            View rootView = getRootView();
6508            if (rootView == null) {
6509                rootView = this;
6510            }
6511            View labeled = rootView.findViewInsideOutShouldExist(this, mLabelForId);
6512            if (labeled != null) {
6513                info.setLabelFor(labeled);
6514            }
6515        }
6516
6517        if (mAccessibilityTraversalBeforeId != View.NO_ID) {
6518            View rootView = getRootView();
6519            if (rootView == null) {
6520                rootView = this;
6521            }
6522            View next = rootView.findViewInsideOutShouldExist(this,
6523                    mAccessibilityTraversalBeforeId);
6524            if (next != null && next.includeForAccessibility()) {
6525                info.setTraversalBefore(next);
6526            }
6527        }
6528
6529        if (mAccessibilityTraversalAfterId != View.NO_ID) {
6530            View rootView = getRootView();
6531            if (rootView == null) {
6532                rootView = this;
6533            }
6534            View next = rootView.findViewInsideOutShouldExist(this,
6535                    mAccessibilityTraversalAfterId);
6536            if (next != null && next.includeForAccessibility()) {
6537                info.setTraversalAfter(next);
6538            }
6539        }
6540
6541        info.setVisibleToUser(isVisibleToUser());
6542
6543        info.setPackageName(mContext.getPackageName());
6544        info.setClassName(getAccessibilityClassName());
6545        info.setContentDescription(getContentDescription());
6546
6547        info.setEnabled(isEnabled());
6548        info.setClickable(isClickable());
6549        info.setFocusable(isFocusable());
6550        info.setFocused(isFocused());
6551        info.setAccessibilityFocused(isAccessibilityFocused());
6552        info.setSelected(isSelected());
6553        info.setLongClickable(isLongClickable());
6554        info.setContextClickable(isContextClickable());
6555        info.setLiveRegion(getAccessibilityLiveRegion());
6556
6557        // TODO: These make sense only if we are in an AdapterView but all
6558        // views can be selected. Maybe from accessibility perspective
6559        // we should report as selectable view in an AdapterView.
6560        info.addAction(AccessibilityNodeInfo.ACTION_SELECT);
6561        info.addAction(AccessibilityNodeInfo.ACTION_CLEAR_SELECTION);
6562
6563        if (isFocusable()) {
6564            if (isFocused()) {
6565                info.addAction(AccessibilityNodeInfo.ACTION_CLEAR_FOCUS);
6566            } else {
6567                info.addAction(AccessibilityNodeInfo.ACTION_FOCUS);
6568            }
6569        }
6570
6571        if (!isAccessibilityFocused()) {
6572            info.addAction(AccessibilityNodeInfo.ACTION_ACCESSIBILITY_FOCUS);
6573        } else {
6574            info.addAction(AccessibilityNodeInfo.ACTION_CLEAR_ACCESSIBILITY_FOCUS);
6575        }
6576
6577        if (isClickable() && isEnabled()) {
6578            info.addAction(AccessibilityNodeInfo.ACTION_CLICK);
6579        }
6580
6581        if (isLongClickable() && isEnabled()) {
6582            info.addAction(AccessibilityNodeInfo.ACTION_LONG_CLICK);
6583        }
6584
6585        if (isContextClickable() && isEnabled()) {
6586            info.addAction(AccessibilityAction.ACTION_CONTEXT_CLICK);
6587        }
6588
6589        CharSequence text = getIterableTextForAccessibility();
6590        if (text != null && text.length() > 0) {
6591            info.setTextSelection(getAccessibilitySelectionStart(), getAccessibilitySelectionEnd());
6592
6593            info.addAction(AccessibilityNodeInfo.ACTION_SET_SELECTION);
6594            info.addAction(AccessibilityNodeInfo.ACTION_NEXT_AT_MOVEMENT_GRANULARITY);
6595            info.addAction(AccessibilityNodeInfo.ACTION_PREVIOUS_AT_MOVEMENT_GRANULARITY);
6596            info.setMovementGranularities(AccessibilityNodeInfo.MOVEMENT_GRANULARITY_CHARACTER
6597                    | AccessibilityNodeInfo.MOVEMENT_GRANULARITY_WORD
6598                    | AccessibilityNodeInfo.MOVEMENT_GRANULARITY_PARAGRAPH);
6599        }
6600
6601        info.addAction(AccessibilityAction.ACTION_SHOW_ON_SCREEN);
6602    }
6603
6604    private View findLabelForView(View view, int labeledId) {
6605        if (mMatchLabelForPredicate == null) {
6606            mMatchLabelForPredicate = new MatchLabelForPredicate();
6607        }
6608        mMatchLabelForPredicate.mLabeledId = labeledId;
6609        return findViewByPredicateInsideOut(view, mMatchLabelForPredicate);
6610    }
6611
6612    /**
6613     * Computes whether this view is visible to the user. Such a view is
6614     * attached, visible, all its predecessors are visible, it is not clipped
6615     * entirely by its predecessors, and has an alpha greater than zero.
6616     *
6617     * @return Whether the view is visible on the screen.
6618     *
6619     * @hide
6620     */
6621    protected boolean isVisibleToUser() {
6622        return isVisibleToUser(null);
6623    }
6624
6625    /**
6626     * Computes whether the given portion of this view is visible to the user.
6627     * Such a view is attached, visible, all its predecessors are visible,
6628     * has an alpha greater than zero, and the specified portion is not
6629     * clipped entirely by its predecessors.
6630     *
6631     * @param boundInView the portion of the view to test; coordinates should be relative; may be
6632     *                    <code>null</code>, and the entire view will be tested in this case.
6633     *                    When <code>true</code> is returned by the function, the actual visible
6634     *                    region will be stored in this parameter; that is, if boundInView is fully
6635     *                    contained within the view, no modification will be made, otherwise regions
6636     *                    outside of the visible area of the view will be clipped.
6637     *
6638     * @return Whether the specified portion of the view is visible on the screen.
6639     *
6640     * @hide
6641     */
6642    protected boolean isVisibleToUser(Rect boundInView) {
6643        if (mAttachInfo != null) {
6644            // Attached to invisible window means this view is not visible.
6645            if (mAttachInfo.mWindowVisibility != View.VISIBLE) {
6646                return false;
6647            }
6648            // An invisible predecessor or one with alpha zero means
6649            // that this view is not visible to the user.
6650            Object current = this;
6651            while (current instanceof View) {
6652                View view = (View) current;
6653                // We have attach info so this view is attached and there is no
6654                // need to check whether we reach to ViewRootImpl on the way up.
6655                if (view.getAlpha() <= 0 || view.getTransitionAlpha() <= 0 ||
6656                        view.getVisibility() != VISIBLE) {
6657                    return false;
6658                }
6659                current = view.mParent;
6660            }
6661            // Check if the view is entirely covered by its predecessors.
6662            Rect visibleRect = mAttachInfo.mTmpInvalRect;
6663            Point offset = mAttachInfo.mPoint;
6664            if (!getGlobalVisibleRect(visibleRect, offset)) {
6665                return false;
6666            }
6667            // Check if the visible portion intersects the rectangle of interest.
6668            if (boundInView != null) {
6669                visibleRect.offset(-offset.x, -offset.y);
6670                return boundInView.intersect(visibleRect);
6671            }
6672            return true;
6673        }
6674        return false;
6675    }
6676
6677    /**
6678     * Returns the delegate for implementing accessibility support via
6679     * composition. For more details see {@link AccessibilityDelegate}.
6680     *
6681     * @return The delegate, or null if none set.
6682     *
6683     * @hide
6684     */
6685    public AccessibilityDelegate getAccessibilityDelegate() {
6686        return mAccessibilityDelegate;
6687    }
6688
6689    /**
6690     * Sets a delegate for implementing accessibility support via composition
6691     * (as opposed to inheritance). For more details, see
6692     * {@link AccessibilityDelegate}.
6693     * <p>
6694     * <strong>Note:</strong> On platform versions prior to
6695     * {@link android.os.Build.VERSION_CODES#M API 23}, delegate methods on
6696     * views in the {@code android.widget.*} package are called <i>before</i>
6697     * host methods. This prevents certain properties such as class name from
6698     * being modified by overriding
6699     * {@link AccessibilityDelegate#onInitializeAccessibilityNodeInfo(View, AccessibilityNodeInfo)},
6700     * as any changes will be overwritten by the host class.
6701     * <p>
6702     * Starting in {@link android.os.Build.VERSION_CODES#M API 23}, delegate
6703     * methods are called <i>after</i> host methods, which all properties to be
6704     * modified without being overwritten by the host class.
6705     *
6706     * @param delegate the object to which accessibility method calls should be
6707     *                 delegated
6708     * @see AccessibilityDelegate
6709     */
6710    public void setAccessibilityDelegate(@Nullable AccessibilityDelegate delegate) {
6711        mAccessibilityDelegate = delegate;
6712    }
6713
6714    /**
6715     * Gets the provider for managing a virtual view hierarchy rooted at this View
6716     * and reported to {@link android.accessibilityservice.AccessibilityService}s
6717     * that explore the window content.
6718     * <p>
6719     * If this method returns an instance, this instance is responsible for managing
6720     * {@link AccessibilityNodeInfo}s describing the virtual sub-tree rooted at this
6721     * View including the one representing the View itself. Similarly the returned
6722     * instance is responsible for performing accessibility actions on any virtual
6723     * view or the root view itself.
6724     * </p>
6725     * <p>
6726     * If an {@link AccessibilityDelegate} has been specified via calling
6727     * {@link #setAccessibilityDelegate(AccessibilityDelegate)} its
6728     * {@link AccessibilityDelegate#getAccessibilityNodeProvider(View)}
6729     * is responsible for handling this call.
6730     * </p>
6731     *
6732     * @return The provider.
6733     *
6734     * @see AccessibilityNodeProvider
6735     */
6736    public AccessibilityNodeProvider getAccessibilityNodeProvider() {
6737        if (mAccessibilityDelegate != null) {
6738            return mAccessibilityDelegate.getAccessibilityNodeProvider(this);
6739        } else {
6740            return null;
6741        }
6742    }
6743
6744    /**
6745     * Gets the unique identifier of this view on the screen for accessibility purposes.
6746     * If this {@link View} is not attached to any window, {@value #NO_ID} is returned.
6747     *
6748     * @return The view accessibility id.
6749     *
6750     * @hide
6751     */
6752    public int getAccessibilityViewId() {
6753        if (mAccessibilityViewId == NO_ID) {
6754            mAccessibilityViewId = sNextAccessibilityViewId++;
6755        }
6756        return mAccessibilityViewId;
6757    }
6758
6759    /**
6760     * Gets the unique identifier of the window in which this View reseides.
6761     *
6762     * @return The window accessibility id.
6763     *
6764     * @hide
6765     */
6766    public int getAccessibilityWindowId() {
6767        return mAttachInfo != null ? mAttachInfo.mAccessibilityWindowId
6768                : AccessibilityNodeInfo.UNDEFINED_ITEM_ID;
6769    }
6770
6771    /**
6772     * Returns the {@link View}'s content description.
6773     * <p>
6774     * <strong>Note:</strong> Do not override this method, as it will have no
6775     * effect on the content description presented to accessibility services.
6776     * You must call {@link #setContentDescription(CharSequence)} to modify the
6777     * content description.
6778     *
6779     * @return the content description
6780     * @see #setContentDescription(CharSequence)
6781     * @attr ref android.R.styleable#View_contentDescription
6782     */
6783    @ViewDebug.ExportedProperty(category = "accessibility")
6784    public CharSequence getContentDescription() {
6785        return mContentDescription;
6786    }
6787
6788    /**
6789     * Sets the {@link View}'s content description.
6790     * <p>
6791     * A content description briefly describes the view and is primarily used
6792     * for accessibility support to determine how a view should be presented to
6793     * the user. In the case of a view with no textual representation, such as
6794     * {@link android.widget.ImageButton}, a useful content description
6795     * explains what the view does. For example, an image button with a phone
6796     * icon that is used to place a call may use "Call" as its content
6797     * description. An image of a floppy disk that is used to save a file may
6798     * use "Save".
6799     *
6800     * @param contentDescription The content description.
6801     * @see #getContentDescription()
6802     * @attr ref android.R.styleable#View_contentDescription
6803     */
6804    @RemotableViewMethod
6805    public void setContentDescription(CharSequence contentDescription) {
6806        if (mContentDescription == null) {
6807            if (contentDescription == null) {
6808                return;
6809            }
6810        } else if (mContentDescription.equals(contentDescription)) {
6811            return;
6812        }
6813        mContentDescription = contentDescription;
6814        final boolean nonEmptyDesc = contentDescription != null && contentDescription.length() > 0;
6815        if (nonEmptyDesc && getImportantForAccessibility() == IMPORTANT_FOR_ACCESSIBILITY_AUTO) {
6816            setImportantForAccessibility(IMPORTANT_FOR_ACCESSIBILITY_YES);
6817            notifySubtreeAccessibilityStateChangedIfNeeded();
6818        } else {
6819            notifyViewAccessibilityStateChangedIfNeeded(
6820                    AccessibilityEvent.CONTENT_CHANGE_TYPE_CONTENT_DESCRIPTION);
6821        }
6822    }
6823
6824    /**
6825     * Sets the id of a view before which this one is visited in accessibility traversal.
6826     * A screen-reader must visit the content of this view before the content of the one
6827     * it precedes. For example, if view B is set to be before view A, then a screen-reader
6828     * will traverse the entire content of B before traversing the entire content of A,
6829     * regardles of what traversal strategy it is using.
6830     * <p>
6831     * Views that do not have specified before/after relationships are traversed in order
6832     * determined by the screen-reader.
6833     * </p>
6834     * <p>
6835     * Setting that this view is before a view that is not important for accessibility
6836     * or if this view is not important for accessibility will have no effect as the
6837     * screen-reader is not aware of unimportant views.
6838     * </p>
6839     *
6840     * @param beforeId The id of a view this one precedes in accessibility traversal.
6841     *
6842     * @attr ref android.R.styleable#View_accessibilityTraversalBefore
6843     *
6844     * @see #setImportantForAccessibility(int)
6845     */
6846    @RemotableViewMethod
6847    public void setAccessibilityTraversalBefore(int beforeId) {
6848        if (mAccessibilityTraversalBeforeId == beforeId) {
6849            return;
6850        }
6851        mAccessibilityTraversalBeforeId = beforeId;
6852        notifyViewAccessibilityStateChangedIfNeeded(
6853                AccessibilityEvent.CONTENT_CHANGE_TYPE_UNDEFINED);
6854    }
6855
6856    /**
6857     * Gets the id of a view before which this one is visited in accessibility traversal.
6858     *
6859     * @return The id of a view this one precedes in accessibility traversal if
6860     *         specified, otherwise {@link #NO_ID}.
6861     *
6862     * @see #setAccessibilityTraversalBefore(int)
6863     */
6864    public int getAccessibilityTraversalBefore() {
6865        return mAccessibilityTraversalBeforeId;
6866    }
6867
6868    /**
6869     * Sets the id of a view after which this one is visited in accessibility traversal.
6870     * A screen-reader must visit the content of the other view before the content of this
6871     * one. For example, if view B is set to be after view A, then a screen-reader
6872     * will traverse the entire content of A before traversing the entire content of B,
6873     * regardles of what traversal strategy it is using.
6874     * <p>
6875     * Views that do not have specified before/after relationships are traversed in order
6876     * determined by the screen-reader.
6877     * </p>
6878     * <p>
6879     * Setting that this view is after a view that is not important for accessibility
6880     * or if this view is not important for accessibility will have no effect as the
6881     * screen-reader is not aware of unimportant views.
6882     * </p>
6883     *
6884     * @param afterId The id of a view this one succedees in accessibility traversal.
6885     *
6886     * @attr ref android.R.styleable#View_accessibilityTraversalAfter
6887     *
6888     * @see #setImportantForAccessibility(int)
6889     */
6890    @RemotableViewMethod
6891    public void setAccessibilityTraversalAfter(int afterId) {
6892        if (mAccessibilityTraversalAfterId == afterId) {
6893            return;
6894        }
6895        mAccessibilityTraversalAfterId = afterId;
6896        notifyViewAccessibilityStateChangedIfNeeded(
6897                AccessibilityEvent.CONTENT_CHANGE_TYPE_UNDEFINED);
6898    }
6899
6900    /**
6901     * Gets the id of a view after which this one is visited in accessibility traversal.
6902     *
6903     * @return The id of a view this one succeedes in accessibility traversal if
6904     *         specified, otherwise {@link #NO_ID}.
6905     *
6906     * @see #setAccessibilityTraversalAfter(int)
6907     */
6908    public int getAccessibilityTraversalAfter() {
6909        return mAccessibilityTraversalAfterId;
6910    }
6911
6912    /**
6913     * Gets the id of a view for which this view serves as a label for
6914     * accessibility purposes.
6915     *
6916     * @return The labeled view id.
6917     */
6918    @ViewDebug.ExportedProperty(category = "accessibility")
6919    public int getLabelFor() {
6920        return mLabelForId;
6921    }
6922
6923    /**
6924     * Sets the id of a view for which this view serves as a label for
6925     * accessibility purposes.
6926     *
6927     * @param id The labeled view id.
6928     */
6929    @RemotableViewMethod
6930    public void setLabelFor(@IdRes int id) {
6931        if (mLabelForId == id) {
6932            return;
6933        }
6934        mLabelForId = id;
6935        if (mLabelForId != View.NO_ID
6936                && mID == View.NO_ID) {
6937            mID = generateViewId();
6938        }
6939        notifyViewAccessibilityStateChangedIfNeeded(
6940                AccessibilityEvent.CONTENT_CHANGE_TYPE_UNDEFINED);
6941    }
6942
6943    /**
6944     * Invoked whenever this view loses focus, either by losing window focus or by losing
6945     * focus within its window. This method can be used to clear any state tied to the
6946     * focus. For instance, if a button is held pressed with the trackball and the window
6947     * loses focus, this method can be used to cancel the press.
6948     *
6949     * Subclasses of View overriding this method should always call super.onFocusLost().
6950     *
6951     * @see #onFocusChanged(boolean, int, android.graphics.Rect)
6952     * @see #onWindowFocusChanged(boolean)
6953     *
6954     * @hide pending API council approval
6955     */
6956    @CallSuper
6957    protected void onFocusLost() {
6958        resetPressedState();
6959    }
6960
6961    private void resetPressedState() {
6962        if ((mViewFlags & ENABLED_MASK) == DISABLED) {
6963            return;
6964        }
6965
6966        if (isPressed()) {
6967            setPressed(false);
6968
6969            if (!mHasPerformedLongPress) {
6970                removeLongPressCallback();
6971            }
6972        }
6973    }
6974
6975    /**
6976     * Returns true if this view has focus
6977     *
6978     * @return True if this view has focus, false otherwise.
6979     */
6980    @ViewDebug.ExportedProperty(category = "focus")
6981    public boolean isFocused() {
6982        return (mPrivateFlags & PFLAG_FOCUSED) != 0;
6983    }
6984
6985    /**
6986     * Find the view in the hierarchy rooted at this view that currently has
6987     * focus.
6988     *
6989     * @return The view that currently has focus, or null if no focused view can
6990     *         be found.
6991     */
6992    public View findFocus() {
6993        return (mPrivateFlags & PFLAG_FOCUSED) != 0 ? this : null;
6994    }
6995
6996    /**
6997     * Indicates whether this view is one of the set of scrollable containers in
6998     * its window.
6999     *
7000     * @return whether this view is one of the set of scrollable containers in
7001     * its window
7002     *
7003     * @attr ref android.R.styleable#View_isScrollContainer
7004     */
7005    public boolean isScrollContainer() {
7006        return (mPrivateFlags & PFLAG_SCROLL_CONTAINER_ADDED) != 0;
7007    }
7008
7009    /**
7010     * Change whether this view is one of the set of scrollable containers in
7011     * its window.  This will be used to determine whether the window can
7012     * resize or must pan when a soft input area is open -- scrollable
7013     * containers allow the window to use resize mode since the container
7014     * will appropriately shrink.
7015     *
7016     * @attr ref android.R.styleable#View_isScrollContainer
7017     */
7018    public void setScrollContainer(boolean isScrollContainer) {
7019        if (isScrollContainer) {
7020            if (mAttachInfo != null && (mPrivateFlags&PFLAG_SCROLL_CONTAINER_ADDED) == 0) {
7021                mAttachInfo.mScrollContainers.add(this);
7022                mPrivateFlags |= PFLAG_SCROLL_CONTAINER_ADDED;
7023            }
7024            mPrivateFlags |= PFLAG_SCROLL_CONTAINER;
7025        } else {
7026            if ((mPrivateFlags&PFLAG_SCROLL_CONTAINER_ADDED) != 0) {
7027                mAttachInfo.mScrollContainers.remove(this);
7028            }
7029            mPrivateFlags &= ~(PFLAG_SCROLL_CONTAINER|PFLAG_SCROLL_CONTAINER_ADDED);
7030        }
7031    }
7032
7033    /**
7034     * Returns the quality of the drawing cache.
7035     *
7036     * @return One of {@link #DRAWING_CACHE_QUALITY_AUTO},
7037     *         {@link #DRAWING_CACHE_QUALITY_LOW}, or {@link #DRAWING_CACHE_QUALITY_HIGH}
7038     *
7039     * @see #setDrawingCacheQuality(int)
7040     * @see #setDrawingCacheEnabled(boolean)
7041     * @see #isDrawingCacheEnabled()
7042     *
7043     * @attr ref android.R.styleable#View_drawingCacheQuality
7044     */
7045    @DrawingCacheQuality
7046    public int getDrawingCacheQuality() {
7047        return mViewFlags & DRAWING_CACHE_QUALITY_MASK;
7048    }
7049
7050    /**
7051     * Set the drawing cache quality of this view. This value is used only when the
7052     * drawing cache is enabled
7053     *
7054     * @param quality One of {@link #DRAWING_CACHE_QUALITY_AUTO},
7055     *        {@link #DRAWING_CACHE_QUALITY_LOW}, or {@link #DRAWING_CACHE_QUALITY_HIGH}
7056     *
7057     * @see #getDrawingCacheQuality()
7058     * @see #setDrawingCacheEnabled(boolean)
7059     * @see #isDrawingCacheEnabled()
7060     *
7061     * @attr ref android.R.styleable#View_drawingCacheQuality
7062     */
7063    public void setDrawingCacheQuality(@DrawingCacheQuality int quality) {
7064        setFlags(quality, DRAWING_CACHE_QUALITY_MASK);
7065    }
7066
7067    /**
7068     * Returns whether the screen should remain on, corresponding to the current
7069     * value of {@link #KEEP_SCREEN_ON}.
7070     *
7071     * @return Returns true if {@link #KEEP_SCREEN_ON} is set.
7072     *
7073     * @see #setKeepScreenOn(boolean)
7074     *
7075     * @attr ref android.R.styleable#View_keepScreenOn
7076     */
7077    public boolean getKeepScreenOn() {
7078        return (mViewFlags & KEEP_SCREEN_ON) != 0;
7079    }
7080
7081    /**
7082     * Controls whether the screen should remain on, modifying the
7083     * value of {@link #KEEP_SCREEN_ON}.
7084     *
7085     * @param keepScreenOn Supply true to set {@link #KEEP_SCREEN_ON}.
7086     *
7087     * @see #getKeepScreenOn()
7088     *
7089     * @attr ref android.R.styleable#View_keepScreenOn
7090     */
7091    public void setKeepScreenOn(boolean keepScreenOn) {
7092        setFlags(keepScreenOn ? KEEP_SCREEN_ON : 0, KEEP_SCREEN_ON);
7093    }
7094
7095    /**
7096     * Gets the id of the view to use when the next focus is {@link #FOCUS_LEFT}.
7097     * @return The next focus ID, or {@link #NO_ID} if the framework should decide automatically.
7098     *
7099     * @attr ref android.R.styleable#View_nextFocusLeft
7100     */
7101    public int getNextFocusLeftId() {
7102        return mNextFocusLeftId;
7103    }
7104
7105    /**
7106     * Sets the id of the view to use when the next focus is {@link #FOCUS_LEFT}.
7107     * @param nextFocusLeftId The next focus ID, or {@link #NO_ID} if the framework should
7108     * decide automatically.
7109     *
7110     * @attr ref android.R.styleable#View_nextFocusLeft
7111     */
7112    public void setNextFocusLeftId(int nextFocusLeftId) {
7113        mNextFocusLeftId = nextFocusLeftId;
7114    }
7115
7116    /**
7117     * Gets the id of the view to use when the next focus is {@link #FOCUS_RIGHT}.
7118     * @return The next focus ID, or {@link #NO_ID} if the framework should decide automatically.
7119     *
7120     * @attr ref android.R.styleable#View_nextFocusRight
7121     */
7122    public int getNextFocusRightId() {
7123        return mNextFocusRightId;
7124    }
7125
7126    /**
7127     * Sets the id of the view to use when the next focus is {@link #FOCUS_RIGHT}.
7128     * @param nextFocusRightId The next focus ID, or {@link #NO_ID} if the framework should
7129     * decide automatically.
7130     *
7131     * @attr ref android.R.styleable#View_nextFocusRight
7132     */
7133    public void setNextFocusRightId(int nextFocusRightId) {
7134        mNextFocusRightId = nextFocusRightId;
7135    }
7136
7137    /**
7138     * Gets the id of the view to use when the next focus is {@link #FOCUS_UP}.
7139     * @return The next focus ID, or {@link #NO_ID} if the framework should decide automatically.
7140     *
7141     * @attr ref android.R.styleable#View_nextFocusUp
7142     */
7143    public int getNextFocusUpId() {
7144        return mNextFocusUpId;
7145    }
7146
7147    /**
7148     * Sets the id of the view to use when the next focus is {@link #FOCUS_UP}.
7149     * @param nextFocusUpId The next focus ID, or {@link #NO_ID} if the framework should
7150     * decide automatically.
7151     *
7152     * @attr ref android.R.styleable#View_nextFocusUp
7153     */
7154    public void setNextFocusUpId(int nextFocusUpId) {
7155        mNextFocusUpId = nextFocusUpId;
7156    }
7157
7158    /**
7159     * Gets the id of the view to use when the next focus is {@link #FOCUS_DOWN}.
7160     * @return The next focus ID, or {@link #NO_ID} if the framework should decide automatically.
7161     *
7162     * @attr ref android.R.styleable#View_nextFocusDown
7163     */
7164    public int getNextFocusDownId() {
7165        return mNextFocusDownId;
7166    }
7167
7168    /**
7169     * Sets the id of the view to use when the next focus is {@link #FOCUS_DOWN}.
7170     * @param nextFocusDownId The next focus ID, or {@link #NO_ID} if the framework should
7171     * decide automatically.
7172     *
7173     * @attr ref android.R.styleable#View_nextFocusDown
7174     */
7175    public void setNextFocusDownId(int nextFocusDownId) {
7176        mNextFocusDownId = nextFocusDownId;
7177    }
7178
7179    /**
7180     * Gets the id of the view to use when the next focus is {@link #FOCUS_FORWARD}.
7181     * @return The next focus ID, or {@link #NO_ID} if the framework should decide automatically.
7182     *
7183     * @attr ref android.R.styleable#View_nextFocusForward
7184     */
7185    public int getNextFocusForwardId() {
7186        return mNextFocusForwardId;
7187    }
7188
7189    /**
7190     * Sets the id of the view to use when the next focus is {@link #FOCUS_FORWARD}.
7191     * @param nextFocusForwardId The next focus ID, or {@link #NO_ID} if the framework should
7192     * decide automatically.
7193     *
7194     * @attr ref android.R.styleable#View_nextFocusForward
7195     */
7196    public void setNextFocusForwardId(int nextFocusForwardId) {
7197        mNextFocusForwardId = nextFocusForwardId;
7198    }
7199
7200    /**
7201     * Returns the visibility of this view and all of its ancestors
7202     *
7203     * @return True if this view and all of its ancestors are {@link #VISIBLE}
7204     */
7205    public boolean isShown() {
7206        View current = this;
7207        //noinspection ConstantConditions
7208        do {
7209            if ((current.mViewFlags & VISIBILITY_MASK) != VISIBLE) {
7210                return false;
7211            }
7212            ViewParent parent = current.mParent;
7213            if (parent == null) {
7214                return false; // We are not attached to the view root
7215            }
7216            if (!(parent instanceof View)) {
7217                return true;
7218            }
7219            current = (View) parent;
7220        } while (current != null);
7221
7222        return false;
7223    }
7224
7225    /**
7226     * Called by the view hierarchy when the content insets for a window have
7227     * changed, to allow it to adjust its content to fit within those windows.
7228     * The content insets tell you the space that the status bar, input method,
7229     * and other system windows infringe on the application's window.
7230     *
7231     * <p>You do not normally need to deal with this function, since the default
7232     * window decoration given to applications takes care of applying it to the
7233     * content of the window.  If you use {@link #SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN}
7234     * or {@link #SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION} this will not be the case,
7235     * and your content can be placed under those system elements.  You can then
7236     * use this method within your view hierarchy if you have parts of your UI
7237     * which you would like to ensure are not being covered.
7238     *
7239     * <p>The default implementation of this method simply applies the content
7240     * insets to the view's padding, consuming that content (modifying the
7241     * insets to be 0), and returning true.  This behavior is off by default, but can
7242     * be enabled through {@link #setFitsSystemWindows(boolean)}.
7243     *
7244     * <p>This function's traversal down the hierarchy is depth-first.  The same content
7245     * insets object is propagated down the hierarchy, so any changes made to it will
7246     * be seen by all following views (including potentially ones above in
7247     * the hierarchy since this is a depth-first traversal).  The first view
7248     * that returns true will abort the entire traversal.
7249     *
7250     * <p>The default implementation works well for a situation where it is
7251     * used with a container that covers the entire window, allowing it to
7252     * apply the appropriate insets to its content on all edges.  If you need
7253     * a more complicated layout (such as two different views fitting system
7254     * windows, one on the top of the window, and one on the bottom),
7255     * you can override the method and handle the insets however you would like.
7256     * Note that the insets provided by the framework are always relative to the
7257     * far edges of the window, not accounting for the location of the called view
7258     * within that window.  (In fact when this method is called you do not yet know
7259     * where the layout will place the view, as it is done before layout happens.)
7260     *
7261     * <p>Note: unlike many View methods, there is no dispatch phase to this
7262     * call.  If you are overriding it in a ViewGroup and want to allow the
7263     * call to continue to your children, you must be sure to call the super
7264     * implementation.
7265     *
7266     * <p>Here is a sample layout that makes use of fitting system windows
7267     * to have controls for a video view placed inside of the window decorations
7268     * that it hides and shows.  This can be used with code like the second
7269     * sample (video player) shown in {@link #setSystemUiVisibility(int)}.
7270     *
7271     * {@sample development/samples/ApiDemos/res/layout/video_player.xml complete}
7272     *
7273     * @param insets Current content insets of the window.  Prior to
7274     * {@link android.os.Build.VERSION_CODES#JELLY_BEAN} you must not modify
7275     * the insets or else you and Android will be unhappy.
7276     *
7277     * @return {@code true} if this view applied the insets and it should not
7278     * continue propagating further down the hierarchy, {@code false} otherwise.
7279     * @see #getFitsSystemWindows()
7280     * @see #setFitsSystemWindows(boolean)
7281     * @see #setSystemUiVisibility(int)
7282     *
7283     * @deprecated As of API 20 use {@link #dispatchApplyWindowInsets(WindowInsets)} to apply
7284     * insets to views. Views should override {@link #onApplyWindowInsets(WindowInsets)} or use
7285     * {@link #setOnApplyWindowInsetsListener(android.view.View.OnApplyWindowInsetsListener)}
7286     * to implement handling their own insets.
7287     */
7288    protected boolean fitSystemWindows(Rect insets) {
7289        if ((mPrivateFlags3 & PFLAG3_APPLYING_INSETS) == 0) {
7290            if (insets == null) {
7291                // Null insets by definition have already been consumed.
7292                // This call cannot apply insets since there are none to apply,
7293                // so return false.
7294                return false;
7295            }
7296            // If we're not in the process of dispatching the newer apply insets call,
7297            // that means we're not in the compatibility path. Dispatch into the newer
7298            // apply insets path and take things from there.
7299            try {
7300                mPrivateFlags3 |= PFLAG3_FITTING_SYSTEM_WINDOWS;
7301                return dispatchApplyWindowInsets(new WindowInsets(insets)).isConsumed();
7302            } finally {
7303                mPrivateFlags3 &= ~PFLAG3_FITTING_SYSTEM_WINDOWS;
7304            }
7305        } else {
7306            // We're being called from the newer apply insets path.
7307            // Perform the standard fallback behavior.
7308            return fitSystemWindowsInt(insets);
7309        }
7310    }
7311
7312    private boolean fitSystemWindowsInt(Rect insets) {
7313        if ((mViewFlags & FITS_SYSTEM_WINDOWS) == FITS_SYSTEM_WINDOWS) {
7314            mUserPaddingStart = UNDEFINED_PADDING;
7315            mUserPaddingEnd = UNDEFINED_PADDING;
7316            Rect localInsets = sThreadLocal.get();
7317            if (localInsets == null) {
7318                localInsets = new Rect();
7319                sThreadLocal.set(localInsets);
7320            }
7321            boolean res = computeFitSystemWindows(insets, localInsets);
7322            mUserPaddingLeftInitial = localInsets.left;
7323            mUserPaddingRightInitial = localInsets.right;
7324            internalSetPadding(localInsets.left, localInsets.top,
7325                    localInsets.right, localInsets.bottom);
7326            return res;
7327        }
7328        return false;
7329    }
7330
7331    /**
7332     * Called when the view should apply {@link WindowInsets} according to its internal policy.
7333     *
7334     * <p>This method should be overridden by views that wish to apply a policy different from or
7335     * in addition to the default behavior. Clients that wish to force a view subtree
7336     * to apply insets should call {@link #dispatchApplyWindowInsets(WindowInsets)}.</p>
7337     *
7338     * <p>Clients may supply an {@link OnApplyWindowInsetsListener} to a view. If one is set
7339     * it will be called during dispatch instead of this method. The listener may optionally
7340     * call this method from its own implementation if it wishes to apply the view's default
7341     * insets policy in addition to its own.</p>
7342     *
7343     * <p>Implementations of this method should either return the insets parameter unchanged
7344     * or a new {@link WindowInsets} cloned from the supplied insets with any insets consumed
7345     * that this view applied itself. This allows new inset types added in future platform
7346     * versions to pass through existing implementations unchanged without being erroneously
7347     * consumed.</p>
7348     *
7349     * <p>By default if a view's {@link #setFitsSystemWindows(boolean) fitsSystemWindows}
7350     * property is set then the view will consume the system window insets and apply them
7351     * as padding for the view.</p>
7352     *
7353     * @param insets Insets to apply
7354     * @return The supplied insets with any applied insets consumed
7355     */
7356    public WindowInsets onApplyWindowInsets(WindowInsets insets) {
7357        if ((mPrivateFlags3 & PFLAG3_FITTING_SYSTEM_WINDOWS) == 0) {
7358            // We weren't called from within a direct call to fitSystemWindows,
7359            // call into it as a fallback in case we're in a class that overrides it
7360            // and has logic to perform.
7361            if (fitSystemWindows(insets.getSystemWindowInsets())) {
7362                return insets.consumeSystemWindowInsets();
7363            }
7364        } else {
7365            // We were called from within a direct call to fitSystemWindows.
7366            if (fitSystemWindowsInt(insets.getSystemWindowInsets())) {
7367                return insets.consumeSystemWindowInsets();
7368            }
7369        }
7370        return insets;
7371    }
7372
7373    /**
7374     * Set an {@link OnApplyWindowInsetsListener} to take over the policy for applying
7375     * window insets to this view. The listener's
7376     * {@link OnApplyWindowInsetsListener#onApplyWindowInsets(View, WindowInsets) onApplyWindowInsets}
7377     * method will be called instead of the view's
7378     * {@link #onApplyWindowInsets(WindowInsets) onApplyWindowInsets} method.
7379     *
7380     * @param listener Listener to set
7381     *
7382     * @see #onApplyWindowInsets(WindowInsets)
7383     */
7384    public void setOnApplyWindowInsetsListener(OnApplyWindowInsetsListener listener) {
7385        getListenerInfo().mOnApplyWindowInsetsListener = listener;
7386    }
7387
7388    /**
7389     * Request to apply the given window insets to this view or another view in its subtree.
7390     *
7391     * <p>This method should be called by clients wishing to apply insets corresponding to areas
7392     * obscured by window decorations or overlays. This can include the status and navigation bars,
7393     * action bars, input methods and more. New inset categories may be added in the future.
7394     * The method returns the insets provided minus any that were applied by this view or its
7395     * children.</p>
7396     *
7397     * <p>Clients wishing to provide custom behavior should override the
7398     * {@link #onApplyWindowInsets(WindowInsets)} method or alternatively provide a
7399     * {@link OnApplyWindowInsetsListener} via the
7400     * {@link #setOnApplyWindowInsetsListener(View.OnApplyWindowInsetsListener) setOnApplyWindowInsetsListener}
7401     * method.</p>
7402     *
7403     * <p>This method replaces the older {@link #fitSystemWindows(Rect) fitSystemWindows} method.
7404     * </p>
7405     *
7406     * @param insets Insets to apply
7407     * @return The provided insets minus the insets that were consumed
7408     */
7409    public WindowInsets dispatchApplyWindowInsets(WindowInsets insets) {
7410        try {
7411            mPrivateFlags3 |= PFLAG3_APPLYING_INSETS;
7412            if (mListenerInfo != null && mListenerInfo.mOnApplyWindowInsetsListener != null) {
7413                return mListenerInfo.mOnApplyWindowInsetsListener.onApplyWindowInsets(this, insets);
7414            } else {
7415                return onApplyWindowInsets(insets);
7416            }
7417        } finally {
7418            mPrivateFlags3 &= ~PFLAG3_APPLYING_INSETS;
7419        }
7420    }
7421
7422    /**
7423     * Compute the view's coordinate within the surface.
7424     *
7425     * <p>Computes the coordinates of this view in its surface. The argument
7426     * must be an array of two integers. After the method returns, the array
7427     * contains the x and y location in that order.</p>
7428     * @hide
7429     * @param location an array of two integers in which to hold the coordinates
7430     */
7431    public void getLocationInSurface(@Size(2) int[] location) {
7432        getLocationInWindow(location);
7433        if (mAttachInfo != null && mAttachInfo.mViewRootImpl != null) {
7434            location[0] += mAttachInfo.mViewRootImpl.mWindowAttributes.surfaceInsets.left;
7435            location[1] += mAttachInfo.mViewRootImpl.mWindowAttributes.surfaceInsets.top;
7436        }
7437    }
7438
7439    /**
7440     * Provide original WindowInsets that are dispatched to the view hierarchy. The insets are
7441     * only available if the view is attached.
7442     *
7443     * @return WindowInsets from the top of the view hierarchy or null if View is detached
7444     */
7445    public WindowInsets getRootWindowInsets() {
7446        if (mAttachInfo != null) {
7447            return mAttachInfo.mViewRootImpl.getWindowInsets(false /* forceConstruct */);
7448        }
7449        return null;
7450    }
7451
7452    /**
7453     * @hide Compute the insets that should be consumed by this view and the ones
7454     * that should propagate to those under it.
7455     */
7456    protected boolean computeFitSystemWindows(Rect inoutInsets, Rect outLocalInsets) {
7457        if ((mViewFlags & OPTIONAL_FITS_SYSTEM_WINDOWS) == 0
7458                || mAttachInfo == null
7459                || ((mAttachInfo.mSystemUiVisibility & SYSTEM_UI_LAYOUT_FLAGS) == 0
7460                        && !mAttachInfo.mOverscanRequested)) {
7461            outLocalInsets.set(inoutInsets);
7462            inoutInsets.set(0, 0, 0, 0);
7463            return true;
7464        } else {
7465            // The application wants to take care of fitting system window for
7466            // the content...  however we still need to take care of any overscan here.
7467            final Rect overscan = mAttachInfo.mOverscanInsets;
7468            outLocalInsets.set(overscan);
7469            inoutInsets.left -= overscan.left;
7470            inoutInsets.top -= overscan.top;
7471            inoutInsets.right -= overscan.right;
7472            inoutInsets.bottom -= overscan.bottom;
7473            return false;
7474        }
7475    }
7476
7477    /**
7478     * Compute insets that should be consumed by this view and the ones that should propagate
7479     * to those under it.
7480     *
7481     * @param in Insets currently being processed by this View, likely received as a parameter
7482     *           to {@link #onApplyWindowInsets(WindowInsets)}.
7483     * @param outLocalInsets A Rect that will receive the insets that should be consumed
7484     *                       by this view
7485     * @return Insets that should be passed along to views under this one
7486     */
7487    public WindowInsets computeSystemWindowInsets(WindowInsets in, Rect outLocalInsets) {
7488        if ((mViewFlags & OPTIONAL_FITS_SYSTEM_WINDOWS) == 0
7489                || mAttachInfo == null
7490                || (mAttachInfo.mSystemUiVisibility & SYSTEM_UI_LAYOUT_FLAGS) == 0) {
7491            outLocalInsets.set(in.getSystemWindowInsets());
7492            return in.consumeSystemWindowInsets();
7493        } else {
7494            outLocalInsets.set(0, 0, 0, 0);
7495            return in;
7496        }
7497    }
7498
7499    /**
7500     * Sets whether or not this view should account for system screen decorations
7501     * such as the status bar and inset its content; that is, controlling whether
7502     * the default implementation of {@link #fitSystemWindows(Rect)} will be
7503     * executed.  See that method for more details.
7504     *
7505     * <p>Note that if you are providing your own implementation of
7506     * {@link #fitSystemWindows(Rect)}, then there is no need to set this
7507     * flag to true -- your implementation will be overriding the default
7508     * implementation that checks this flag.
7509     *
7510     * @param fitSystemWindows If true, then the default implementation of
7511     * {@link #fitSystemWindows(Rect)} will be executed.
7512     *
7513     * @attr ref android.R.styleable#View_fitsSystemWindows
7514     * @see #getFitsSystemWindows()
7515     * @see #fitSystemWindows(Rect)
7516     * @see #setSystemUiVisibility(int)
7517     */
7518    public void setFitsSystemWindows(boolean fitSystemWindows) {
7519        setFlags(fitSystemWindows ? FITS_SYSTEM_WINDOWS : 0, FITS_SYSTEM_WINDOWS);
7520    }
7521
7522    /**
7523     * Check for state of {@link #setFitsSystemWindows(boolean)}. If this method
7524     * returns {@code true}, the default implementation of {@link #fitSystemWindows(Rect)}
7525     * will be executed.
7526     *
7527     * @return {@code true} if the default implementation of
7528     * {@link #fitSystemWindows(Rect)} will be executed.
7529     *
7530     * @attr ref android.R.styleable#View_fitsSystemWindows
7531     * @see #setFitsSystemWindows(boolean)
7532     * @see #fitSystemWindows(Rect)
7533     * @see #setSystemUiVisibility(int)
7534     */
7535    @ViewDebug.ExportedProperty
7536    public boolean getFitsSystemWindows() {
7537        return (mViewFlags & FITS_SYSTEM_WINDOWS) == FITS_SYSTEM_WINDOWS;
7538    }
7539
7540    /** @hide */
7541    public boolean fitsSystemWindows() {
7542        return getFitsSystemWindows();
7543    }
7544
7545    /**
7546     * Ask that a new dispatch of {@link #fitSystemWindows(Rect)} be performed.
7547     * @deprecated Use {@link #requestApplyInsets()} for newer platform versions.
7548     */
7549    public void requestFitSystemWindows() {
7550        if (mParent != null) {
7551            mParent.requestFitSystemWindows();
7552        }
7553    }
7554
7555    /**
7556     * Ask that a new dispatch of {@link #onApplyWindowInsets(WindowInsets)} be performed.
7557     */
7558    public void requestApplyInsets() {
7559        requestFitSystemWindows();
7560    }
7561
7562    /**
7563     * For use by PhoneWindow to make its own system window fitting optional.
7564     * @hide
7565     */
7566    public void makeOptionalFitsSystemWindows() {
7567        setFlags(OPTIONAL_FITS_SYSTEM_WINDOWS, OPTIONAL_FITS_SYSTEM_WINDOWS);
7568    }
7569
7570    /**
7571     * Returns the outsets, which areas of the device that aren't a surface, but we would like to
7572     * treat them as such.
7573     * @hide
7574     */
7575    public void getOutsets(Rect outOutsetRect) {
7576        if (mAttachInfo != null) {
7577            outOutsetRect.set(mAttachInfo.mOutsets);
7578        } else {
7579            outOutsetRect.setEmpty();
7580        }
7581    }
7582
7583    /**
7584     * Returns the visibility status for this view.
7585     *
7586     * @return One of {@link #VISIBLE}, {@link #INVISIBLE}, or {@link #GONE}.
7587     * @attr ref android.R.styleable#View_visibility
7588     */
7589    @ViewDebug.ExportedProperty(mapping = {
7590        @ViewDebug.IntToString(from = VISIBLE,   to = "VISIBLE"),
7591        @ViewDebug.IntToString(from = INVISIBLE, to = "INVISIBLE"),
7592        @ViewDebug.IntToString(from = GONE,      to = "GONE")
7593    })
7594    @Visibility
7595    public int getVisibility() {
7596        return mViewFlags & VISIBILITY_MASK;
7597    }
7598
7599    /**
7600     * Set the enabled state of this view.
7601     *
7602     * @param visibility One of {@link #VISIBLE}, {@link #INVISIBLE}, or {@link #GONE}.
7603     * @attr ref android.R.styleable#View_visibility
7604     */
7605    @RemotableViewMethod
7606    public void setVisibility(@Visibility int visibility) {
7607        setFlags(visibility, VISIBILITY_MASK);
7608    }
7609
7610    /**
7611     * Returns the enabled status for this view. The interpretation of the
7612     * enabled state varies by subclass.
7613     *
7614     * @return True if this view is enabled, false otherwise.
7615     */
7616    @ViewDebug.ExportedProperty
7617    public boolean isEnabled() {
7618        return (mViewFlags & ENABLED_MASK) == ENABLED;
7619    }
7620
7621    /**
7622     * Set the enabled state of this view. The interpretation of the enabled
7623     * state varies by subclass.
7624     *
7625     * @param enabled True if this view is enabled, false otherwise.
7626     */
7627    @RemotableViewMethod
7628    public void setEnabled(boolean enabled) {
7629        if (enabled == isEnabled()) return;
7630
7631        setFlags(enabled ? ENABLED : DISABLED, ENABLED_MASK);
7632
7633        /*
7634         * The View most likely has to change its appearance, so refresh
7635         * the drawable state.
7636         */
7637        refreshDrawableState();
7638
7639        // Invalidate too, since the default behavior for views is to be
7640        // be drawn at 50% alpha rather than to change the drawable.
7641        invalidate(true);
7642
7643        if (!enabled) {
7644            cancelPendingInputEvents();
7645        }
7646    }
7647
7648    /**
7649     * Set whether this view can receive the focus.
7650     *
7651     * Setting this to false will also ensure that this view is not focusable
7652     * in touch mode.
7653     *
7654     * @param focusable If true, this view can receive the focus.
7655     *
7656     * @see #setFocusableInTouchMode(boolean)
7657     * @attr ref android.R.styleable#View_focusable
7658     */
7659    public void setFocusable(boolean focusable) {
7660        if (!focusable) {
7661            setFlags(0, FOCUSABLE_IN_TOUCH_MODE);
7662        }
7663        setFlags(focusable ? FOCUSABLE : NOT_FOCUSABLE, FOCUSABLE_MASK);
7664    }
7665
7666    /**
7667     * Set whether this view can receive focus while in touch mode.
7668     *
7669     * Setting this to true will also ensure that this view is focusable.
7670     *
7671     * @param focusableInTouchMode If true, this view can receive the focus while
7672     *   in touch mode.
7673     *
7674     * @see #setFocusable(boolean)
7675     * @attr ref android.R.styleable#View_focusableInTouchMode
7676     */
7677    public void setFocusableInTouchMode(boolean focusableInTouchMode) {
7678        // Focusable in touch mode should always be set before the focusable flag
7679        // otherwise, setting the focusable flag will trigger a focusableViewAvailable()
7680        // which, in touch mode, will not successfully request focus on this view
7681        // because the focusable in touch mode flag is not set
7682        setFlags(focusableInTouchMode ? FOCUSABLE_IN_TOUCH_MODE : 0, FOCUSABLE_IN_TOUCH_MODE);
7683        if (focusableInTouchMode) {
7684            setFlags(FOCUSABLE, FOCUSABLE_MASK);
7685        }
7686    }
7687
7688    /**
7689     * Set whether this view should have sound effects enabled for events such as
7690     * clicking and touching.
7691     *
7692     * <p>You may wish to disable sound effects for a view if you already play sounds,
7693     * for instance, a dial key that plays dtmf tones.
7694     *
7695     * @param soundEffectsEnabled whether sound effects are enabled for this view.
7696     * @see #isSoundEffectsEnabled()
7697     * @see #playSoundEffect(int)
7698     * @attr ref android.R.styleable#View_soundEffectsEnabled
7699     */
7700    public void setSoundEffectsEnabled(boolean soundEffectsEnabled) {
7701        setFlags(soundEffectsEnabled ? SOUND_EFFECTS_ENABLED: 0, SOUND_EFFECTS_ENABLED);
7702    }
7703
7704    /**
7705     * @return whether this view should have sound effects enabled for events such as
7706     *     clicking and touching.
7707     *
7708     * @see #setSoundEffectsEnabled(boolean)
7709     * @see #playSoundEffect(int)
7710     * @attr ref android.R.styleable#View_soundEffectsEnabled
7711     */
7712    @ViewDebug.ExportedProperty
7713    public boolean isSoundEffectsEnabled() {
7714        return SOUND_EFFECTS_ENABLED == (mViewFlags & SOUND_EFFECTS_ENABLED);
7715    }
7716
7717    /**
7718     * Set whether this view should have haptic feedback for events such as
7719     * long presses.
7720     *
7721     * <p>You may wish to disable haptic feedback if your view already controls
7722     * its own haptic feedback.
7723     *
7724     * @param hapticFeedbackEnabled whether haptic feedback enabled for this view.
7725     * @see #isHapticFeedbackEnabled()
7726     * @see #performHapticFeedback(int)
7727     * @attr ref android.R.styleable#View_hapticFeedbackEnabled
7728     */
7729    public void setHapticFeedbackEnabled(boolean hapticFeedbackEnabled) {
7730        setFlags(hapticFeedbackEnabled ? HAPTIC_FEEDBACK_ENABLED: 0, HAPTIC_FEEDBACK_ENABLED);
7731    }
7732
7733    /**
7734     * @return whether this view should have haptic feedback enabled for events
7735     * long presses.
7736     *
7737     * @see #setHapticFeedbackEnabled(boolean)
7738     * @see #performHapticFeedback(int)
7739     * @attr ref android.R.styleable#View_hapticFeedbackEnabled
7740     */
7741    @ViewDebug.ExportedProperty
7742    public boolean isHapticFeedbackEnabled() {
7743        return HAPTIC_FEEDBACK_ENABLED == (mViewFlags & HAPTIC_FEEDBACK_ENABLED);
7744    }
7745
7746    /**
7747     * Returns the layout direction for this view.
7748     *
7749     * @return One of {@link #LAYOUT_DIRECTION_LTR},
7750     *   {@link #LAYOUT_DIRECTION_RTL},
7751     *   {@link #LAYOUT_DIRECTION_INHERIT} or
7752     *   {@link #LAYOUT_DIRECTION_LOCALE}.
7753     *
7754     * @attr ref android.R.styleable#View_layoutDirection
7755     *
7756     * @hide
7757     */
7758    @ViewDebug.ExportedProperty(category = "layout", mapping = {
7759        @ViewDebug.IntToString(from = LAYOUT_DIRECTION_LTR,     to = "LTR"),
7760        @ViewDebug.IntToString(from = LAYOUT_DIRECTION_RTL,     to = "RTL"),
7761        @ViewDebug.IntToString(from = LAYOUT_DIRECTION_INHERIT, to = "INHERIT"),
7762        @ViewDebug.IntToString(from = LAYOUT_DIRECTION_LOCALE,  to = "LOCALE")
7763    })
7764    @LayoutDir
7765    public int getRawLayoutDirection() {
7766        return (mPrivateFlags2 & PFLAG2_LAYOUT_DIRECTION_MASK) >> PFLAG2_LAYOUT_DIRECTION_MASK_SHIFT;
7767    }
7768
7769    /**
7770     * Set the layout direction for this view. This will propagate a reset of layout direction
7771     * resolution to the view's children and resolve layout direction for this view.
7772     *
7773     * @param layoutDirection the layout direction to set. Should be one of:
7774     *
7775     * {@link #LAYOUT_DIRECTION_LTR},
7776     * {@link #LAYOUT_DIRECTION_RTL},
7777     * {@link #LAYOUT_DIRECTION_INHERIT},
7778     * {@link #LAYOUT_DIRECTION_LOCALE}.
7779     *
7780     * Resolution will be done if the value is set to LAYOUT_DIRECTION_INHERIT. The resolution
7781     * proceeds up the parent chain of the view to get the value. If there is no parent, then it
7782     * will return the default {@link #LAYOUT_DIRECTION_LTR}.
7783     *
7784     * @attr ref android.R.styleable#View_layoutDirection
7785     */
7786    @RemotableViewMethod
7787    public void setLayoutDirection(@LayoutDir int layoutDirection) {
7788        if (getRawLayoutDirection() != layoutDirection) {
7789            // Reset the current layout direction and the resolved one
7790            mPrivateFlags2 &= ~PFLAG2_LAYOUT_DIRECTION_MASK;
7791            resetRtlProperties();
7792            // Set the new layout direction (filtered)
7793            mPrivateFlags2 |=
7794                    ((layoutDirection << PFLAG2_LAYOUT_DIRECTION_MASK_SHIFT) & PFLAG2_LAYOUT_DIRECTION_MASK);
7795            // We need to resolve all RTL properties as they all depend on layout direction
7796            resolveRtlPropertiesIfNeeded();
7797            requestLayout();
7798            invalidate(true);
7799        }
7800    }
7801
7802    /**
7803     * Returns the resolved layout direction for this view.
7804     *
7805     * @return {@link #LAYOUT_DIRECTION_RTL} if the layout direction is RTL or returns
7806     * {@link #LAYOUT_DIRECTION_LTR} if the layout direction is not RTL.
7807     *
7808     * For compatibility, this will return {@link #LAYOUT_DIRECTION_LTR} if API version
7809     * is lower than {@link android.os.Build.VERSION_CODES#JELLY_BEAN_MR1}.
7810     *
7811     * @attr ref android.R.styleable#View_layoutDirection
7812     */
7813    @ViewDebug.ExportedProperty(category = "layout", mapping = {
7814        @ViewDebug.IntToString(from = LAYOUT_DIRECTION_LTR, to = "RESOLVED_DIRECTION_LTR"),
7815        @ViewDebug.IntToString(from = LAYOUT_DIRECTION_RTL, to = "RESOLVED_DIRECTION_RTL")
7816    })
7817    @ResolvedLayoutDir
7818    public int getLayoutDirection() {
7819        final int targetSdkVersion = getContext().getApplicationInfo().targetSdkVersion;
7820        if (targetSdkVersion < JELLY_BEAN_MR1) {
7821            mPrivateFlags2 |= PFLAG2_LAYOUT_DIRECTION_RESOLVED;
7822            return LAYOUT_DIRECTION_RESOLVED_DEFAULT;
7823        }
7824        return ((mPrivateFlags2 & PFLAG2_LAYOUT_DIRECTION_RESOLVED_RTL) ==
7825                PFLAG2_LAYOUT_DIRECTION_RESOLVED_RTL) ? LAYOUT_DIRECTION_RTL : LAYOUT_DIRECTION_LTR;
7826    }
7827
7828    /**
7829     * Indicates whether or not this view's layout is right-to-left. This is resolved from
7830     * layout attribute and/or the inherited value from the parent
7831     *
7832     * @return true if the layout is right-to-left.
7833     *
7834     * @hide
7835     */
7836    @ViewDebug.ExportedProperty(category = "layout")
7837    public boolean isLayoutRtl() {
7838        return (getLayoutDirection() == LAYOUT_DIRECTION_RTL);
7839    }
7840
7841    /**
7842     * Indicates whether the view is currently tracking transient state that the
7843     * app should not need to concern itself with saving and restoring, but that
7844     * the framework should take special note to preserve when possible.
7845     *
7846     * <p>A view with transient state cannot be trivially rebound from an external
7847     * data source, such as an adapter binding item views in a list. This may be
7848     * because the view is performing an animation, tracking user selection
7849     * of content, or similar.</p>
7850     *
7851     * @return true if the view has transient state
7852     */
7853    @ViewDebug.ExportedProperty(category = "layout")
7854    public boolean hasTransientState() {
7855        return (mPrivateFlags2 & PFLAG2_HAS_TRANSIENT_STATE) == PFLAG2_HAS_TRANSIENT_STATE;
7856    }
7857
7858    /**
7859     * Set whether this view is currently tracking transient state that the
7860     * framework should attempt to preserve when possible. This flag is reference counted,
7861     * so every call to setHasTransientState(true) should be paired with a later call
7862     * to setHasTransientState(false).
7863     *
7864     * <p>A view with transient state cannot be trivially rebound from an external
7865     * data source, such as an adapter binding item views in a list. This may be
7866     * because the view is performing an animation, tracking user selection
7867     * of content, or similar.</p>
7868     *
7869     * @param hasTransientState true if this view has transient state
7870     */
7871    public void setHasTransientState(boolean hasTransientState) {
7872        mTransientStateCount = hasTransientState ? mTransientStateCount + 1 :
7873                mTransientStateCount - 1;
7874        if (mTransientStateCount < 0) {
7875            mTransientStateCount = 0;
7876            Log.e(VIEW_LOG_TAG, "hasTransientState decremented below 0: " +
7877                    "unmatched pair of setHasTransientState calls");
7878        } else if ((hasTransientState && mTransientStateCount == 1) ||
7879                (!hasTransientState && mTransientStateCount == 0)) {
7880            // update flag if we've just incremented up from 0 or decremented down to 0
7881            mPrivateFlags2 = (mPrivateFlags2 & ~PFLAG2_HAS_TRANSIENT_STATE) |
7882                    (hasTransientState ? PFLAG2_HAS_TRANSIENT_STATE : 0);
7883            if (mParent != null) {
7884                try {
7885                    mParent.childHasTransientStateChanged(this, hasTransientState);
7886                } catch (AbstractMethodError e) {
7887                    Log.e(VIEW_LOG_TAG, mParent.getClass().getSimpleName() +
7888                            " does not fully implement ViewParent", e);
7889                }
7890            }
7891        }
7892    }
7893
7894    /**
7895     * Returns true if this view is currently attached to a window.
7896     */
7897    public boolean isAttachedToWindow() {
7898        return mAttachInfo != null;
7899    }
7900
7901    /**
7902     * Returns true if this view has been through at least one layout since it
7903     * was last attached to or detached from a window.
7904     */
7905    public boolean isLaidOut() {
7906        return (mPrivateFlags3 & PFLAG3_IS_LAID_OUT) == PFLAG3_IS_LAID_OUT;
7907    }
7908
7909    /**
7910     * If this view doesn't do any drawing on its own, set this flag to
7911     * allow further optimizations. By default, this flag is not set on
7912     * View, but could be set on some View subclasses such as ViewGroup.
7913     *
7914     * Typically, if you override {@link #onDraw(android.graphics.Canvas)}
7915     * you should clear this flag.
7916     *
7917     * @param willNotDraw whether or not this View draw on its own
7918     */
7919    public void setWillNotDraw(boolean willNotDraw) {
7920        setFlags(willNotDraw ? WILL_NOT_DRAW : 0, DRAW_MASK);
7921    }
7922
7923    /**
7924     * Returns whether or not this View draws on its own.
7925     *
7926     * @return true if this view has nothing to draw, false otherwise
7927     */
7928    @ViewDebug.ExportedProperty(category = "drawing")
7929    public boolean willNotDraw() {
7930        return (mViewFlags & DRAW_MASK) == WILL_NOT_DRAW;
7931    }
7932
7933    /**
7934     * When a View's drawing cache is enabled, drawing is redirected to an
7935     * offscreen bitmap. Some views, like an ImageView, must be able to
7936     * bypass this mechanism if they already draw a single bitmap, to avoid
7937     * unnecessary usage of the memory.
7938     *
7939     * @param willNotCacheDrawing true if this view does not cache its
7940     *        drawing, false otherwise
7941     */
7942    public void setWillNotCacheDrawing(boolean willNotCacheDrawing) {
7943        setFlags(willNotCacheDrawing ? WILL_NOT_CACHE_DRAWING : 0, WILL_NOT_CACHE_DRAWING);
7944    }
7945
7946    /**
7947     * Returns whether or not this View can cache its drawing or not.
7948     *
7949     * @return true if this view does not cache its drawing, false otherwise
7950     */
7951    @ViewDebug.ExportedProperty(category = "drawing")
7952    public boolean willNotCacheDrawing() {
7953        return (mViewFlags & WILL_NOT_CACHE_DRAWING) == WILL_NOT_CACHE_DRAWING;
7954    }
7955
7956    /**
7957     * Indicates whether this view reacts to click events or not.
7958     *
7959     * @return true if the view is clickable, false otherwise
7960     *
7961     * @see #setClickable(boolean)
7962     * @attr ref android.R.styleable#View_clickable
7963     */
7964    @ViewDebug.ExportedProperty
7965    public boolean isClickable() {
7966        return (mViewFlags & CLICKABLE) == CLICKABLE;
7967    }
7968
7969    /**
7970     * Enables or disables click events for this view. When a view
7971     * is clickable it will change its state to "pressed" on every click.
7972     * Subclasses should set the view clickable to visually react to
7973     * user's clicks.
7974     *
7975     * @param clickable true to make the view clickable, false otherwise
7976     *
7977     * @see #isClickable()
7978     * @attr ref android.R.styleable#View_clickable
7979     */
7980    public void setClickable(boolean clickable) {
7981        setFlags(clickable ? CLICKABLE : 0, CLICKABLE);
7982    }
7983
7984    /**
7985     * Indicates whether this view reacts to long click events or not.
7986     *
7987     * @return true if the view is long clickable, false otherwise
7988     *
7989     * @see #setLongClickable(boolean)
7990     * @attr ref android.R.styleable#View_longClickable
7991     */
7992    public boolean isLongClickable() {
7993        return (mViewFlags & LONG_CLICKABLE) == LONG_CLICKABLE;
7994    }
7995
7996    /**
7997     * Enables or disables long click events for this view. When a view is long
7998     * clickable it reacts to the user holding down the button for a longer
7999     * duration than a tap. This event can either launch the listener or a
8000     * context menu.
8001     *
8002     * @param longClickable true to make the view long clickable, false otherwise
8003     * @see #isLongClickable()
8004     * @attr ref android.R.styleable#View_longClickable
8005     */
8006    public void setLongClickable(boolean longClickable) {
8007        setFlags(longClickable ? LONG_CLICKABLE : 0, LONG_CLICKABLE);
8008    }
8009
8010    /**
8011     * Indicates whether this view reacts to context clicks or not.
8012     *
8013     * @return true if the view is context clickable, false otherwise
8014     * @see #setContextClickable(boolean)
8015     * @attr ref android.R.styleable#View_contextClickable
8016     */
8017    public boolean isContextClickable() {
8018        return (mViewFlags & CONTEXT_CLICKABLE) == CONTEXT_CLICKABLE;
8019    }
8020
8021    /**
8022     * Enables or disables context clicking for this view. This event can launch the listener.
8023     *
8024     * @param contextClickable true to make the view react to a context click, false otherwise
8025     * @see #isContextClickable()
8026     * @attr ref android.R.styleable#View_contextClickable
8027     */
8028    public void setContextClickable(boolean contextClickable) {
8029        setFlags(contextClickable ? CONTEXT_CLICKABLE : 0, CONTEXT_CLICKABLE);
8030    }
8031
8032    /**
8033     * Sets the pressed state for this view and provides a touch coordinate for
8034     * animation hinting.
8035     *
8036     * @param pressed Pass true to set the View's internal state to "pressed",
8037     *            or false to reverts the View's internal state from a
8038     *            previously set "pressed" state.
8039     * @param x The x coordinate of the touch that caused the press
8040     * @param y The y coordinate of the touch that caused the press
8041     */
8042    private void setPressed(boolean pressed, float x, float y) {
8043        if (pressed) {
8044            drawableHotspotChanged(x, y);
8045        }
8046
8047        setPressed(pressed);
8048    }
8049
8050    /**
8051     * Sets the pressed state for this view.
8052     *
8053     * @see #isClickable()
8054     * @see #setClickable(boolean)
8055     *
8056     * @param pressed Pass true to set the View's internal state to "pressed", or false to reverts
8057     *        the View's internal state from a previously set "pressed" state.
8058     */
8059    public void setPressed(boolean pressed) {
8060        final boolean needsRefresh = pressed != ((mPrivateFlags & PFLAG_PRESSED) == PFLAG_PRESSED);
8061
8062        if (pressed) {
8063            mPrivateFlags |= PFLAG_PRESSED;
8064        } else {
8065            mPrivateFlags &= ~PFLAG_PRESSED;
8066        }
8067
8068        if (needsRefresh) {
8069            refreshDrawableState();
8070        }
8071        dispatchSetPressed(pressed);
8072    }
8073
8074    /**
8075     * Dispatch setPressed to all of this View's children.
8076     *
8077     * @see #setPressed(boolean)
8078     *
8079     * @param pressed The new pressed state
8080     */
8081    protected void dispatchSetPressed(boolean pressed) {
8082    }
8083
8084    /**
8085     * Indicates whether the view is currently in pressed state. Unless
8086     * {@link #setPressed(boolean)} is explicitly called, only clickable views can enter
8087     * the pressed state.
8088     *
8089     * @see #setPressed(boolean)
8090     * @see #isClickable()
8091     * @see #setClickable(boolean)
8092     *
8093     * @return true if the view is currently pressed, false otherwise
8094     */
8095    @ViewDebug.ExportedProperty
8096    public boolean isPressed() {
8097        return (mPrivateFlags & PFLAG_PRESSED) == PFLAG_PRESSED;
8098    }
8099
8100    /**
8101     * @hide
8102     * Indicates whether this view will participate in data collection through
8103     * {@link ViewStructure}.  If true, it will not provide any data
8104     * for itself or its children.  If false, the normal data collection will be allowed.
8105     *
8106     * @return Returns false if assist data collection is not blocked, else true.
8107     *
8108     * @see #setAssistBlocked(boolean)
8109     * @attr ref android.R.styleable#View_assistBlocked
8110     */
8111    public boolean isAssistBlocked() {
8112        return (mPrivateFlags3 & PFLAG3_ASSIST_BLOCKED) != 0;
8113    }
8114
8115    /**
8116     * @hide
8117     * Controls whether assist data collection from this view and its children is enabled
8118     * (that is, whether {@link #onProvideStructure} and
8119     * {@link #onProvideVirtualStructure} will be called).  The default value is false,
8120     * allowing normal assist collection.  Setting this to false will disable assist collection.
8121     *
8122     * @param enabled Set to true to <em>disable</em> assist data collection, or false
8123     * (the default) to allow it.
8124     *
8125     * @see #isAssistBlocked()
8126     * @see #onProvideStructure
8127     * @see #onProvideVirtualStructure
8128     * @attr ref android.R.styleable#View_assistBlocked
8129     */
8130    public void setAssistBlocked(boolean enabled) {
8131        if (enabled) {
8132            mPrivateFlags3 |= PFLAG3_ASSIST_BLOCKED;
8133        } else {
8134            mPrivateFlags3 &= ~PFLAG3_ASSIST_BLOCKED;
8135        }
8136    }
8137
8138    /**
8139     * Indicates whether this view will save its state (that is,
8140     * whether its {@link #onSaveInstanceState} method will be called).
8141     *
8142     * @return Returns true if the view state saving is enabled, else false.
8143     *
8144     * @see #setSaveEnabled(boolean)
8145     * @attr ref android.R.styleable#View_saveEnabled
8146     */
8147    public boolean isSaveEnabled() {
8148        return (mViewFlags & SAVE_DISABLED_MASK) != SAVE_DISABLED;
8149    }
8150
8151    /**
8152     * Controls whether the saving of this view's state is
8153     * enabled (that is, whether its {@link #onSaveInstanceState} method
8154     * will be called).  Note that even if freezing is enabled, the
8155     * view still must have an id assigned to it (via {@link #setId(int)})
8156     * for its state to be saved.  This flag can only disable the
8157     * saving of this view; any child views may still have their state saved.
8158     *
8159     * @param enabled Set to false to <em>disable</em> state saving, or true
8160     * (the default) to allow it.
8161     *
8162     * @see #isSaveEnabled()
8163     * @see #setId(int)
8164     * @see #onSaveInstanceState()
8165     * @attr ref android.R.styleable#View_saveEnabled
8166     */
8167    public void setSaveEnabled(boolean enabled) {
8168        setFlags(enabled ? 0 : SAVE_DISABLED, SAVE_DISABLED_MASK);
8169    }
8170
8171    /**
8172     * Gets whether the framework should discard touches when the view's
8173     * window is obscured by another visible window.
8174     * Refer to the {@link View} security documentation for more details.
8175     *
8176     * @return True if touch filtering is enabled.
8177     *
8178     * @see #setFilterTouchesWhenObscured(boolean)
8179     * @attr ref android.R.styleable#View_filterTouchesWhenObscured
8180     */
8181    @ViewDebug.ExportedProperty
8182    public boolean getFilterTouchesWhenObscured() {
8183        return (mViewFlags & FILTER_TOUCHES_WHEN_OBSCURED) != 0;
8184    }
8185
8186    /**
8187     * Sets whether the framework should discard touches when the view's
8188     * window is obscured by another visible window.
8189     * Refer to the {@link View} security documentation for more details.
8190     *
8191     * @param enabled True if touch filtering should be enabled.
8192     *
8193     * @see #getFilterTouchesWhenObscured
8194     * @attr ref android.R.styleable#View_filterTouchesWhenObscured
8195     */
8196    public void setFilterTouchesWhenObscured(boolean enabled) {
8197        setFlags(enabled ? FILTER_TOUCHES_WHEN_OBSCURED : 0,
8198                FILTER_TOUCHES_WHEN_OBSCURED);
8199    }
8200
8201    /**
8202     * Indicates whether the entire hierarchy under this view will save its
8203     * state when a state saving traversal occurs from its parent.  The default
8204     * is true; if false, these views will not be saved unless
8205     * {@link #saveHierarchyState(SparseArray)} is called directly on this view.
8206     *
8207     * @return Returns true if the view state saving from parent is enabled, else false.
8208     *
8209     * @see #setSaveFromParentEnabled(boolean)
8210     */
8211    public boolean isSaveFromParentEnabled() {
8212        return (mViewFlags & PARENT_SAVE_DISABLED_MASK) != PARENT_SAVE_DISABLED;
8213    }
8214
8215    /**
8216     * Controls whether the entire hierarchy under this view will save its
8217     * state when a state saving traversal occurs from its parent.  The default
8218     * is true; if false, these views will not be saved unless
8219     * {@link #saveHierarchyState(SparseArray)} is called directly on this view.
8220     *
8221     * @param enabled Set to false to <em>disable</em> state saving, or true
8222     * (the default) to allow it.
8223     *
8224     * @see #isSaveFromParentEnabled()
8225     * @see #setId(int)
8226     * @see #onSaveInstanceState()
8227     */
8228    public void setSaveFromParentEnabled(boolean enabled) {
8229        setFlags(enabled ? 0 : PARENT_SAVE_DISABLED, PARENT_SAVE_DISABLED_MASK);
8230    }
8231
8232
8233    /**
8234     * Returns whether this View is able to take focus.
8235     *
8236     * @return True if this view can take focus, or false otherwise.
8237     * @attr ref android.R.styleable#View_focusable
8238     */
8239    @ViewDebug.ExportedProperty(category = "focus")
8240    public final boolean isFocusable() {
8241        return FOCUSABLE == (mViewFlags & FOCUSABLE_MASK);
8242    }
8243
8244    /**
8245     * When a view is focusable, it may not want to take focus when in touch mode.
8246     * For example, a button would like focus when the user is navigating via a D-pad
8247     * so that the user can click on it, but once the user starts touching the screen,
8248     * the button shouldn't take focus
8249     * @return Whether the view is focusable in touch mode.
8250     * @attr ref android.R.styleable#View_focusableInTouchMode
8251     */
8252    @ViewDebug.ExportedProperty
8253    public final boolean isFocusableInTouchMode() {
8254        return FOCUSABLE_IN_TOUCH_MODE == (mViewFlags & FOCUSABLE_IN_TOUCH_MODE);
8255    }
8256
8257    /**
8258     * Find the nearest view in the specified direction that can take focus.
8259     * This does not actually give focus to that view.
8260     *
8261     * @param direction One of FOCUS_UP, FOCUS_DOWN, FOCUS_LEFT, and FOCUS_RIGHT
8262     *
8263     * @return The nearest focusable in the specified direction, or null if none
8264     *         can be found.
8265     */
8266    public View focusSearch(@FocusRealDirection int direction) {
8267        if (mParent != null) {
8268            return mParent.focusSearch(this, direction);
8269        } else {
8270            return null;
8271        }
8272    }
8273
8274    /**
8275     * This method is the last chance for the focused view and its ancestors to
8276     * respond to an arrow key. This is called when the focused view did not
8277     * consume the key internally, nor could the view system find a new view in
8278     * the requested direction to give focus to.
8279     *
8280     * @param focused The currently focused view.
8281     * @param direction The direction focus wants to move. One of FOCUS_UP,
8282     *        FOCUS_DOWN, FOCUS_LEFT, and FOCUS_RIGHT.
8283     * @return True if the this view consumed this unhandled move.
8284     */
8285    public boolean dispatchUnhandledMove(View focused, @FocusRealDirection int direction) {
8286        return false;
8287    }
8288
8289    /**
8290     * If a user manually specified the next view id for a particular direction,
8291     * use the root to look up the view.
8292     * @param root The root view of the hierarchy containing this view.
8293     * @param direction One of FOCUS_UP, FOCUS_DOWN, FOCUS_LEFT, FOCUS_RIGHT, FOCUS_FORWARD,
8294     * or FOCUS_BACKWARD.
8295     * @return The user specified next view, or null if there is none.
8296     */
8297    View findUserSetNextFocus(View root, @FocusDirection int direction) {
8298        switch (direction) {
8299            case FOCUS_LEFT:
8300                if (mNextFocusLeftId == View.NO_ID) return null;
8301                return findViewInsideOutShouldExist(root, mNextFocusLeftId);
8302            case FOCUS_RIGHT:
8303                if (mNextFocusRightId == View.NO_ID) return null;
8304                return findViewInsideOutShouldExist(root, mNextFocusRightId);
8305            case FOCUS_UP:
8306                if (mNextFocusUpId == View.NO_ID) return null;
8307                return findViewInsideOutShouldExist(root, mNextFocusUpId);
8308            case FOCUS_DOWN:
8309                if (mNextFocusDownId == View.NO_ID) return null;
8310                return findViewInsideOutShouldExist(root, mNextFocusDownId);
8311            case FOCUS_FORWARD:
8312                if (mNextFocusForwardId == View.NO_ID) return null;
8313                return findViewInsideOutShouldExist(root, mNextFocusForwardId);
8314            case FOCUS_BACKWARD: {
8315                if (mID == View.NO_ID) return null;
8316                final int id = mID;
8317                return root.findViewByPredicateInsideOut(this, new Predicate<View>() {
8318                    @Override
8319                    public boolean apply(View t) {
8320                        return t.mNextFocusForwardId == id;
8321                    }
8322                });
8323            }
8324        }
8325        return null;
8326    }
8327
8328    private View findViewInsideOutShouldExist(View root, int id) {
8329        if (mMatchIdPredicate == null) {
8330            mMatchIdPredicate = new MatchIdPredicate();
8331        }
8332        mMatchIdPredicate.mId = id;
8333        View result = root.findViewByPredicateInsideOut(this, mMatchIdPredicate);
8334        if (result == null) {
8335            Log.w(VIEW_LOG_TAG, "couldn't find view with id " + id);
8336        }
8337        return result;
8338    }
8339
8340    /**
8341     * Find and return all focusable views that are descendants of this view,
8342     * possibly including this view if it is focusable itself.
8343     *
8344     * @param direction The direction of the focus
8345     * @return A list of focusable views
8346     */
8347    public ArrayList<View> getFocusables(@FocusDirection int direction) {
8348        ArrayList<View> result = new ArrayList<View>(24);
8349        addFocusables(result, direction);
8350        return result;
8351    }
8352
8353    /**
8354     * Add any focusable views that are descendants of this view (possibly
8355     * including this view if it is focusable itself) to views.  If we are in touch mode,
8356     * only add views that are also focusable in touch mode.
8357     *
8358     * @param views Focusable views found so far
8359     * @param direction The direction of the focus
8360     */
8361    public void addFocusables(ArrayList<View> views, @FocusDirection int direction) {
8362        addFocusables(views, direction, FOCUSABLES_TOUCH_MODE);
8363    }
8364
8365    /**
8366     * Adds any focusable views that are descendants of this view (possibly
8367     * including this view if it is focusable itself) to views. This method
8368     * adds all focusable views regardless if we are in touch mode or
8369     * only views focusable in touch mode if we are in touch mode or
8370     * only views that can take accessibility focus if accessibility is enabled
8371     * depending on the focusable mode parameter.
8372     *
8373     * @param views Focusable views found so far or null if all we are interested is
8374     *        the number of focusables.
8375     * @param direction The direction of the focus.
8376     * @param focusableMode The type of focusables to be added.
8377     *
8378     * @see #FOCUSABLES_ALL
8379     * @see #FOCUSABLES_TOUCH_MODE
8380     */
8381    public void addFocusables(ArrayList<View> views, @FocusDirection int direction,
8382            @FocusableMode int focusableMode) {
8383        if (views == null) {
8384            return;
8385        }
8386        if (!isFocusable()) {
8387            return;
8388        }
8389        if ((focusableMode & FOCUSABLES_TOUCH_MODE) == FOCUSABLES_TOUCH_MODE
8390                && isInTouchMode() && !isFocusableInTouchMode()) {
8391            return;
8392        }
8393        views.add(this);
8394    }
8395
8396    /**
8397     * Finds the Views that contain given text. The containment is case insensitive.
8398     * The search is performed by either the text that the View renders or the content
8399     * description that describes the view for accessibility purposes and the view does
8400     * not render or both. Clients can specify how the search is to be performed via
8401     * passing the {@link #FIND_VIEWS_WITH_TEXT} and
8402     * {@link #FIND_VIEWS_WITH_CONTENT_DESCRIPTION} flags.
8403     *
8404     * @param outViews The output list of matching Views.
8405     * @param searched The text to match against.
8406     *
8407     * @see #FIND_VIEWS_WITH_TEXT
8408     * @see #FIND_VIEWS_WITH_CONTENT_DESCRIPTION
8409     * @see #setContentDescription(CharSequence)
8410     */
8411    public void findViewsWithText(ArrayList<View> outViews, CharSequence searched,
8412            @FindViewFlags int flags) {
8413        if (getAccessibilityNodeProvider() != null) {
8414            if ((flags & FIND_VIEWS_WITH_ACCESSIBILITY_NODE_PROVIDERS) != 0) {
8415                outViews.add(this);
8416            }
8417        } else if ((flags & FIND_VIEWS_WITH_CONTENT_DESCRIPTION) != 0
8418                && (searched != null && searched.length() > 0)
8419                && (mContentDescription != null && mContentDescription.length() > 0)) {
8420            String searchedLowerCase = searched.toString().toLowerCase();
8421            String contentDescriptionLowerCase = mContentDescription.toString().toLowerCase();
8422            if (contentDescriptionLowerCase.contains(searchedLowerCase)) {
8423                outViews.add(this);
8424            }
8425        }
8426    }
8427
8428    /**
8429     * Find and return all touchable views that are descendants of this view,
8430     * possibly including this view if it is touchable itself.
8431     *
8432     * @return A list of touchable views
8433     */
8434    public ArrayList<View> getTouchables() {
8435        ArrayList<View> result = new ArrayList<View>();
8436        addTouchables(result);
8437        return result;
8438    }
8439
8440    /**
8441     * Add any touchable views that are descendants of this view (possibly
8442     * including this view if it is touchable itself) to views.
8443     *
8444     * @param views Touchable views found so far
8445     */
8446    public void addTouchables(ArrayList<View> views) {
8447        final int viewFlags = mViewFlags;
8448
8449        if (((viewFlags & CLICKABLE) == CLICKABLE || (viewFlags & LONG_CLICKABLE) == LONG_CLICKABLE
8450                || (viewFlags & CONTEXT_CLICKABLE) == CONTEXT_CLICKABLE)
8451                && (viewFlags & ENABLED_MASK) == ENABLED) {
8452            views.add(this);
8453        }
8454    }
8455
8456    /**
8457     * Returns whether this View is accessibility focused.
8458     *
8459     * @return True if this View is accessibility focused.
8460     */
8461    public boolean isAccessibilityFocused() {
8462        return (mPrivateFlags2 & PFLAG2_ACCESSIBILITY_FOCUSED) != 0;
8463    }
8464
8465    /**
8466     * Call this to try to give accessibility focus to this view.
8467     *
8468     * A view will not actually take focus if {@link AccessibilityManager#isEnabled()}
8469     * returns false or the view is no visible or the view already has accessibility
8470     * focus.
8471     *
8472     * See also {@link #focusSearch(int)}, which is what you call to say that you
8473     * have focus, and you want your parent to look for the next one.
8474     *
8475     * @return Whether this view actually took accessibility focus.
8476     *
8477     * @hide
8478     */
8479    public boolean requestAccessibilityFocus() {
8480        AccessibilityManager manager = AccessibilityManager.getInstance(mContext);
8481        if (!manager.isEnabled() || !manager.isTouchExplorationEnabled()) {
8482            return false;
8483        }
8484        if ((mViewFlags & VISIBILITY_MASK) != VISIBLE) {
8485            return false;
8486        }
8487        if ((mPrivateFlags2 & PFLAG2_ACCESSIBILITY_FOCUSED) == 0) {
8488            mPrivateFlags2 |= PFLAG2_ACCESSIBILITY_FOCUSED;
8489            ViewRootImpl viewRootImpl = getViewRootImpl();
8490            if (viewRootImpl != null) {
8491                viewRootImpl.setAccessibilityFocus(this, null);
8492            }
8493            invalidate();
8494            sendAccessibilityEvent(AccessibilityEvent.TYPE_VIEW_ACCESSIBILITY_FOCUSED);
8495            return true;
8496        }
8497        return false;
8498    }
8499
8500    /**
8501     * Call this to try to clear accessibility focus of this view.
8502     *
8503     * See also {@link #focusSearch(int)}, which is what you call to say that you
8504     * have focus, and you want your parent to look for the next one.
8505     *
8506     * @hide
8507     */
8508    public void clearAccessibilityFocus() {
8509        clearAccessibilityFocusNoCallbacks();
8510
8511        // Clear the global reference of accessibility focus if this view or
8512        // any of its descendants had accessibility focus. This will NOT send
8513        // an event or update internal state if focus is cleared from a
8514        // descendant view, which may leave views in inconsistent states.
8515        final ViewRootImpl viewRootImpl = getViewRootImpl();
8516        if (viewRootImpl != null) {
8517            final View focusHost = viewRootImpl.getAccessibilityFocusedHost();
8518            if (focusHost != null && ViewRootImpl.isViewDescendantOf(focusHost, this)) {
8519                viewRootImpl.setAccessibilityFocus(null, null);
8520            }
8521        }
8522    }
8523
8524    private void sendAccessibilityHoverEvent(int eventType) {
8525        // Since we are not delivering to a client accessibility events from not
8526        // important views (unless the clinet request that) we need to fire the
8527        // event from the deepest view exposed to the client. As a consequence if
8528        // the user crosses a not exposed view the client will see enter and exit
8529        // of the exposed predecessor followed by and enter and exit of that same
8530        // predecessor when entering and exiting the not exposed descendant. This
8531        // is fine since the client has a clear idea which view is hovered at the
8532        // price of a couple more events being sent. This is a simple and
8533        // working solution.
8534        View source = this;
8535        while (true) {
8536            if (source.includeForAccessibility()) {
8537                source.sendAccessibilityEvent(eventType);
8538                return;
8539            }
8540            ViewParent parent = source.getParent();
8541            if (parent instanceof View) {
8542                source = (View) parent;
8543            } else {
8544                return;
8545            }
8546        }
8547    }
8548
8549    /**
8550     * Clears accessibility focus without calling any callback methods
8551     * normally invoked in {@link #clearAccessibilityFocus()}. This method
8552     * is used for clearing accessibility focus when giving this focus to
8553     * another view.
8554     */
8555    void clearAccessibilityFocusNoCallbacks() {
8556        if ((mPrivateFlags2 & PFLAG2_ACCESSIBILITY_FOCUSED) != 0) {
8557            mPrivateFlags2 &= ~PFLAG2_ACCESSIBILITY_FOCUSED;
8558            invalidate();
8559            sendAccessibilityEvent(AccessibilityEvent.TYPE_VIEW_ACCESSIBILITY_FOCUS_CLEARED);
8560        }
8561    }
8562
8563    /**
8564     * Call this to try to give focus to a specific view or to one of its
8565     * descendants.
8566     *
8567     * A view will not actually take focus if it is not focusable ({@link #isFocusable} returns
8568     * false), or if it is focusable and it is not focusable in touch mode
8569     * ({@link #isFocusableInTouchMode}) while the device is in touch mode.
8570     *
8571     * See also {@link #focusSearch(int)}, which is what you call to say that you
8572     * have focus, and you want your parent to look for the next one.
8573     *
8574     * This is equivalent to calling {@link #requestFocus(int, Rect)} with arguments
8575     * {@link #FOCUS_DOWN} and <code>null</code>.
8576     *
8577     * @return Whether this view or one of its descendants actually took focus.
8578     */
8579    public final boolean requestFocus() {
8580        return requestFocus(View.FOCUS_DOWN);
8581    }
8582
8583    /**
8584     * Call this to try to give focus to a specific view or to one of its
8585     * descendants and give it a hint about what direction focus is heading.
8586     *
8587     * A view will not actually take focus if it is not focusable ({@link #isFocusable} returns
8588     * false), or if it is focusable and it is not focusable in touch mode
8589     * ({@link #isFocusableInTouchMode}) while the device is in touch mode.
8590     *
8591     * See also {@link #focusSearch(int)}, which is what you call to say that you
8592     * have focus, and you want your parent to look for the next one.
8593     *
8594     * This is equivalent to calling {@link #requestFocus(int, Rect)} with
8595     * <code>null</code> set for the previously focused rectangle.
8596     *
8597     * @param direction One of FOCUS_UP, FOCUS_DOWN, FOCUS_LEFT, and FOCUS_RIGHT
8598     * @return Whether this view or one of its descendants actually took focus.
8599     */
8600    public final boolean requestFocus(int direction) {
8601        return requestFocus(direction, null);
8602    }
8603
8604    /**
8605     * Call this to try to give focus to a specific view or to one of its descendants
8606     * and give it hints about the direction and a specific rectangle that the focus
8607     * is coming from.  The rectangle can help give larger views a finer grained hint
8608     * about where focus is coming from, and therefore, where to show selection, or
8609     * forward focus change internally.
8610     *
8611     * A view will not actually take focus if it is not focusable ({@link #isFocusable} returns
8612     * false), or if it is focusable and it is not focusable in touch mode
8613     * ({@link #isFocusableInTouchMode}) while the device is in touch mode.
8614     *
8615     * A View will not take focus if it is not visible.
8616     *
8617     * A View will not take focus if one of its parents has
8618     * {@link android.view.ViewGroup#getDescendantFocusability()} equal to
8619     * {@link ViewGroup#FOCUS_BLOCK_DESCENDANTS}.
8620     *
8621     * See also {@link #focusSearch(int)}, which is what you call to say that you
8622     * have focus, and you want your parent to look for the next one.
8623     *
8624     * You may wish to override this method if your custom {@link View} has an internal
8625     * {@link View} that it wishes to forward the request to.
8626     *
8627     * @param direction One of FOCUS_UP, FOCUS_DOWN, FOCUS_LEFT, and FOCUS_RIGHT
8628     * @param previouslyFocusedRect The rectangle (in this View's coordinate system)
8629     *        to give a finer grained hint about where focus is coming from.  May be null
8630     *        if there is no hint.
8631     * @return Whether this view or one of its descendants actually took focus.
8632     */
8633    public boolean requestFocus(int direction, Rect previouslyFocusedRect) {
8634        return requestFocusNoSearch(direction, previouslyFocusedRect);
8635    }
8636
8637    private boolean requestFocusNoSearch(int direction, Rect previouslyFocusedRect) {
8638        // need to be focusable
8639        if ((mViewFlags & FOCUSABLE_MASK) != FOCUSABLE ||
8640                (mViewFlags & VISIBILITY_MASK) != VISIBLE) {
8641            return false;
8642        }
8643
8644        // need to be focusable in touch mode if in touch mode
8645        if (isInTouchMode() &&
8646            (FOCUSABLE_IN_TOUCH_MODE != (mViewFlags & FOCUSABLE_IN_TOUCH_MODE))) {
8647               return false;
8648        }
8649
8650        // need to not have any parents blocking us
8651        if (hasAncestorThatBlocksDescendantFocus()) {
8652            return false;
8653        }
8654
8655        handleFocusGainInternal(direction, previouslyFocusedRect);
8656        return true;
8657    }
8658
8659    /**
8660     * Call this to try to give focus to a specific view or to one of its descendants. This is a
8661     * special variant of {@link #requestFocus() } that will allow views that are not focusable in
8662     * touch mode to request focus when they are touched.
8663     *
8664     * @return Whether this view or one of its descendants actually took focus.
8665     *
8666     * @see #isInTouchMode()
8667     *
8668     */
8669    public final boolean requestFocusFromTouch() {
8670        // Leave touch mode if we need to
8671        if (isInTouchMode()) {
8672            ViewRootImpl viewRoot = getViewRootImpl();
8673            if (viewRoot != null) {
8674                viewRoot.ensureTouchMode(false);
8675            }
8676        }
8677        return requestFocus(View.FOCUS_DOWN);
8678    }
8679
8680    /**
8681     * @return Whether any ancestor of this view blocks descendant focus.
8682     */
8683    private boolean hasAncestorThatBlocksDescendantFocus() {
8684        final boolean focusableInTouchMode = isFocusableInTouchMode();
8685        ViewParent ancestor = mParent;
8686        while (ancestor instanceof ViewGroup) {
8687            final ViewGroup vgAncestor = (ViewGroup) ancestor;
8688            if (vgAncestor.getDescendantFocusability() == ViewGroup.FOCUS_BLOCK_DESCENDANTS
8689                    || (!focusableInTouchMode && vgAncestor.shouldBlockFocusForTouchscreen())) {
8690                return true;
8691            } else {
8692                ancestor = vgAncestor.getParent();
8693            }
8694        }
8695        return false;
8696    }
8697
8698    /**
8699     * Gets the mode for determining whether this View is important for accessibility
8700     * which is if it fires accessibility events and if it is reported to
8701     * accessibility services that query the screen.
8702     *
8703     * @return The mode for determining whether a View is important for accessibility.
8704     *
8705     * @attr ref android.R.styleable#View_importantForAccessibility
8706     *
8707     * @see #IMPORTANT_FOR_ACCESSIBILITY_YES
8708     * @see #IMPORTANT_FOR_ACCESSIBILITY_NO
8709     * @see #IMPORTANT_FOR_ACCESSIBILITY_NO_HIDE_DESCENDANTS
8710     * @see #IMPORTANT_FOR_ACCESSIBILITY_AUTO
8711     */
8712    @ViewDebug.ExportedProperty(category = "accessibility", mapping = {
8713            @ViewDebug.IntToString(from = IMPORTANT_FOR_ACCESSIBILITY_AUTO, to = "auto"),
8714            @ViewDebug.IntToString(from = IMPORTANT_FOR_ACCESSIBILITY_YES, to = "yes"),
8715            @ViewDebug.IntToString(from = IMPORTANT_FOR_ACCESSIBILITY_NO, to = "no"),
8716            @ViewDebug.IntToString(from = IMPORTANT_FOR_ACCESSIBILITY_NO_HIDE_DESCENDANTS,
8717                    to = "noHideDescendants")
8718        })
8719    public int getImportantForAccessibility() {
8720        return (mPrivateFlags2 & PFLAG2_IMPORTANT_FOR_ACCESSIBILITY_MASK)
8721                >> PFLAG2_IMPORTANT_FOR_ACCESSIBILITY_SHIFT;
8722    }
8723
8724    /**
8725     * Sets the live region mode for this view. This indicates to accessibility
8726     * services whether they should automatically notify the user about changes
8727     * to the view's content description or text, or to the content descriptions
8728     * or text of the view's children (where applicable).
8729     * <p>
8730     * For example, in a login screen with a TextView that displays an "incorrect
8731     * password" notification, that view should be marked as a live region with
8732     * mode {@link #ACCESSIBILITY_LIVE_REGION_POLITE}.
8733     * <p>
8734     * To disable change notifications for this view, use
8735     * {@link #ACCESSIBILITY_LIVE_REGION_NONE}. This is the default live region
8736     * mode for most views.
8737     * <p>
8738     * To indicate that the user should be notified of changes, use
8739     * {@link #ACCESSIBILITY_LIVE_REGION_POLITE}.
8740     * <p>
8741     * If the view's changes should interrupt ongoing speech and notify the user
8742     * immediately, use {@link #ACCESSIBILITY_LIVE_REGION_ASSERTIVE}.
8743     *
8744     * @param mode The live region mode for this view, one of:
8745     *        <ul>
8746     *        <li>{@link #ACCESSIBILITY_LIVE_REGION_NONE}
8747     *        <li>{@link #ACCESSIBILITY_LIVE_REGION_POLITE}
8748     *        <li>{@link #ACCESSIBILITY_LIVE_REGION_ASSERTIVE}
8749     *        </ul>
8750     * @attr ref android.R.styleable#View_accessibilityLiveRegion
8751     */
8752    public void setAccessibilityLiveRegion(int mode) {
8753        if (mode != getAccessibilityLiveRegion()) {
8754            mPrivateFlags2 &= ~PFLAG2_ACCESSIBILITY_LIVE_REGION_MASK;
8755            mPrivateFlags2 |= (mode << PFLAG2_ACCESSIBILITY_LIVE_REGION_SHIFT)
8756                    & PFLAG2_ACCESSIBILITY_LIVE_REGION_MASK;
8757            notifyViewAccessibilityStateChangedIfNeeded(
8758                    AccessibilityEvent.CONTENT_CHANGE_TYPE_UNDEFINED);
8759        }
8760    }
8761
8762    /**
8763     * Gets the live region mode for this View.
8764     *
8765     * @return The live region mode for the view.
8766     *
8767     * @attr ref android.R.styleable#View_accessibilityLiveRegion
8768     *
8769     * @see #setAccessibilityLiveRegion(int)
8770     */
8771    public int getAccessibilityLiveRegion() {
8772        return (mPrivateFlags2 & PFLAG2_ACCESSIBILITY_LIVE_REGION_MASK)
8773                >> PFLAG2_ACCESSIBILITY_LIVE_REGION_SHIFT;
8774    }
8775
8776    /**
8777     * Sets how to determine whether this view is important for accessibility
8778     * which is if it fires accessibility events and if it is reported to
8779     * accessibility services that query the screen.
8780     *
8781     * @param mode How to determine whether this view is important for accessibility.
8782     *
8783     * @attr ref android.R.styleable#View_importantForAccessibility
8784     *
8785     * @see #IMPORTANT_FOR_ACCESSIBILITY_YES
8786     * @see #IMPORTANT_FOR_ACCESSIBILITY_NO
8787     * @see #IMPORTANT_FOR_ACCESSIBILITY_NO_HIDE_DESCENDANTS
8788     * @see #IMPORTANT_FOR_ACCESSIBILITY_AUTO
8789     */
8790    public void setImportantForAccessibility(int mode) {
8791        final int oldMode = getImportantForAccessibility();
8792        if (mode != oldMode) {
8793            final boolean hideDescendants =
8794                    mode == IMPORTANT_FOR_ACCESSIBILITY_NO_HIDE_DESCENDANTS;
8795
8796            // If this node or its descendants are no longer important, try to
8797            // clear accessibility focus.
8798            if (mode == IMPORTANT_FOR_ACCESSIBILITY_NO || hideDescendants) {
8799                final View focusHost = findAccessibilityFocusHost(hideDescendants);
8800                if (focusHost != null) {
8801                    focusHost.clearAccessibilityFocus();
8802                }
8803            }
8804
8805            // If we're moving between AUTO and another state, we might not need
8806            // to send a subtree changed notification. We'll store the computed
8807            // importance, since we'll need to check it later to make sure.
8808            final boolean maySkipNotify = oldMode == IMPORTANT_FOR_ACCESSIBILITY_AUTO
8809                    || mode == IMPORTANT_FOR_ACCESSIBILITY_AUTO;
8810            final boolean oldIncludeForAccessibility = maySkipNotify && includeForAccessibility();
8811            mPrivateFlags2 &= ~PFLAG2_IMPORTANT_FOR_ACCESSIBILITY_MASK;
8812            mPrivateFlags2 |= (mode << PFLAG2_IMPORTANT_FOR_ACCESSIBILITY_SHIFT)
8813                    & PFLAG2_IMPORTANT_FOR_ACCESSIBILITY_MASK;
8814            if (!maySkipNotify || oldIncludeForAccessibility != includeForAccessibility()) {
8815                notifySubtreeAccessibilityStateChangedIfNeeded();
8816            } else {
8817                notifyViewAccessibilityStateChangedIfNeeded(
8818                        AccessibilityEvent.CONTENT_CHANGE_TYPE_UNDEFINED);
8819            }
8820        }
8821    }
8822
8823    /**
8824     * Returns the view within this view's hierarchy that is hosting
8825     * accessibility focus.
8826     *
8827     * @param searchDescendants whether to search for focus in descendant views
8828     * @return the view hosting accessibility focus, or {@code null}
8829     */
8830    private View findAccessibilityFocusHost(boolean searchDescendants) {
8831        if (isAccessibilityFocusedViewOrHost()) {
8832            return this;
8833        }
8834
8835        if (searchDescendants) {
8836            final ViewRootImpl viewRoot = getViewRootImpl();
8837            if (viewRoot != null) {
8838                final View focusHost = viewRoot.getAccessibilityFocusedHost();
8839                if (focusHost != null && ViewRootImpl.isViewDescendantOf(focusHost, this)) {
8840                    return focusHost;
8841                }
8842            }
8843        }
8844
8845        return null;
8846    }
8847
8848    /**
8849     * Computes whether this view should be exposed for accessibility. In
8850     * general, views that are interactive or provide information are exposed
8851     * while views that serve only as containers are hidden.
8852     * <p>
8853     * If an ancestor of this view has importance
8854     * {@link #IMPORTANT_FOR_ACCESSIBILITY_NO_HIDE_DESCENDANTS}, this method
8855     * returns <code>false</code>.
8856     * <p>
8857     * Otherwise, the value is computed according to the view's
8858     * {@link #getImportantForAccessibility()} value:
8859     * <ol>
8860     * <li>{@link #IMPORTANT_FOR_ACCESSIBILITY_NO} or
8861     * {@link #IMPORTANT_FOR_ACCESSIBILITY_NO_HIDE_DESCENDANTS}, return <code>false
8862     * </code>
8863     * <li>{@link #IMPORTANT_FOR_ACCESSIBILITY_YES}, return <code>true</code>
8864     * <li>{@link #IMPORTANT_FOR_ACCESSIBILITY_AUTO}, return <code>true</code> if
8865     * view satisfies any of the following:
8866     * <ul>
8867     * <li>Is actionable, e.g. {@link #isClickable()},
8868     * {@link #isLongClickable()}, or {@link #isFocusable()}
8869     * <li>Has an {@link AccessibilityDelegate}
8870     * <li>Has an interaction listener, e.g. {@link OnTouchListener},
8871     * {@link OnKeyListener}, etc.
8872     * <li>Is an accessibility live region, e.g.
8873     * {@link #getAccessibilityLiveRegion()} is not
8874     * {@link #ACCESSIBILITY_LIVE_REGION_NONE}.
8875     * </ul>
8876     * </ol>
8877     *
8878     * @return Whether the view is exposed for accessibility.
8879     * @see #setImportantForAccessibility(int)
8880     * @see #getImportantForAccessibility()
8881     */
8882    public boolean isImportantForAccessibility() {
8883        final int mode = (mPrivateFlags2 & PFLAG2_IMPORTANT_FOR_ACCESSIBILITY_MASK)
8884                >> PFLAG2_IMPORTANT_FOR_ACCESSIBILITY_SHIFT;
8885        if (mode == IMPORTANT_FOR_ACCESSIBILITY_NO
8886                || mode == IMPORTANT_FOR_ACCESSIBILITY_NO_HIDE_DESCENDANTS) {
8887            return false;
8888        }
8889
8890        // Check parent mode to ensure we're not hidden.
8891        ViewParent parent = mParent;
8892        while (parent instanceof View) {
8893            if (((View) parent).getImportantForAccessibility()
8894                    == IMPORTANT_FOR_ACCESSIBILITY_NO_HIDE_DESCENDANTS) {
8895                return false;
8896            }
8897            parent = parent.getParent();
8898        }
8899
8900        return mode == IMPORTANT_FOR_ACCESSIBILITY_YES || isActionableForAccessibility()
8901                || hasListenersForAccessibility() || getAccessibilityNodeProvider() != null
8902                || getAccessibilityLiveRegion() != ACCESSIBILITY_LIVE_REGION_NONE;
8903    }
8904
8905    /**
8906     * Gets the parent for accessibility purposes. Note that the parent for
8907     * accessibility is not necessary the immediate parent. It is the first
8908     * predecessor that is important for accessibility.
8909     *
8910     * @return The parent for accessibility purposes.
8911     */
8912    public ViewParent getParentForAccessibility() {
8913        if (mParent instanceof View) {
8914            View parentView = (View) mParent;
8915            if (parentView.includeForAccessibility()) {
8916                return mParent;
8917            } else {
8918                return mParent.getParentForAccessibility();
8919            }
8920        }
8921        return null;
8922    }
8923
8924    /**
8925     * Adds the children of this View relevant for accessibility to the given list
8926     * as output. Since some Views are not important for accessibility the added
8927     * child views are not necessarily direct children of this view, rather they are
8928     * the first level of descendants important for accessibility.
8929     *
8930     * @param outChildren The output list that will receive children for accessibility.
8931     */
8932    public void addChildrenForAccessibility(ArrayList<View> outChildren) {
8933
8934    }
8935
8936    /**
8937     * Whether to regard this view for accessibility. A view is regarded for
8938     * accessibility if it is important for accessibility or the querying
8939     * accessibility service has explicitly requested that view not
8940     * important for accessibility are regarded.
8941     *
8942     * @return Whether to regard the view for accessibility.
8943     *
8944     * @hide
8945     */
8946    public boolean includeForAccessibility() {
8947        if (mAttachInfo != null) {
8948            return (mAttachInfo.mAccessibilityFetchFlags
8949                    & AccessibilityNodeInfo.FLAG_INCLUDE_NOT_IMPORTANT_VIEWS) != 0
8950                    || isImportantForAccessibility();
8951        }
8952        return false;
8953    }
8954
8955    /**
8956     * Returns whether the View is considered actionable from
8957     * accessibility perspective. Such view are important for
8958     * accessibility.
8959     *
8960     * @return True if the view is actionable for accessibility.
8961     *
8962     * @hide
8963     */
8964    public boolean isActionableForAccessibility() {
8965        return (isClickable() || isLongClickable() || isFocusable());
8966    }
8967
8968    /**
8969     * Returns whether the View has registered callbacks which makes it
8970     * important for accessibility.
8971     *
8972     * @return True if the view is actionable for accessibility.
8973     */
8974    private boolean hasListenersForAccessibility() {
8975        ListenerInfo info = getListenerInfo();
8976        return mTouchDelegate != null || info.mOnKeyListener != null
8977                || info.mOnTouchListener != null || info.mOnGenericMotionListener != null
8978                || info.mOnHoverListener != null || info.mOnDragListener != null;
8979    }
8980
8981    /**
8982     * Notifies that the accessibility state of this view changed. The change
8983     * is local to this view and does not represent structural changes such
8984     * as children and parent. For example, the view became focusable. The
8985     * notification is at at most once every
8986     * {@link ViewConfiguration#getSendRecurringAccessibilityEventsInterval()}
8987     * to avoid unnecessary load to the system. Also once a view has a pending
8988     * notification this method is a NOP until the notification has been sent.
8989     *
8990     * @hide
8991     */
8992    public void notifyViewAccessibilityStateChangedIfNeeded(int changeType) {
8993        if (!AccessibilityManager.getInstance(mContext).isEnabled() || mAttachInfo == null) {
8994            return;
8995        }
8996        if (mSendViewStateChangedAccessibilityEvent == null) {
8997            mSendViewStateChangedAccessibilityEvent =
8998                    new SendViewStateChangedAccessibilityEvent();
8999        }
9000        mSendViewStateChangedAccessibilityEvent.runOrPost(changeType);
9001    }
9002
9003    /**
9004     * Notifies that the accessibility state of this view changed. The change
9005     * is *not* local to this view and does represent structural changes such
9006     * as children and parent. For example, the view size changed. The
9007     * notification is at at most once every
9008     * {@link ViewConfiguration#getSendRecurringAccessibilityEventsInterval()}
9009     * to avoid unnecessary load to the system. Also once a view has a pending
9010     * notification this method is a NOP until the notification has been sent.
9011     *
9012     * @hide
9013     */
9014    public void notifySubtreeAccessibilityStateChangedIfNeeded() {
9015        if (!AccessibilityManager.getInstance(mContext).isEnabled() || mAttachInfo == null) {
9016            return;
9017        }
9018        if ((mPrivateFlags2 & PFLAG2_SUBTREE_ACCESSIBILITY_STATE_CHANGED) == 0) {
9019            mPrivateFlags2 |= PFLAG2_SUBTREE_ACCESSIBILITY_STATE_CHANGED;
9020            if (mParent != null) {
9021                try {
9022                    mParent.notifySubtreeAccessibilityStateChanged(
9023                            this, this, AccessibilityEvent.CONTENT_CHANGE_TYPE_SUBTREE);
9024                } catch (AbstractMethodError e) {
9025                    Log.e(VIEW_LOG_TAG, mParent.getClass().getSimpleName() +
9026                            " does not fully implement ViewParent", e);
9027                }
9028            }
9029        }
9030    }
9031
9032    /**
9033     * Change the visibility of the View without triggering any other changes. This is
9034     * important for transitions, where visibility changes should not adjust focus or
9035     * trigger a new layout. This is only used when the visibility has already been changed
9036     * and we need a transient value during an animation. When the animation completes,
9037     * the original visibility value is always restored.
9038     *
9039     * @param visibility One of {@link #VISIBLE}, {@link #INVISIBLE}, or {@link #GONE}.
9040     * @hide
9041     */
9042    public void setTransitionVisibility(@Visibility int visibility) {
9043        mViewFlags = (mViewFlags & ~View.VISIBILITY_MASK) | visibility;
9044    }
9045
9046    /**
9047     * Reset the flag indicating the accessibility state of the subtree rooted
9048     * at this view changed.
9049     */
9050    void resetSubtreeAccessibilityStateChanged() {
9051        mPrivateFlags2 &= ~PFLAG2_SUBTREE_ACCESSIBILITY_STATE_CHANGED;
9052    }
9053
9054    /**
9055     * Report an accessibility action to this view's parents for delegated processing.
9056     *
9057     * <p>Implementations of {@link #performAccessibilityAction(int, Bundle)} may internally
9058     * call this method to delegate an accessibility action to a supporting parent. If the parent
9059     * returns true from its
9060     * {@link ViewParent#onNestedPrePerformAccessibilityAction(View, int, android.os.Bundle)}
9061     * method this method will return true to signify that the action was consumed.</p>
9062     *
9063     * <p>This method is useful for implementing nested scrolling child views. If
9064     * {@link #isNestedScrollingEnabled()} returns true and the action is a scrolling action
9065     * a custom view implementation may invoke this method to allow a parent to consume the
9066     * scroll first. If this method returns true the custom view should skip its own scrolling
9067     * behavior.</p>
9068     *
9069     * @param action Accessibility action to delegate
9070     * @param arguments Optional action arguments
9071     * @return true if the action was consumed by a parent
9072     */
9073    public boolean dispatchNestedPrePerformAccessibilityAction(int action, Bundle arguments) {
9074        for (ViewParent p = getParent(); p != null; p = p.getParent()) {
9075            if (p.onNestedPrePerformAccessibilityAction(this, action, arguments)) {
9076                return true;
9077            }
9078        }
9079        return false;
9080    }
9081
9082    /**
9083     * Performs the specified accessibility action on the view. For
9084     * possible accessibility actions look at {@link AccessibilityNodeInfo}.
9085     * <p>
9086     * If an {@link AccessibilityDelegate} has been specified via calling
9087     * {@link #setAccessibilityDelegate(AccessibilityDelegate)} its
9088     * {@link AccessibilityDelegate#performAccessibilityAction(View, int, Bundle)}
9089     * is responsible for handling this call.
9090     * </p>
9091     *
9092     * <p>The default implementation will delegate
9093     * {@link AccessibilityNodeInfo#ACTION_SCROLL_BACKWARD} and
9094     * {@link AccessibilityNodeInfo#ACTION_SCROLL_FORWARD} to nested scrolling parents if
9095     * {@link #isNestedScrollingEnabled() nested scrolling is enabled} on this view.</p>
9096     *
9097     * @param action The action to perform.
9098     * @param arguments Optional action arguments.
9099     * @return Whether the action was performed.
9100     */
9101    public boolean performAccessibilityAction(int action, Bundle arguments) {
9102      if (mAccessibilityDelegate != null) {
9103          return mAccessibilityDelegate.performAccessibilityAction(this, action, arguments);
9104      } else {
9105          return performAccessibilityActionInternal(action, arguments);
9106      }
9107    }
9108
9109   /**
9110    * @see #performAccessibilityAction(int, Bundle)
9111    *
9112    * Note: Called from the default {@link AccessibilityDelegate}.
9113    *
9114    * @hide
9115    */
9116    public boolean performAccessibilityActionInternal(int action, Bundle arguments) {
9117        if (isNestedScrollingEnabled()
9118                && (action == AccessibilityNodeInfo.ACTION_SCROLL_BACKWARD
9119                || action == AccessibilityNodeInfo.ACTION_SCROLL_FORWARD
9120                || action == R.id.accessibilityActionScrollUp
9121                || action == R.id.accessibilityActionScrollLeft
9122                || action == R.id.accessibilityActionScrollDown
9123                || action == R.id.accessibilityActionScrollRight)) {
9124            if (dispatchNestedPrePerformAccessibilityAction(action, arguments)) {
9125                return true;
9126            }
9127        }
9128
9129        switch (action) {
9130            case AccessibilityNodeInfo.ACTION_CLICK: {
9131                if (isClickable()) {
9132                    performClick();
9133                    return true;
9134                }
9135            } break;
9136            case AccessibilityNodeInfo.ACTION_LONG_CLICK: {
9137                if (isLongClickable()) {
9138                    performLongClick();
9139                    return true;
9140                }
9141            } break;
9142            case AccessibilityNodeInfo.ACTION_FOCUS: {
9143                if (!hasFocus()) {
9144                    // Get out of touch mode since accessibility
9145                    // wants to move focus around.
9146                    getViewRootImpl().ensureTouchMode(false);
9147                    return requestFocus();
9148                }
9149            } break;
9150            case AccessibilityNodeInfo.ACTION_CLEAR_FOCUS: {
9151                if (hasFocus()) {
9152                    clearFocus();
9153                    return !isFocused();
9154                }
9155            } break;
9156            case AccessibilityNodeInfo.ACTION_SELECT: {
9157                if (!isSelected()) {
9158                    setSelected(true);
9159                    return isSelected();
9160                }
9161            } break;
9162            case AccessibilityNodeInfo.ACTION_CLEAR_SELECTION: {
9163                if (isSelected()) {
9164                    setSelected(false);
9165                    return !isSelected();
9166                }
9167            } break;
9168            case AccessibilityNodeInfo.ACTION_ACCESSIBILITY_FOCUS: {
9169                if (!isAccessibilityFocused()) {
9170                    return requestAccessibilityFocus();
9171                }
9172            } break;
9173            case AccessibilityNodeInfo.ACTION_CLEAR_ACCESSIBILITY_FOCUS: {
9174                if (isAccessibilityFocused()) {
9175                    clearAccessibilityFocus();
9176                    return true;
9177                }
9178            } break;
9179            case AccessibilityNodeInfo.ACTION_NEXT_AT_MOVEMENT_GRANULARITY: {
9180                if (arguments != null) {
9181                    final int granularity = arguments.getInt(
9182                            AccessibilityNodeInfo.ACTION_ARGUMENT_MOVEMENT_GRANULARITY_INT);
9183                    final boolean extendSelection = arguments.getBoolean(
9184                            AccessibilityNodeInfo.ACTION_ARGUMENT_EXTEND_SELECTION_BOOLEAN);
9185                    return traverseAtGranularity(granularity, true, extendSelection);
9186                }
9187            } break;
9188            case AccessibilityNodeInfo.ACTION_PREVIOUS_AT_MOVEMENT_GRANULARITY: {
9189                if (arguments != null) {
9190                    final int granularity = arguments.getInt(
9191                            AccessibilityNodeInfo.ACTION_ARGUMENT_MOVEMENT_GRANULARITY_INT);
9192                    final boolean extendSelection = arguments.getBoolean(
9193                            AccessibilityNodeInfo.ACTION_ARGUMENT_EXTEND_SELECTION_BOOLEAN);
9194                    return traverseAtGranularity(granularity, false, extendSelection);
9195                }
9196            } break;
9197            case AccessibilityNodeInfo.ACTION_SET_SELECTION: {
9198                CharSequence text = getIterableTextForAccessibility();
9199                if (text == null) {
9200                    return false;
9201                }
9202                final int start = (arguments != null) ? arguments.getInt(
9203                        AccessibilityNodeInfo.ACTION_ARGUMENT_SELECTION_START_INT, -1) : -1;
9204                final int end = (arguments != null) ? arguments.getInt(
9205                AccessibilityNodeInfo.ACTION_ARGUMENT_SELECTION_END_INT, -1) : -1;
9206                // Only cursor position can be specified (selection length == 0)
9207                if ((getAccessibilitySelectionStart() != start
9208                        || getAccessibilitySelectionEnd() != end)
9209                        && (start == end)) {
9210                    setAccessibilitySelection(start, end);
9211                    notifyViewAccessibilityStateChangedIfNeeded(
9212                            AccessibilityEvent.CONTENT_CHANGE_TYPE_UNDEFINED);
9213                    return true;
9214                }
9215            } break;
9216            case R.id.accessibilityActionShowOnScreen: {
9217                if (mAttachInfo != null) {
9218                    final Rect r = mAttachInfo.mTmpInvalRect;
9219                    getDrawingRect(r);
9220                    return requestRectangleOnScreen(r, true);
9221                }
9222            } break;
9223            case R.id.accessibilityActionContextClick: {
9224                if (isContextClickable()) {
9225                    performContextClick();
9226                    return true;
9227                }
9228            } break;
9229        }
9230        return false;
9231    }
9232
9233    private boolean traverseAtGranularity(int granularity, boolean forward,
9234            boolean extendSelection) {
9235        CharSequence text = getIterableTextForAccessibility();
9236        if (text == null || text.length() == 0) {
9237            return false;
9238        }
9239        TextSegmentIterator iterator = getIteratorForGranularity(granularity);
9240        if (iterator == null) {
9241            return false;
9242        }
9243        int current = getAccessibilitySelectionEnd();
9244        if (current == ACCESSIBILITY_CURSOR_POSITION_UNDEFINED) {
9245            current = forward ? 0 : text.length();
9246        }
9247        final int[] range = forward ? iterator.following(current) : iterator.preceding(current);
9248        if (range == null) {
9249            return false;
9250        }
9251        final int segmentStart = range[0];
9252        final int segmentEnd = range[1];
9253        int selectionStart;
9254        int selectionEnd;
9255        if (extendSelection && isAccessibilitySelectionExtendable()) {
9256            selectionStart = getAccessibilitySelectionStart();
9257            if (selectionStart == ACCESSIBILITY_CURSOR_POSITION_UNDEFINED) {
9258                selectionStart = forward ? segmentStart : segmentEnd;
9259            }
9260            selectionEnd = forward ? segmentEnd : segmentStart;
9261        } else {
9262            selectionStart = selectionEnd= forward ? segmentEnd : segmentStart;
9263        }
9264        setAccessibilitySelection(selectionStart, selectionEnd);
9265        final int action = forward ? AccessibilityNodeInfo.ACTION_NEXT_AT_MOVEMENT_GRANULARITY
9266                : AccessibilityNodeInfo.ACTION_PREVIOUS_AT_MOVEMENT_GRANULARITY;
9267        sendViewTextTraversedAtGranularityEvent(action, granularity, segmentStart, segmentEnd);
9268        return true;
9269    }
9270
9271    /**
9272     * Gets the text reported for accessibility purposes.
9273     *
9274     * @return The accessibility text.
9275     *
9276     * @hide
9277     */
9278    public CharSequence getIterableTextForAccessibility() {
9279        return getContentDescription();
9280    }
9281
9282    /**
9283     * Gets whether accessibility selection can be extended.
9284     *
9285     * @return If selection is extensible.
9286     *
9287     * @hide
9288     */
9289    public boolean isAccessibilitySelectionExtendable() {
9290        return false;
9291    }
9292
9293    /**
9294     * @hide
9295     */
9296    public int getAccessibilitySelectionStart() {
9297        return mAccessibilityCursorPosition;
9298    }
9299
9300    /**
9301     * @hide
9302     */
9303    public int getAccessibilitySelectionEnd() {
9304        return getAccessibilitySelectionStart();
9305    }
9306
9307    /**
9308     * @hide
9309     */
9310    public void setAccessibilitySelection(int start, int end) {
9311        if (start ==  end && end == mAccessibilityCursorPosition) {
9312            return;
9313        }
9314        if (start >= 0 && start == end && end <= getIterableTextForAccessibility().length()) {
9315            mAccessibilityCursorPosition = start;
9316        } else {
9317            mAccessibilityCursorPosition = ACCESSIBILITY_CURSOR_POSITION_UNDEFINED;
9318        }
9319        sendAccessibilityEvent(AccessibilityEvent.TYPE_VIEW_TEXT_SELECTION_CHANGED);
9320    }
9321
9322    private void sendViewTextTraversedAtGranularityEvent(int action, int granularity,
9323            int fromIndex, int toIndex) {
9324        if (mParent == null) {
9325            return;
9326        }
9327        AccessibilityEvent event = AccessibilityEvent.obtain(
9328                AccessibilityEvent.TYPE_VIEW_TEXT_TRAVERSED_AT_MOVEMENT_GRANULARITY);
9329        onInitializeAccessibilityEvent(event);
9330        onPopulateAccessibilityEvent(event);
9331        event.setFromIndex(fromIndex);
9332        event.setToIndex(toIndex);
9333        event.setAction(action);
9334        event.setMovementGranularity(granularity);
9335        mParent.requestSendAccessibilityEvent(this, event);
9336    }
9337
9338    /**
9339     * @hide
9340     */
9341    public TextSegmentIterator getIteratorForGranularity(int granularity) {
9342        switch (granularity) {
9343            case AccessibilityNodeInfo.MOVEMENT_GRANULARITY_CHARACTER: {
9344                CharSequence text = getIterableTextForAccessibility();
9345                if (text != null && text.length() > 0) {
9346                    CharacterTextSegmentIterator iterator =
9347                        CharacterTextSegmentIterator.getInstance(
9348                                mContext.getResources().getConfiguration().locale);
9349                    iterator.initialize(text.toString());
9350                    return iterator;
9351                }
9352            } break;
9353            case AccessibilityNodeInfo.MOVEMENT_GRANULARITY_WORD: {
9354                CharSequence text = getIterableTextForAccessibility();
9355                if (text != null && text.length() > 0) {
9356                    WordTextSegmentIterator iterator =
9357                        WordTextSegmentIterator.getInstance(
9358                                mContext.getResources().getConfiguration().locale);
9359                    iterator.initialize(text.toString());
9360                    return iterator;
9361                }
9362            } break;
9363            case AccessibilityNodeInfo.MOVEMENT_GRANULARITY_PARAGRAPH: {
9364                CharSequence text = getIterableTextForAccessibility();
9365                if (text != null && text.length() > 0) {
9366                    ParagraphTextSegmentIterator iterator =
9367                        ParagraphTextSegmentIterator.getInstance();
9368                    iterator.initialize(text.toString());
9369                    return iterator;
9370                }
9371            } break;
9372        }
9373        return null;
9374    }
9375
9376    /**
9377     * @hide
9378     */
9379    public void dispatchStartTemporaryDetach() {
9380        onStartTemporaryDetach();
9381    }
9382
9383    /**
9384     * This is called when a container is going to temporarily detach a child, with
9385     * {@link ViewGroup#detachViewFromParent(View) ViewGroup.detachViewFromParent}.
9386     * It will either be followed by {@link #onFinishTemporaryDetach()} or
9387     * {@link #onDetachedFromWindow()} when the container is done.
9388     */
9389    public void onStartTemporaryDetach() {
9390        removeUnsetPressCallback();
9391        mPrivateFlags |= PFLAG_CANCEL_NEXT_UP_EVENT;
9392    }
9393
9394    /**
9395     * @hide
9396     */
9397    public void dispatchFinishTemporaryDetach() {
9398        onFinishTemporaryDetach();
9399    }
9400
9401    /**
9402     * Called after {@link #onStartTemporaryDetach} when the container is done
9403     * changing the view.
9404     */
9405    public void onFinishTemporaryDetach() {
9406    }
9407
9408    /**
9409     * Return the global {@link KeyEvent.DispatcherState KeyEvent.DispatcherState}
9410     * for this view's window.  Returns null if the view is not currently attached
9411     * to the window.  Normally you will not need to use this directly, but
9412     * just use the standard high-level event callbacks like
9413     * {@link #onKeyDown(int, KeyEvent)}.
9414     */
9415    public KeyEvent.DispatcherState getKeyDispatcherState() {
9416        return mAttachInfo != null ? mAttachInfo.mKeyDispatchState : null;
9417    }
9418
9419    /**
9420     * Dispatch a key event before it is processed by any input method
9421     * associated with the view hierarchy.  This can be used to intercept
9422     * key events in special situations before the IME consumes them; a
9423     * typical example would be handling the BACK key to update the application's
9424     * UI instead of allowing the IME to see it and close itself.
9425     *
9426     * @param event The key event to be dispatched.
9427     * @return True if the event was handled, false otherwise.
9428     */
9429    public boolean dispatchKeyEventPreIme(KeyEvent event) {
9430        return onKeyPreIme(event.getKeyCode(), event);
9431    }
9432
9433    /**
9434     * Dispatch a key event to the next view on the focus path. This path runs
9435     * from the top of the view tree down to the currently focused view. If this
9436     * view has focus, it will dispatch to itself. Otherwise it will dispatch
9437     * the next node down the focus path. This method also fires any key
9438     * listeners.
9439     *
9440     * @param event The key event to be dispatched.
9441     * @return True if the event was handled, false otherwise.
9442     */
9443    public boolean dispatchKeyEvent(KeyEvent event) {
9444        if (mInputEventConsistencyVerifier != null) {
9445            mInputEventConsistencyVerifier.onKeyEvent(event, 0);
9446        }
9447
9448        // Give any attached key listener a first crack at the event.
9449        //noinspection SimplifiableIfStatement
9450        ListenerInfo li = mListenerInfo;
9451        if (li != null && li.mOnKeyListener != null && (mViewFlags & ENABLED_MASK) == ENABLED
9452                && li.mOnKeyListener.onKey(this, event.getKeyCode(), event)) {
9453            return true;
9454        }
9455
9456        if (event.dispatch(this, mAttachInfo != null
9457                ? mAttachInfo.mKeyDispatchState : null, this)) {
9458            return true;
9459        }
9460
9461        if (mInputEventConsistencyVerifier != null) {
9462            mInputEventConsistencyVerifier.onUnhandledEvent(event, 0);
9463        }
9464        return false;
9465    }
9466
9467    /**
9468     * Dispatches a key shortcut event.
9469     *
9470     * @param event The key event to be dispatched.
9471     * @return True if the event was handled by the view, false otherwise.
9472     */
9473    public boolean dispatchKeyShortcutEvent(KeyEvent event) {
9474        return onKeyShortcut(event.getKeyCode(), event);
9475    }
9476
9477    /**
9478     * Pass the touch screen motion event down to the target view, or this
9479     * view if it is the target.
9480     *
9481     * @param event The motion event to be dispatched.
9482     * @return True if the event was handled by the view, false otherwise.
9483     */
9484    public boolean dispatchTouchEvent(MotionEvent event) {
9485        // If the event should be handled by accessibility focus first.
9486        if (event.isTargetAccessibilityFocus()) {
9487            // We don't have focus or no virtual descendant has it, do not handle the event.
9488            if (!isAccessibilityFocusedViewOrHost()) {
9489                return false;
9490            }
9491            // We have focus and got the event, then use normal event dispatch.
9492            event.setTargetAccessibilityFocus(false);
9493        }
9494
9495        boolean result = false;
9496
9497        if (mInputEventConsistencyVerifier != null) {
9498            mInputEventConsistencyVerifier.onTouchEvent(event, 0);
9499        }
9500
9501        final int actionMasked = event.getActionMasked();
9502        if (actionMasked == MotionEvent.ACTION_DOWN) {
9503            // Defensive cleanup for new gesture
9504            stopNestedScroll();
9505        }
9506
9507        if (onFilterTouchEventForSecurity(event)) {
9508            //noinspection SimplifiableIfStatement
9509            ListenerInfo li = mListenerInfo;
9510            if (li != null && li.mOnTouchListener != null
9511                    && (mViewFlags & ENABLED_MASK) == ENABLED
9512                    && li.mOnTouchListener.onTouch(this, event)) {
9513                result = true;
9514            }
9515
9516            if (!result && onTouchEvent(event)) {
9517                result = true;
9518            }
9519        }
9520
9521        if (!result && mInputEventConsistencyVerifier != null) {
9522            mInputEventConsistencyVerifier.onUnhandledEvent(event, 0);
9523        }
9524
9525        // Clean up after nested scrolls if this is the end of a gesture;
9526        // also cancel it if we tried an ACTION_DOWN but we didn't want the rest
9527        // of the gesture.
9528        if (actionMasked == MotionEvent.ACTION_UP ||
9529                actionMasked == MotionEvent.ACTION_CANCEL ||
9530                (actionMasked == MotionEvent.ACTION_DOWN && !result)) {
9531            stopNestedScroll();
9532        }
9533
9534        return result;
9535    }
9536
9537    boolean isAccessibilityFocusedViewOrHost() {
9538        return isAccessibilityFocused() || (getViewRootImpl() != null && getViewRootImpl()
9539                .getAccessibilityFocusedHost() == this);
9540    }
9541
9542    /**
9543     * Filter the touch event to apply security policies.
9544     *
9545     * @param event The motion event to be filtered.
9546     * @return True if the event should be dispatched, false if the event should be dropped.
9547     *
9548     * @see #getFilterTouchesWhenObscured
9549     */
9550    public boolean onFilterTouchEventForSecurity(MotionEvent event) {
9551        //noinspection RedundantIfStatement
9552        if ((mViewFlags & FILTER_TOUCHES_WHEN_OBSCURED) != 0
9553                && (event.getFlags() & MotionEvent.FLAG_WINDOW_IS_OBSCURED) != 0) {
9554            // Window is obscured, drop this touch.
9555            return false;
9556        }
9557        return true;
9558    }
9559
9560    /**
9561     * Pass a trackball motion event down to the focused view.
9562     *
9563     * @param event The motion event to be dispatched.
9564     * @return True if the event was handled by the view, false otherwise.
9565     */
9566    public boolean dispatchTrackballEvent(MotionEvent event) {
9567        if (mInputEventConsistencyVerifier != null) {
9568            mInputEventConsistencyVerifier.onTrackballEvent(event, 0);
9569        }
9570
9571        return onTrackballEvent(event);
9572    }
9573
9574    /**
9575     * Dispatch a generic motion event.
9576     * <p>
9577     * Generic motion events with source class {@link InputDevice#SOURCE_CLASS_POINTER}
9578     * are delivered to the view under the pointer.  All other generic motion events are
9579     * delivered to the focused view.  Hover events are handled specially and are delivered
9580     * to {@link #onHoverEvent(MotionEvent)}.
9581     * </p>
9582     *
9583     * @param event The motion event to be dispatched.
9584     * @return True if the event was handled by the view, false otherwise.
9585     */
9586    public boolean dispatchGenericMotionEvent(MotionEvent event) {
9587        if (mInputEventConsistencyVerifier != null) {
9588            mInputEventConsistencyVerifier.onGenericMotionEvent(event, 0);
9589        }
9590
9591        final int source = event.getSource();
9592        if ((source & InputDevice.SOURCE_CLASS_POINTER) != 0) {
9593            final int action = event.getAction();
9594            if (action == MotionEvent.ACTION_HOVER_ENTER
9595                    || action == MotionEvent.ACTION_HOVER_MOVE
9596                    || action == MotionEvent.ACTION_HOVER_EXIT) {
9597                if (dispatchHoverEvent(event)) {
9598                    return true;
9599                }
9600            } else if (dispatchGenericPointerEvent(event)) {
9601                return true;
9602            }
9603        } else if (dispatchGenericFocusedEvent(event)) {
9604            return true;
9605        }
9606
9607        if (dispatchGenericMotionEventInternal(event)) {
9608            return true;
9609        }
9610
9611        if (mInputEventConsistencyVerifier != null) {
9612            mInputEventConsistencyVerifier.onUnhandledEvent(event, 0);
9613        }
9614        return false;
9615    }
9616
9617    private boolean dispatchGenericMotionEventInternal(MotionEvent event) {
9618        //noinspection SimplifiableIfStatement
9619        ListenerInfo li = mListenerInfo;
9620        if (li != null && li.mOnGenericMotionListener != null
9621                && (mViewFlags & ENABLED_MASK) == ENABLED
9622                && li.mOnGenericMotionListener.onGenericMotion(this, event)) {
9623            return true;
9624        }
9625
9626        if (onGenericMotionEvent(event)) {
9627            return true;
9628        }
9629
9630        final int actionButton = event.getActionButton();
9631        switch (event.getActionMasked()) {
9632            case MotionEvent.ACTION_BUTTON_PRESS:
9633                if (isContextClickable() && !mInContextButtonPress && !mHasPerformedLongPress
9634                        && (actionButton == MotionEvent.BUTTON_STYLUS_PRIMARY
9635                        || actionButton == MotionEvent.BUTTON_SECONDARY)) {
9636                    if (performContextClick()) {
9637                        mInContextButtonPress = true;
9638                        setPressed(true, event.getX(), event.getY());
9639                        removeTapCallback();
9640                        removeLongPressCallback();
9641                        return true;
9642                    }
9643                }
9644                break;
9645
9646            case MotionEvent.ACTION_BUTTON_RELEASE:
9647                if (mInContextButtonPress && (actionButton == MotionEvent.BUTTON_STYLUS_PRIMARY
9648                        || actionButton == MotionEvent.BUTTON_SECONDARY)) {
9649                    mInContextButtonPress = false;
9650                    mIgnoreNextUpEvent = true;
9651                }
9652                break;
9653        }
9654
9655        if (mInputEventConsistencyVerifier != null) {
9656            mInputEventConsistencyVerifier.onUnhandledEvent(event, 0);
9657        }
9658        return false;
9659    }
9660
9661    /**
9662     * Dispatch a hover event.
9663     * <p>
9664     * Do not call this method directly.
9665     * Call {@link #dispatchGenericMotionEvent(MotionEvent)} instead.
9666     * </p>
9667     *
9668     * @param event The motion event to be dispatched.
9669     * @return True if the event was handled by the view, false otherwise.
9670     */
9671    protected boolean dispatchHoverEvent(MotionEvent event) {
9672        ListenerInfo li = mListenerInfo;
9673        //noinspection SimplifiableIfStatement
9674        if (li != null && li.mOnHoverListener != null
9675                && (mViewFlags & ENABLED_MASK) == ENABLED
9676                && li.mOnHoverListener.onHover(this, event)) {
9677            return true;
9678        }
9679
9680        return onHoverEvent(event);
9681    }
9682
9683    /**
9684     * Returns true if the view has a child to which it has recently sent
9685     * {@link MotionEvent#ACTION_HOVER_ENTER}.  If this view is hovered and
9686     * it does not have a hovered child, then it must be the innermost hovered view.
9687     * @hide
9688     */
9689    protected boolean hasHoveredChild() {
9690        return false;
9691    }
9692
9693    /**
9694     * Dispatch a generic motion event to the view under the first pointer.
9695     * <p>
9696     * Do not call this method directly.
9697     * Call {@link #dispatchGenericMotionEvent(MotionEvent)} instead.
9698     * </p>
9699     *
9700     * @param event The motion event to be dispatched.
9701     * @return True if the event was handled by the view, false otherwise.
9702     */
9703    protected boolean dispatchGenericPointerEvent(MotionEvent event) {
9704        return false;
9705    }
9706
9707    /**
9708     * Dispatch a generic motion event to the currently focused view.
9709     * <p>
9710     * Do not call this method directly.
9711     * Call {@link #dispatchGenericMotionEvent(MotionEvent)} instead.
9712     * </p>
9713     *
9714     * @param event The motion event to be dispatched.
9715     * @return True if the event was handled by the view, false otherwise.
9716     */
9717    protected boolean dispatchGenericFocusedEvent(MotionEvent event) {
9718        return false;
9719    }
9720
9721    /**
9722     * Dispatch a pointer event.
9723     * <p>
9724     * Dispatches touch related pointer events to {@link #onTouchEvent(MotionEvent)} and all
9725     * other events to {@link #onGenericMotionEvent(MotionEvent)}.  This separation of concerns
9726     * reinforces the invariant that {@link #onTouchEvent(MotionEvent)} is really about touches
9727     * and should not be expected to handle other pointing device features.
9728     * </p>
9729     *
9730     * @param event The motion event to be dispatched.
9731     * @return True if the event was handled by the view, false otherwise.
9732     * @hide
9733     */
9734    public final boolean dispatchPointerEvent(MotionEvent event) {
9735        if (event.isTouchEvent()) {
9736            return dispatchTouchEvent(event);
9737        } else {
9738            return dispatchGenericMotionEvent(event);
9739        }
9740    }
9741
9742    /**
9743     * Called when the window containing this view gains or loses window focus.
9744     * ViewGroups should override to route to their children.
9745     *
9746     * @param hasFocus True if the window containing this view now has focus,
9747     *        false otherwise.
9748     */
9749    public void dispatchWindowFocusChanged(boolean hasFocus) {
9750        onWindowFocusChanged(hasFocus);
9751    }
9752
9753    /**
9754     * Called when the window containing this view gains or loses focus.  Note
9755     * that this is separate from view focus: to receive key events, both
9756     * your view and its window must have focus.  If a window is displayed
9757     * on top of yours that takes input focus, then your own window will lose
9758     * focus but the view focus will remain unchanged.
9759     *
9760     * @param hasWindowFocus True if the window containing this view now has
9761     *        focus, false otherwise.
9762     */
9763    public void onWindowFocusChanged(boolean hasWindowFocus) {
9764        InputMethodManager imm = InputMethodManager.peekInstance();
9765        if (!hasWindowFocus) {
9766            if (isPressed()) {
9767                setPressed(false);
9768            }
9769            if (imm != null && (mPrivateFlags & PFLAG_FOCUSED) != 0) {
9770                imm.focusOut(this);
9771            }
9772            removeLongPressCallback();
9773            removeTapCallback();
9774            onFocusLost();
9775        } else if (imm != null && (mPrivateFlags & PFLAG_FOCUSED) != 0) {
9776            imm.focusIn(this);
9777        }
9778        refreshDrawableState();
9779    }
9780
9781    /**
9782     * Returns true if this view is in a window that currently has window focus.
9783     * Note that this is not the same as the view itself having focus.
9784     *
9785     * @return True if this view is in a window that currently has window focus.
9786     */
9787    public boolean hasWindowFocus() {
9788        return mAttachInfo != null && mAttachInfo.mHasWindowFocus;
9789    }
9790
9791    /**
9792     * Dispatch a view visibility change down the view hierarchy.
9793     * ViewGroups should override to route to their children.
9794     * @param changedView The view whose visibility changed. Could be 'this' or
9795     * an ancestor view.
9796     * @param visibility The new visibility of changedView: {@link #VISIBLE},
9797     * {@link #INVISIBLE} or {@link #GONE}.
9798     */
9799    protected void dispatchVisibilityChanged(@NonNull View changedView,
9800            @Visibility int visibility) {
9801        onVisibilityChanged(changedView, visibility);
9802    }
9803
9804    /**
9805     * Called when the visibility of the view or an ancestor of the view has
9806     * changed.
9807     *
9808     * @param changedView The view whose visibility changed. May be
9809     *                    {@code this} or an ancestor view.
9810     * @param visibility The new visibility, one of {@link #VISIBLE},
9811     *                   {@link #INVISIBLE} or {@link #GONE}.
9812     */
9813    protected void onVisibilityChanged(@NonNull View changedView, @Visibility int visibility) {
9814        final boolean visible = visibility == VISIBLE && getVisibility() == VISIBLE;
9815        if (visible && mAttachInfo != null) {
9816            initialAwakenScrollBars();
9817        }
9818
9819        final Drawable dr = mBackground;
9820        if (dr != null && visible != dr.isVisible()) {
9821            dr.setVisible(visible, false);
9822        }
9823        final Drawable fg = mForegroundInfo != null ? mForegroundInfo.mDrawable : null;
9824        if (fg != null && visible != fg.isVisible()) {
9825            fg.setVisible(visible, false);
9826        }
9827    }
9828
9829    /**
9830     * Dispatch a hint about whether this view is displayed. For instance, when
9831     * a View moves out of the screen, it might receives a display hint indicating
9832     * the view is not displayed. Applications should not <em>rely</em> on this hint
9833     * as there is no guarantee that they will receive one.
9834     *
9835     * @param hint A hint about whether or not this view is displayed:
9836     * {@link #VISIBLE} or {@link #INVISIBLE}.
9837     */
9838    public void dispatchDisplayHint(@Visibility int hint) {
9839        onDisplayHint(hint);
9840    }
9841
9842    /**
9843     * Gives this view a hint about whether is displayed or not. For instance, when
9844     * a View moves out of the screen, it might receives a display hint indicating
9845     * the view is not displayed. Applications should not <em>rely</em> on this hint
9846     * as there is no guarantee that they will receive one.
9847     *
9848     * @param hint A hint about whether or not this view is displayed:
9849     * {@link #VISIBLE} or {@link #INVISIBLE}.
9850     */
9851    protected void onDisplayHint(@Visibility int hint) {
9852    }
9853
9854    /**
9855     * Dispatch a window visibility change down the view hierarchy.
9856     * ViewGroups should override to route to their children.
9857     *
9858     * @param visibility The new visibility of the window.
9859     *
9860     * @see #onWindowVisibilityChanged(int)
9861     */
9862    public void dispatchWindowVisibilityChanged(@Visibility int visibility) {
9863        onWindowVisibilityChanged(visibility);
9864    }
9865
9866    /**
9867     * Called when the window containing has change its visibility
9868     * (between {@link #GONE}, {@link #INVISIBLE}, and {@link #VISIBLE}).  Note
9869     * that this tells you whether or not your window is being made visible
9870     * to the window manager; this does <em>not</em> tell you whether or not
9871     * your window is obscured by other windows on the screen, even if it
9872     * is itself visible.
9873     *
9874     * @param visibility The new visibility of the window.
9875     */
9876    protected void onWindowVisibilityChanged(@Visibility int visibility) {
9877        if (visibility == VISIBLE) {
9878            initialAwakenScrollBars();
9879        }
9880    }
9881
9882    /**
9883     * Returns the current visibility of the window this view is attached to
9884     * (either {@link #GONE}, {@link #INVISIBLE}, or {@link #VISIBLE}).
9885     *
9886     * @return Returns the current visibility of the view's window.
9887     */
9888    @Visibility
9889    public int getWindowVisibility() {
9890        return mAttachInfo != null ? mAttachInfo.mWindowVisibility : GONE;
9891    }
9892
9893    /**
9894     * Retrieve the overall visible display size in which the window this view is
9895     * attached to has been positioned in.  This takes into account screen
9896     * decorations above the window, for both cases where the window itself
9897     * is being position inside of them or the window is being placed under
9898     * then and covered insets are used for the window to position its content
9899     * inside.  In effect, this tells you the available area where content can
9900     * be placed and remain visible to users.
9901     *
9902     * <p>This function requires an IPC back to the window manager to retrieve
9903     * the requested information, so should not be used in performance critical
9904     * code like drawing.
9905     *
9906     * @param outRect Filled in with the visible display frame.  If the view
9907     * is not attached to a window, this is simply the raw display size.
9908     */
9909    public void getWindowVisibleDisplayFrame(Rect outRect) {
9910        if (mAttachInfo != null) {
9911            try {
9912                mAttachInfo.mSession.getDisplayFrame(mAttachInfo.mWindow, outRect);
9913            } catch (RemoteException e) {
9914                return;
9915            }
9916            // XXX This is really broken, and probably all needs to be done
9917            // in the window manager, and we need to know more about whether
9918            // we want the area behind or in front of the IME.
9919            final Rect insets = mAttachInfo.mVisibleInsets;
9920            outRect.left += insets.left;
9921            outRect.top += insets.top;
9922            outRect.right -= insets.right;
9923            outRect.bottom -= insets.bottom;
9924            return;
9925        }
9926        // The view is not attached to a display so we don't have a context.
9927        // Make a best guess about the display size.
9928        Display d = DisplayManagerGlobal.getInstance().getRealDisplay(Display.DEFAULT_DISPLAY);
9929        d.getRectSize(outRect);
9930    }
9931
9932    /**
9933     * Dispatch a notification about a resource configuration change down
9934     * the view hierarchy.
9935     * ViewGroups should override to route to their children.
9936     *
9937     * @param newConfig The new resource configuration.
9938     *
9939     * @see #onConfigurationChanged(android.content.res.Configuration)
9940     */
9941    public void dispatchConfigurationChanged(Configuration newConfig) {
9942        onConfigurationChanged(newConfig);
9943    }
9944
9945    /**
9946     * Called when the current configuration of the resources being used
9947     * by the application have changed.  You can use this to decide when
9948     * to reload resources that can changed based on orientation and other
9949     * configuration characteristics.  You only need to use this if you are
9950     * not relying on the normal {@link android.app.Activity} mechanism of
9951     * recreating the activity instance upon a configuration change.
9952     *
9953     * @param newConfig The new resource configuration.
9954     */
9955    protected void onConfigurationChanged(Configuration newConfig) {
9956    }
9957
9958    /**
9959     * Private function to aggregate all per-view attributes in to the view
9960     * root.
9961     */
9962    void dispatchCollectViewAttributes(AttachInfo attachInfo, int visibility) {
9963        performCollectViewAttributes(attachInfo, visibility);
9964    }
9965
9966    void performCollectViewAttributes(AttachInfo attachInfo, int visibility) {
9967        if ((visibility & VISIBILITY_MASK) == VISIBLE) {
9968            if ((mViewFlags & KEEP_SCREEN_ON) == KEEP_SCREEN_ON) {
9969                attachInfo.mKeepScreenOn = true;
9970            }
9971            attachInfo.mSystemUiVisibility |= mSystemUiVisibility;
9972            ListenerInfo li = mListenerInfo;
9973            if (li != null && li.mOnSystemUiVisibilityChangeListener != null) {
9974                attachInfo.mHasSystemUiListeners = true;
9975            }
9976        }
9977    }
9978
9979    void needGlobalAttributesUpdate(boolean force) {
9980        final AttachInfo ai = mAttachInfo;
9981        if (ai != null && !ai.mRecomputeGlobalAttributes) {
9982            if (force || ai.mKeepScreenOn || (ai.mSystemUiVisibility != 0)
9983                    || ai.mHasSystemUiListeners) {
9984                ai.mRecomputeGlobalAttributes = true;
9985            }
9986        }
9987    }
9988
9989    /**
9990     * Returns whether the device is currently in touch mode.  Touch mode is entered
9991     * once the user begins interacting with the device by touch, and affects various
9992     * things like whether focus is always visible to the user.
9993     *
9994     * @return Whether the device is in touch mode.
9995     */
9996    @ViewDebug.ExportedProperty
9997    public boolean isInTouchMode() {
9998        if (mAttachInfo != null) {
9999            return mAttachInfo.mInTouchMode;
10000        } else {
10001            return ViewRootImpl.isInTouchMode();
10002        }
10003    }
10004
10005    /**
10006     * Returns the context the view is running in, through which it can
10007     * access the current theme, resources, etc.
10008     *
10009     * @return The view's Context.
10010     */
10011    @ViewDebug.CapturedViewProperty
10012    public final Context getContext() {
10013        return mContext;
10014    }
10015
10016    /**
10017     * Handle a key event before it is processed by any input method
10018     * associated with the view hierarchy.  This can be used to intercept
10019     * key events in special situations before the IME consumes them; a
10020     * typical example would be handling the BACK key to update the application's
10021     * UI instead of allowing the IME to see it and close itself.
10022     *
10023     * @param keyCode The value in event.getKeyCode().
10024     * @param event Description of the key event.
10025     * @return If you handled the event, return true. If you want to allow the
10026     *         event to be handled by the next receiver, return false.
10027     */
10028    public boolean onKeyPreIme(int keyCode, KeyEvent event) {
10029        return false;
10030    }
10031
10032    /**
10033     * Default implementation of {@link KeyEvent.Callback#onKeyDown(int, KeyEvent)
10034     * KeyEvent.Callback.onKeyDown()}: perform press of the view
10035     * when {@link KeyEvent#KEYCODE_DPAD_CENTER} or {@link KeyEvent#KEYCODE_ENTER}
10036     * is released, if the view is enabled and clickable.
10037     * <p>
10038     * Key presses in software keyboards will generally NOT trigger this
10039     * listener, although some may elect to do so in some situations. Do not
10040     * rely on this to catch software key presses.
10041     *
10042     * @param keyCode a key code that represents the button pressed, from
10043     *                {@link android.view.KeyEvent}
10044     * @param event the KeyEvent object that defines the button action
10045     */
10046    public boolean onKeyDown(int keyCode, KeyEvent event) {
10047        if (KeyEvent.isConfirmKey(keyCode)) {
10048            if ((mViewFlags & ENABLED_MASK) == DISABLED) {
10049                return true;
10050            }
10051
10052            // Long clickable items don't necessarily have to be clickable.
10053            if (((mViewFlags & CLICKABLE) == CLICKABLE
10054                    || (mViewFlags & LONG_CLICKABLE) == LONG_CLICKABLE)
10055                    && (event.getRepeatCount() == 0)) {
10056                // For the purposes of menu anchoring and drawable hotspots,
10057                // key events are considered to be at the center of the view.
10058                final float x = getWidth() / 2f;
10059                final float y = getHeight() / 2f;
10060                setPressed(true, x, y);
10061                checkForLongClick(0, x, y);
10062                return true;
10063            }
10064        }
10065
10066        return false;
10067    }
10068
10069    /**
10070     * Default implementation of {@link KeyEvent.Callback#onKeyLongPress(int, KeyEvent)
10071     * KeyEvent.Callback.onKeyLongPress()}: always returns false (doesn't handle
10072     * the event).
10073     * <p>Key presses in software keyboards will generally NOT trigger this listener,
10074     * although some may elect to do so in some situations. Do not rely on this to
10075     * catch software key presses.
10076     */
10077    public boolean onKeyLongPress(int keyCode, KeyEvent event) {
10078        return false;
10079    }
10080
10081    /**
10082     * Default implementation of {@link KeyEvent.Callback#onKeyUp(int, KeyEvent)
10083     * KeyEvent.Callback.onKeyUp()}: perform clicking of the view
10084     * when {@link KeyEvent#KEYCODE_DPAD_CENTER} or
10085     * {@link KeyEvent#KEYCODE_ENTER} is released.
10086     * <p>Key presses in software keyboards will generally NOT trigger this listener,
10087     * although some may elect to do so in some situations. Do not rely on this to
10088     * catch software key presses.
10089     *
10090     * @param keyCode A key code that represents the button pressed, from
10091     *                {@link android.view.KeyEvent}.
10092     * @param event   The KeyEvent object that defines the button action.
10093     */
10094    public boolean onKeyUp(int keyCode, KeyEvent event) {
10095        if (KeyEvent.isConfirmKey(keyCode)) {
10096            if ((mViewFlags & ENABLED_MASK) == DISABLED) {
10097                return true;
10098            }
10099            if ((mViewFlags & CLICKABLE) == CLICKABLE && isPressed()) {
10100                setPressed(false);
10101
10102                if (!mHasPerformedLongPress) {
10103                    // This is a tap, so remove the longpress check
10104                    removeLongPressCallback();
10105                    return performClick();
10106                }
10107            }
10108        }
10109        return false;
10110    }
10111
10112    /**
10113     * Default implementation of {@link KeyEvent.Callback#onKeyMultiple(int, int, KeyEvent)
10114     * KeyEvent.Callback.onKeyMultiple()}: 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     * @param keyCode     A key code that represents the button pressed, from
10121     *                    {@link android.view.KeyEvent}.
10122     * @param repeatCount The number of times the action was made.
10123     * @param event       The KeyEvent object that defines the button action.
10124     */
10125    public boolean onKeyMultiple(int keyCode, int repeatCount, KeyEvent event) {
10126        return false;
10127    }
10128
10129    /**
10130     * Called on the focused view when a key shortcut event is not handled.
10131     * Override this method to implement local key shortcuts for the View.
10132     * Key shortcuts can also be implemented by setting the
10133     * {@link MenuItem#setShortcut(char, char) shortcut} property of menu items.
10134     *
10135     * @param keyCode The value in event.getKeyCode().
10136     * @param event Description of the key event.
10137     * @return If you handled the event, return true. If you want to allow the
10138     *         event to be handled by the next receiver, return false.
10139     */
10140    public boolean onKeyShortcut(int keyCode, KeyEvent event) {
10141        return false;
10142    }
10143
10144    /**
10145     * Check whether the called view is a text editor, in which case it
10146     * would make sense to automatically display a soft input window for
10147     * it.  Subclasses should override this if they implement
10148     * {@link #onCreateInputConnection(EditorInfo)} to return true if
10149     * a call on that method would return a non-null InputConnection, and
10150     * they are really a first-class editor that the user would normally
10151     * start typing on when the go into a window containing your view.
10152     *
10153     * <p>The default implementation always returns false.  This does
10154     * <em>not</em> mean that its {@link #onCreateInputConnection(EditorInfo)}
10155     * will not be called or the user can not otherwise perform edits on your
10156     * view; it is just a hint to the system that this is not the primary
10157     * purpose of this view.
10158     *
10159     * @return Returns true if this view is a text editor, else false.
10160     */
10161    public boolean onCheckIsTextEditor() {
10162        return false;
10163    }
10164
10165    /**
10166     * Create a new InputConnection for an InputMethod to interact
10167     * with the view.  The default implementation returns null, since it doesn't
10168     * support input methods.  You can override this to implement such support.
10169     * This is only needed for views that take focus and text input.
10170     *
10171     * <p>When implementing this, you probably also want to implement
10172     * {@link #onCheckIsTextEditor()} to indicate you will return a
10173     * non-null InputConnection.</p>
10174     *
10175     * <p>Also, take good care to fill in the {@link android.view.inputmethod.EditorInfo}
10176     * object correctly and in its entirety, so that the connected IME can rely
10177     * on its values. For example, {@link android.view.inputmethod.EditorInfo#initialSelStart}
10178     * and  {@link android.view.inputmethod.EditorInfo#initialSelEnd} members
10179     * must be filled in with the correct cursor position for IMEs to work correctly
10180     * with your application.</p>
10181     *
10182     * @param outAttrs Fill in with attribute information about the connection.
10183     */
10184    public InputConnection onCreateInputConnection(EditorInfo outAttrs) {
10185        return null;
10186    }
10187
10188    /**
10189     * Called by the {@link android.view.inputmethod.InputMethodManager}
10190     * when a view who is not the current
10191     * input connection target is trying to make a call on the manager.  The
10192     * default implementation returns false; you can override this to return
10193     * true for certain views if you are performing InputConnection proxying
10194     * to them.
10195     * @param view The View that is making the InputMethodManager call.
10196     * @return Return true to allow the call, false to reject.
10197     */
10198    public boolean checkInputConnectionProxy(View view) {
10199        return false;
10200    }
10201
10202    /**
10203     * Show the context menu for this view. It is not safe to hold on to the
10204     * menu after returning from this method.
10205     *
10206     * You should normally not overload this method. Overload
10207     * {@link #onCreateContextMenu(ContextMenu)} or define an
10208     * {@link OnCreateContextMenuListener} to add items to the context menu.
10209     *
10210     * @param menu The context menu to populate
10211     */
10212    public void createContextMenu(ContextMenu menu) {
10213        ContextMenuInfo menuInfo = getContextMenuInfo();
10214
10215        // Sets the current menu info so all items added to menu will have
10216        // my extra info set.
10217        ((MenuBuilder)menu).setCurrentMenuInfo(menuInfo);
10218
10219        onCreateContextMenu(menu);
10220        ListenerInfo li = mListenerInfo;
10221        if (li != null && li.mOnCreateContextMenuListener != null) {
10222            li.mOnCreateContextMenuListener.onCreateContextMenu(menu, this, menuInfo);
10223        }
10224
10225        // Clear the extra information so subsequent items that aren't mine don't
10226        // have my extra info.
10227        ((MenuBuilder)menu).setCurrentMenuInfo(null);
10228
10229        if (mParent != null) {
10230            mParent.createContextMenu(menu);
10231        }
10232    }
10233
10234    /**
10235     * Views should implement this if they have extra information to associate
10236     * with the context menu. The return result is supplied as a parameter to
10237     * the {@link OnCreateContextMenuListener#onCreateContextMenu(ContextMenu, View, ContextMenuInfo)}
10238     * callback.
10239     *
10240     * @return Extra information about the item for which the context menu
10241     *         should be shown. This information will vary across different
10242     *         subclasses of View.
10243     */
10244    protected ContextMenuInfo getContextMenuInfo() {
10245        return null;
10246    }
10247
10248    /**
10249     * Views should implement this if the view itself is going to add items to
10250     * the context menu.
10251     *
10252     * @param menu the context menu to populate
10253     */
10254    protected void onCreateContextMenu(ContextMenu menu) {
10255    }
10256
10257    /**
10258     * Implement this method to handle trackball motion events.  The
10259     * <em>relative</em> movement of the trackball since the last event
10260     * can be retrieve with {@link MotionEvent#getX MotionEvent.getX()} and
10261     * {@link MotionEvent#getY MotionEvent.getY()}.  These are normalized so
10262     * that a movement of 1 corresponds to the user pressing one DPAD key (so
10263     * they will often be fractional values, representing the more fine-grained
10264     * movement information available from a trackball).
10265     *
10266     * @param event The motion event.
10267     * @return True if the event was handled, false otherwise.
10268     */
10269    public boolean onTrackballEvent(MotionEvent event) {
10270        return false;
10271    }
10272
10273    /**
10274     * Implement this method to handle generic motion events.
10275     * <p>
10276     * Generic motion events describe joystick movements, mouse hovers, track pad
10277     * touches, scroll wheel movements and other input events.  The
10278     * {@link MotionEvent#getSource() source} of the motion event specifies
10279     * the class of input that was received.  Implementations of this method
10280     * must examine the bits in the source before processing the event.
10281     * The following code example shows how this is done.
10282     * </p><p>
10283     * Generic motion events with source class {@link InputDevice#SOURCE_CLASS_POINTER}
10284     * are delivered to the view under the pointer.  All other generic motion events are
10285     * delivered to the focused view.
10286     * </p>
10287     * <pre> public boolean onGenericMotionEvent(MotionEvent event) {
10288     *     if (event.isFromSource(InputDevice.SOURCE_CLASS_JOYSTICK)) {
10289     *         if (event.getAction() == MotionEvent.ACTION_MOVE) {
10290     *             // process the joystick movement...
10291     *             return true;
10292     *         }
10293     *     }
10294     *     if (event.isFromSource(InputDevice.SOURCE_CLASS_POINTER)) {
10295     *         switch (event.getAction()) {
10296     *             case MotionEvent.ACTION_HOVER_MOVE:
10297     *                 // process the mouse hover movement...
10298     *                 return true;
10299     *             case MotionEvent.ACTION_SCROLL:
10300     *                 // process the scroll wheel movement...
10301     *                 return true;
10302     *         }
10303     *     }
10304     *     return super.onGenericMotionEvent(event);
10305     * }</pre>
10306     *
10307     * @param event The generic motion event being processed.
10308     * @return True if the event was handled, false otherwise.
10309     */
10310    public boolean onGenericMotionEvent(MotionEvent event) {
10311        return false;
10312    }
10313
10314    /**
10315     * Implement this method to handle hover events.
10316     * <p>
10317     * This method is called whenever a pointer is hovering into, over, or out of the
10318     * bounds of a view and the view is not currently being touched.
10319     * Hover events are represented as pointer events with action
10320     * {@link MotionEvent#ACTION_HOVER_ENTER}, {@link MotionEvent#ACTION_HOVER_MOVE},
10321     * or {@link MotionEvent#ACTION_HOVER_EXIT}.
10322     * </p>
10323     * <ul>
10324     * <li>The view receives a hover event with action {@link MotionEvent#ACTION_HOVER_ENTER}
10325     * when the pointer enters the bounds of the view.</li>
10326     * <li>The view receives a hover event with action {@link MotionEvent#ACTION_HOVER_MOVE}
10327     * when the pointer has already entered the bounds of the view and has moved.</li>
10328     * <li>The view receives a hover event with action {@link MotionEvent#ACTION_HOVER_EXIT}
10329     * when the pointer has exited the bounds of the view or when the pointer is
10330     * about to go down due to a button click, tap, or similar user action that
10331     * causes the view to be touched.</li>
10332     * </ul>
10333     * <p>
10334     * The view should implement this method to return true to indicate that it is
10335     * handling the hover event, such as by changing its drawable state.
10336     * </p><p>
10337     * The default implementation calls {@link #setHovered} to update the hovered state
10338     * of the view when a hover enter or hover exit event is received, if the view
10339     * is enabled and is clickable.  The default implementation also sends hover
10340     * accessibility events.
10341     * </p>
10342     *
10343     * @param event The motion event that describes the hover.
10344     * @return True if the view handled the hover event.
10345     *
10346     * @see #isHovered
10347     * @see #setHovered
10348     * @see #onHoverChanged
10349     */
10350    public boolean onHoverEvent(MotionEvent event) {
10351        // The root view may receive hover (or touch) events that are outside the bounds of
10352        // the window.  This code ensures that we only send accessibility events for
10353        // hovers that are actually within the bounds of the root view.
10354        final int action = event.getActionMasked();
10355        if (!mSendingHoverAccessibilityEvents) {
10356            if ((action == MotionEvent.ACTION_HOVER_ENTER
10357                    || action == MotionEvent.ACTION_HOVER_MOVE)
10358                    && !hasHoveredChild()
10359                    && pointInView(event.getX(), event.getY())) {
10360                sendAccessibilityHoverEvent(AccessibilityEvent.TYPE_VIEW_HOVER_ENTER);
10361                mSendingHoverAccessibilityEvents = true;
10362            }
10363        } else {
10364            if (action == MotionEvent.ACTION_HOVER_EXIT
10365                    || (action == MotionEvent.ACTION_MOVE
10366                            && !pointInView(event.getX(), event.getY()))) {
10367                mSendingHoverAccessibilityEvents = false;
10368                sendAccessibilityHoverEvent(AccessibilityEvent.TYPE_VIEW_HOVER_EXIT);
10369            }
10370        }
10371
10372        if (isHoverable()) {
10373            switch (action) {
10374                case MotionEvent.ACTION_HOVER_ENTER:
10375                    setHovered(true);
10376                    break;
10377                case MotionEvent.ACTION_HOVER_EXIT:
10378                    setHovered(false);
10379                    break;
10380            }
10381
10382            // Dispatch the event to onGenericMotionEvent before returning true.
10383            // This is to provide compatibility with existing applications that
10384            // handled HOVER_MOVE events in onGenericMotionEvent and that would
10385            // break because of the new default handling for hoverable views
10386            // in onHoverEvent.
10387            // Note that onGenericMotionEvent will be called by default when
10388            // onHoverEvent returns false (refer to dispatchGenericMotionEvent).
10389            dispatchGenericMotionEventInternal(event);
10390            // The event was already handled by calling setHovered(), so always
10391            // return true.
10392            return true;
10393        }
10394
10395        return false;
10396    }
10397
10398    /**
10399     * Returns true if the view should handle {@link #onHoverEvent}
10400     * by calling {@link #setHovered} to change its hovered state.
10401     *
10402     * @return True if the view is hoverable.
10403     */
10404    private boolean isHoverable() {
10405        final int viewFlags = mViewFlags;
10406        if ((viewFlags & ENABLED_MASK) == DISABLED) {
10407            return false;
10408        }
10409
10410        return (viewFlags & CLICKABLE) == CLICKABLE
10411                || (viewFlags & LONG_CLICKABLE) == LONG_CLICKABLE
10412                || (viewFlags & CONTEXT_CLICKABLE) == CONTEXT_CLICKABLE;
10413    }
10414
10415    /**
10416     * Returns true if the view is currently hovered.
10417     *
10418     * @return True if the view is currently hovered.
10419     *
10420     * @see #setHovered
10421     * @see #onHoverChanged
10422     */
10423    @ViewDebug.ExportedProperty
10424    public boolean isHovered() {
10425        return (mPrivateFlags & PFLAG_HOVERED) != 0;
10426    }
10427
10428    /**
10429     * Sets whether the view is currently hovered.
10430     * <p>
10431     * Calling this method also changes the drawable state of the view.  This
10432     * enables the view to react to hover by using different drawable resources
10433     * to change its appearance.
10434     * </p><p>
10435     * The {@link #onHoverChanged} method is called when the hovered state changes.
10436     * </p>
10437     *
10438     * @param hovered True if the view is hovered.
10439     *
10440     * @see #isHovered
10441     * @see #onHoverChanged
10442     */
10443    public void setHovered(boolean hovered) {
10444        if (hovered) {
10445            if ((mPrivateFlags & PFLAG_HOVERED) == 0) {
10446                mPrivateFlags |= PFLAG_HOVERED;
10447                refreshDrawableState();
10448                onHoverChanged(true);
10449            }
10450        } else {
10451            if ((mPrivateFlags & PFLAG_HOVERED) != 0) {
10452                mPrivateFlags &= ~PFLAG_HOVERED;
10453                refreshDrawableState();
10454                onHoverChanged(false);
10455            }
10456        }
10457    }
10458
10459    /**
10460     * Implement this method to handle hover state changes.
10461     * <p>
10462     * This method is called whenever the hover state changes as a result of a
10463     * call to {@link #setHovered}.
10464     * </p>
10465     *
10466     * @param hovered The current hover state, as returned by {@link #isHovered}.
10467     *
10468     * @see #isHovered
10469     * @see #setHovered
10470     */
10471    public void onHoverChanged(boolean hovered) {
10472    }
10473
10474    /**
10475     * Implement this method to handle touch screen motion events.
10476     * <p>
10477     * If this method is used to detect click actions, it is recommended that
10478     * the actions be performed by implementing and calling
10479     * {@link #performClick()}. This will ensure consistent system behavior,
10480     * including:
10481     * <ul>
10482     * <li>obeying click sound preferences
10483     * <li>dispatching OnClickListener calls
10484     * <li>handling {@link AccessibilityNodeInfo#ACTION_CLICK ACTION_CLICK} when
10485     * accessibility features are enabled
10486     * </ul>
10487     *
10488     * @param event The motion event.
10489     * @return True if the event was handled, false otherwise.
10490     */
10491    public boolean onTouchEvent(MotionEvent event) {
10492        final float x = event.getX();
10493        final float y = event.getY();
10494        final int viewFlags = mViewFlags;
10495        final int action = event.getAction();
10496
10497        if ((viewFlags & ENABLED_MASK) == DISABLED) {
10498            if (action == MotionEvent.ACTION_UP && (mPrivateFlags & PFLAG_PRESSED) != 0) {
10499                setPressed(false);
10500            }
10501            // A disabled view that is clickable still consumes the touch
10502            // events, it just doesn't respond to them.
10503            return (((viewFlags & CLICKABLE) == CLICKABLE
10504                    || (viewFlags & LONG_CLICKABLE) == LONG_CLICKABLE)
10505                    || (viewFlags & CONTEXT_CLICKABLE) == CONTEXT_CLICKABLE);
10506        }
10507
10508        if (mTouchDelegate != null) {
10509            if (mTouchDelegate.onTouchEvent(event)) {
10510                return true;
10511            }
10512        }
10513
10514        if (((viewFlags & CLICKABLE) == CLICKABLE ||
10515                (viewFlags & LONG_CLICKABLE) == LONG_CLICKABLE) ||
10516                (viewFlags & CONTEXT_CLICKABLE) == CONTEXT_CLICKABLE) {
10517            switch (action) {
10518                case MotionEvent.ACTION_UP:
10519                    boolean prepressed = (mPrivateFlags & PFLAG_PREPRESSED) != 0;
10520                    if ((mPrivateFlags & PFLAG_PRESSED) != 0 || prepressed) {
10521                        // take focus if we don't have it already and we should in
10522                        // touch mode.
10523                        boolean focusTaken = false;
10524                        if (isFocusable() && isFocusableInTouchMode() && !isFocused()) {
10525                            focusTaken = requestFocus();
10526                        }
10527
10528                        if (prepressed) {
10529                            // The button is being released before we actually
10530                            // showed it as pressed.  Make it show the pressed
10531                            // state now (before scheduling the click) to ensure
10532                            // the user sees it.
10533                            setPressed(true, x, y);
10534                       }
10535
10536                        if (!mHasPerformedLongPress && !mIgnoreNextUpEvent) {
10537                            // This is a tap, so remove the longpress check
10538                            removeLongPressCallback();
10539
10540                            // Only perform take click actions if we were in the pressed state
10541                            if (!focusTaken) {
10542                                // Use a Runnable and post this rather than calling
10543                                // performClick directly. This lets other visual state
10544                                // of the view update before click actions start.
10545                                if (mPerformClick == null) {
10546                                    mPerformClick = new PerformClick();
10547                                }
10548                                if (!post(mPerformClick)) {
10549                                    performClick();
10550                                }
10551                            }
10552                        }
10553
10554                        if (mUnsetPressedState == null) {
10555                            mUnsetPressedState = new UnsetPressedState();
10556                        }
10557
10558                        if (prepressed) {
10559                            postDelayed(mUnsetPressedState,
10560                                    ViewConfiguration.getPressedStateDuration());
10561                        } else if (!post(mUnsetPressedState)) {
10562                            // If the post failed, unpress right now
10563                            mUnsetPressedState.run();
10564                        }
10565
10566                        removeTapCallback();
10567                    }
10568                    mIgnoreNextUpEvent = false;
10569                    break;
10570
10571                case MotionEvent.ACTION_DOWN:
10572                    mHasPerformedLongPress = false;
10573
10574                    if (performButtonActionOnTouchDown(event)) {
10575                        break;
10576                    }
10577
10578                    // Walk up the hierarchy to determine if we're inside a scrolling container.
10579                    boolean isInScrollingContainer = isInScrollingContainer();
10580
10581                    // For views inside a scrolling container, delay the pressed feedback for
10582                    // a short period in case this is a scroll.
10583                    if (isInScrollingContainer) {
10584                        mPrivateFlags |= PFLAG_PREPRESSED;
10585                        if (mPendingCheckForTap == null) {
10586                            mPendingCheckForTap = new CheckForTap();
10587                        }
10588                        mPendingCheckForTap.x = event.getX();
10589                        mPendingCheckForTap.y = event.getY();
10590                        postDelayed(mPendingCheckForTap, ViewConfiguration.getTapTimeout());
10591                    } else {
10592                        // Not inside a scrolling container, so show the feedback right away
10593                        setPressed(true, x, y);
10594                        checkForLongClick(0, x, y);
10595                    }
10596                    break;
10597
10598                case MotionEvent.ACTION_CANCEL:
10599                    setPressed(false);
10600                    removeTapCallback();
10601                    removeLongPressCallback();
10602                    mInContextButtonPress = false;
10603                    mHasPerformedLongPress = false;
10604                    mIgnoreNextUpEvent = false;
10605                    break;
10606
10607                case MotionEvent.ACTION_MOVE:
10608                    drawableHotspotChanged(x, y);
10609
10610                    // Be lenient about moving outside of buttons
10611                    if (!pointInView(x, y, mTouchSlop)) {
10612                        // Outside button
10613                        removeTapCallback();
10614                        if ((mPrivateFlags & PFLAG_PRESSED) != 0) {
10615                            // Remove any future long press/tap checks
10616                            removeLongPressCallback();
10617
10618                            setPressed(false);
10619                        }
10620                    }
10621                    break;
10622            }
10623
10624            return true;
10625        }
10626
10627        return false;
10628    }
10629
10630    /**
10631     * @hide
10632     */
10633    public boolean isInScrollingContainer() {
10634        ViewParent p = getParent();
10635        while (p != null && p instanceof ViewGroup) {
10636            if (((ViewGroup) p).shouldDelayChildPressedState()) {
10637                return true;
10638            }
10639            p = p.getParent();
10640        }
10641        return false;
10642    }
10643
10644    /**
10645     * Remove the longpress detection timer.
10646     */
10647    private void removeLongPressCallback() {
10648        if (mPendingCheckForLongPress != null) {
10649          removeCallbacks(mPendingCheckForLongPress);
10650        }
10651    }
10652
10653    /**
10654     * Remove the pending click action
10655     */
10656    private void removePerformClickCallback() {
10657        if (mPerformClick != null) {
10658            removeCallbacks(mPerformClick);
10659        }
10660    }
10661
10662    /**
10663     * Remove the prepress detection timer.
10664     */
10665    private void removeUnsetPressCallback() {
10666        if ((mPrivateFlags & PFLAG_PRESSED) != 0 && mUnsetPressedState != null) {
10667            setPressed(false);
10668            removeCallbacks(mUnsetPressedState);
10669        }
10670    }
10671
10672    /**
10673     * Remove the tap detection timer.
10674     */
10675    private void removeTapCallback() {
10676        if (mPendingCheckForTap != null) {
10677            mPrivateFlags &= ~PFLAG_PREPRESSED;
10678            removeCallbacks(mPendingCheckForTap);
10679        }
10680    }
10681
10682    /**
10683     * Cancels a pending long press.  Your subclass can use this if you
10684     * want the context menu to come up if the user presses and holds
10685     * at the same place, but you don't want it to come up if they press
10686     * and then move around enough to cause scrolling.
10687     */
10688    public void cancelLongPress() {
10689        removeLongPressCallback();
10690
10691        /*
10692         * The prepressed state handled by the tap callback is a display
10693         * construct, but the tap callback will post a long press callback
10694         * less its own timeout. Remove it here.
10695         */
10696        removeTapCallback();
10697    }
10698
10699    /**
10700     * Remove the pending callback for sending a
10701     * {@link AccessibilityEvent#TYPE_VIEW_SCROLLED} accessibility event.
10702     */
10703    private void removeSendViewScrolledAccessibilityEventCallback() {
10704        if (mSendViewScrolledAccessibilityEvent != null) {
10705            removeCallbacks(mSendViewScrolledAccessibilityEvent);
10706            mSendViewScrolledAccessibilityEvent.mIsPending = false;
10707        }
10708    }
10709
10710    /**
10711     * Sets the TouchDelegate for this View.
10712     */
10713    public void setTouchDelegate(TouchDelegate delegate) {
10714        mTouchDelegate = delegate;
10715    }
10716
10717    /**
10718     * Gets the TouchDelegate for this View.
10719     */
10720    public TouchDelegate getTouchDelegate() {
10721        return mTouchDelegate;
10722    }
10723
10724    /**
10725     * Request unbuffered dispatch of the given stream of MotionEvents to this View.
10726     *
10727     * Until this View receives a corresponding {@link MotionEvent#ACTION_UP}, ask that the input
10728     * system not batch {@link MotionEvent}s but instead deliver them as soon as they're
10729     * available. This method should only be called for touch events.
10730     *
10731     * <p class="note">This api is not intended for most applications. Buffered dispatch
10732     * provides many of benefits, and just requesting unbuffered dispatch on most MotionEvent
10733     * streams will not improve your input latency. Side effects include: increased latency,
10734     * jittery scrolls and inability to take advantage of system resampling. Talk to your input
10735     * professional to see if {@link #requestUnbufferedDispatch(MotionEvent)} is right for
10736     * you.</p>
10737     */
10738    public final void requestUnbufferedDispatch(MotionEvent event) {
10739        final int action = event.getAction();
10740        if (mAttachInfo == null
10741                || action != MotionEvent.ACTION_DOWN && action != MotionEvent.ACTION_MOVE
10742                || !event.isTouchEvent()) {
10743            return;
10744        }
10745        mAttachInfo.mUnbufferedDispatchRequested = true;
10746    }
10747
10748    /**
10749     * Set flags controlling behavior of this view.
10750     *
10751     * @param flags Constant indicating the value which should be set
10752     * @param mask Constant indicating the bit range that should be changed
10753     */
10754    void setFlags(int flags, int mask) {
10755        final boolean accessibilityEnabled =
10756                AccessibilityManager.getInstance(mContext).isEnabled();
10757        final boolean oldIncludeForAccessibility = accessibilityEnabled && includeForAccessibility();
10758
10759        int old = mViewFlags;
10760        mViewFlags = (mViewFlags & ~mask) | (flags & mask);
10761
10762        int changed = mViewFlags ^ old;
10763        if (changed == 0) {
10764            return;
10765        }
10766        int privateFlags = mPrivateFlags;
10767
10768        /* Check if the FOCUSABLE bit has changed */
10769        if (((changed & FOCUSABLE_MASK) != 0) &&
10770                ((privateFlags & PFLAG_HAS_BOUNDS) !=0)) {
10771            if (((old & FOCUSABLE_MASK) == FOCUSABLE)
10772                    && ((privateFlags & PFLAG_FOCUSED) != 0)) {
10773                /* Give up focus if we are no longer focusable */
10774                clearFocus();
10775            } else if (((old & FOCUSABLE_MASK) == NOT_FOCUSABLE)
10776                    && ((privateFlags & PFLAG_FOCUSED) == 0)) {
10777                /*
10778                 * Tell the view system that we are now available to take focus
10779                 * if no one else already has it.
10780                 */
10781                if (mParent != null) mParent.focusableViewAvailable(this);
10782            }
10783        }
10784
10785        final int newVisibility = flags & VISIBILITY_MASK;
10786        if (newVisibility == VISIBLE) {
10787            if ((changed & VISIBILITY_MASK) != 0) {
10788                /*
10789                 * If this view is becoming visible, invalidate it in case it changed while
10790                 * it was not visible. Marking it drawn ensures that the invalidation will
10791                 * go through.
10792                 */
10793                mPrivateFlags |= PFLAG_DRAWN;
10794                invalidate(true);
10795
10796                needGlobalAttributesUpdate(true);
10797
10798                // a view becoming visible is worth notifying the parent
10799                // about in case nothing has focus.  even if this specific view
10800                // isn't focusable, it may contain something that is, so let
10801                // the root view try to give this focus if nothing else does.
10802                if ((mParent != null) && (mBottom > mTop) && (mRight > mLeft)) {
10803                    mParent.focusableViewAvailable(this);
10804                }
10805            }
10806        }
10807
10808        /* Check if the GONE bit has changed */
10809        if ((changed & GONE) != 0) {
10810            needGlobalAttributesUpdate(false);
10811            requestLayout();
10812
10813            if (((mViewFlags & VISIBILITY_MASK) == GONE)) {
10814                if (hasFocus()) clearFocus();
10815                clearAccessibilityFocus();
10816                destroyDrawingCache();
10817                if (mParent instanceof View) {
10818                    // GONE views noop invalidation, so invalidate the parent
10819                    ((View) mParent).invalidate(true);
10820                }
10821                // Mark the view drawn to ensure that it gets invalidated properly the next
10822                // time it is visible and gets invalidated
10823                mPrivateFlags |= PFLAG_DRAWN;
10824            }
10825            if (mAttachInfo != null) {
10826                mAttachInfo.mViewVisibilityChanged = true;
10827            }
10828        }
10829
10830        /* Check if the VISIBLE bit has changed */
10831        if ((changed & INVISIBLE) != 0) {
10832            needGlobalAttributesUpdate(false);
10833            /*
10834             * If this view is becoming invisible, set the DRAWN flag so that
10835             * the next invalidate() will not be skipped.
10836             */
10837            mPrivateFlags |= PFLAG_DRAWN;
10838
10839            if (((mViewFlags & VISIBILITY_MASK) == INVISIBLE)) {
10840                // root view becoming invisible shouldn't clear focus and accessibility focus
10841                if (getRootView() != this) {
10842                    if (hasFocus()) clearFocus();
10843                    clearAccessibilityFocus();
10844                }
10845            }
10846            if (mAttachInfo != null) {
10847                mAttachInfo.mViewVisibilityChanged = true;
10848            }
10849        }
10850
10851        if ((changed & VISIBILITY_MASK) != 0) {
10852            // If the view is invisible, cleanup its display list to free up resources
10853            if (newVisibility != VISIBLE && mAttachInfo != null) {
10854                cleanupDraw();
10855            }
10856
10857            if (mParent instanceof ViewGroup) {
10858                ((ViewGroup) mParent).onChildVisibilityChanged(this,
10859                        (changed & VISIBILITY_MASK), newVisibility);
10860                ((View) mParent).invalidate(true);
10861            } else if (mParent != null) {
10862                mParent.invalidateChild(this, null);
10863            }
10864
10865            if (mAttachInfo != null) {
10866                dispatchVisibilityChanged(this, newVisibility);
10867                notifySubtreeAccessibilityStateChangedIfNeeded();
10868            }
10869        }
10870
10871        if ((changed & WILL_NOT_CACHE_DRAWING) != 0) {
10872            destroyDrawingCache();
10873        }
10874
10875        if ((changed & DRAWING_CACHE_ENABLED) != 0) {
10876            destroyDrawingCache();
10877            mPrivateFlags &= ~PFLAG_DRAWING_CACHE_VALID;
10878            invalidateParentCaches();
10879        }
10880
10881        if ((changed & DRAWING_CACHE_QUALITY_MASK) != 0) {
10882            destroyDrawingCache();
10883            mPrivateFlags &= ~PFLAG_DRAWING_CACHE_VALID;
10884        }
10885
10886        if ((changed & DRAW_MASK) != 0) {
10887            if ((mViewFlags & WILL_NOT_DRAW) != 0) {
10888                if (mBackground != null
10889                        || (mForegroundInfo != null && mForegroundInfo.mDrawable != null)) {
10890                    mPrivateFlags &= ~PFLAG_SKIP_DRAW;
10891                } else {
10892                    mPrivateFlags |= PFLAG_SKIP_DRAW;
10893                }
10894            } else {
10895                mPrivateFlags &= ~PFLAG_SKIP_DRAW;
10896            }
10897            requestLayout();
10898            invalidate(true);
10899        }
10900
10901        if ((changed & KEEP_SCREEN_ON) != 0) {
10902            if (mParent != null && mAttachInfo != null && !mAttachInfo.mRecomputeGlobalAttributes) {
10903                mParent.recomputeViewAttributes(this);
10904            }
10905        }
10906
10907        if (accessibilityEnabled) {
10908            if ((changed & FOCUSABLE_MASK) != 0 || (changed & VISIBILITY_MASK) != 0
10909                    || (changed & CLICKABLE) != 0 || (changed & LONG_CLICKABLE) != 0
10910                    || (changed & CONTEXT_CLICKABLE) != 0) {
10911                if (oldIncludeForAccessibility != includeForAccessibility()) {
10912                    notifySubtreeAccessibilityStateChangedIfNeeded();
10913                } else {
10914                    notifyViewAccessibilityStateChangedIfNeeded(
10915                            AccessibilityEvent.CONTENT_CHANGE_TYPE_UNDEFINED);
10916                }
10917            } else if ((changed & ENABLED_MASK) != 0) {
10918                notifyViewAccessibilityStateChangedIfNeeded(
10919                        AccessibilityEvent.CONTENT_CHANGE_TYPE_UNDEFINED);
10920            }
10921        }
10922    }
10923
10924    /**
10925     * Change the view's z order in the tree, so it's on top of other sibling
10926     * views. This ordering change may affect layout, if the parent container
10927     * uses an order-dependent layout scheme (e.g., LinearLayout). Prior
10928     * to {@link android.os.Build.VERSION_CODES#KITKAT} this
10929     * method should be followed by calls to {@link #requestLayout()} and
10930     * {@link View#invalidate()} on the view's parent to force the parent to redraw
10931     * with the new child ordering.
10932     *
10933     * @see ViewGroup#bringChildToFront(View)
10934     */
10935    public void bringToFront() {
10936        if (mParent != null) {
10937            mParent.bringChildToFront(this);
10938        }
10939    }
10940
10941    /**
10942     * This is called in response to an internal scroll in this view (i.e., the
10943     * view scrolled its own contents). This is typically as a result of
10944     * {@link #scrollBy(int, int)} or {@link #scrollTo(int, int)} having been
10945     * called.
10946     *
10947     * @param l Current horizontal scroll origin.
10948     * @param t Current vertical scroll origin.
10949     * @param oldl Previous horizontal scroll origin.
10950     * @param oldt Previous vertical scroll origin.
10951     */
10952    protected void onScrollChanged(int l, int t, int oldl, int oldt) {
10953        notifySubtreeAccessibilityStateChangedIfNeeded();
10954
10955        if (AccessibilityManager.getInstance(mContext).isEnabled()) {
10956            postSendViewScrolledAccessibilityEventCallback();
10957        }
10958
10959        mBackgroundSizeChanged = true;
10960        if (mForegroundInfo != null) {
10961            mForegroundInfo.mBoundsChanged = true;
10962        }
10963
10964        final AttachInfo ai = mAttachInfo;
10965        if (ai != null) {
10966            ai.mViewScrollChanged = true;
10967        }
10968
10969        if (mListenerInfo != null && mListenerInfo.mOnScrollChangeListener != null) {
10970            mListenerInfo.mOnScrollChangeListener.onScrollChange(this, l, t, oldl, oldt);
10971        }
10972    }
10973
10974    /**
10975     * Interface definition for a callback to be invoked when the scroll
10976     * X or Y positions of a view change.
10977     * <p>
10978     * <b>Note:</b> Some views handle scrolling independently from View and may
10979     * have their own separate listeners for scroll-type events. For example,
10980     * {@link android.widget.ListView ListView} allows clients to register an
10981     * {@link android.widget.ListView#setOnScrollListener(android.widget.AbsListView.OnScrollListener) AbsListView.OnScrollListener}
10982     * to listen for changes in list scroll position.
10983     *
10984     * @see #setOnScrollChangeListener(View.OnScrollChangeListener)
10985     */
10986    public interface OnScrollChangeListener {
10987        /**
10988         * Called when the scroll position of a view changes.
10989         *
10990         * @param v The view whose scroll position has changed.
10991         * @param scrollX Current horizontal scroll origin.
10992         * @param scrollY Current vertical scroll origin.
10993         * @param oldScrollX Previous horizontal scroll origin.
10994         * @param oldScrollY Previous vertical scroll origin.
10995         */
10996        void onScrollChange(View v, int scrollX, int scrollY, int oldScrollX, int oldScrollY);
10997    }
10998
10999    /**
11000     * Interface definition for a callback to be invoked when the layout bounds of a view
11001     * changes due to layout processing.
11002     */
11003    public interface OnLayoutChangeListener {
11004        /**
11005         * Called when the layout bounds of a view changes due to layout processing.
11006         *
11007         * @param v The view whose bounds have changed.
11008         * @param left The new value of the view's left property.
11009         * @param top The new value of the view's top property.
11010         * @param right The new value of the view's right property.
11011         * @param bottom The new value of the view's bottom property.
11012         * @param oldLeft The previous value of the view's left property.
11013         * @param oldTop The previous value of the view's top property.
11014         * @param oldRight The previous value of the view's right property.
11015         * @param oldBottom The previous value of the view's bottom property.
11016         */
11017        void onLayoutChange(View v, int left, int top, int right, int bottom,
11018            int oldLeft, int oldTop, int oldRight, int oldBottom);
11019    }
11020
11021    /**
11022     * This is called during layout when the size of this view has changed. If
11023     * you were just added to the view hierarchy, you're called with the old
11024     * values of 0.
11025     *
11026     * @param w Current width of this view.
11027     * @param h Current height of this view.
11028     * @param oldw Old width of this view.
11029     * @param oldh Old height of this view.
11030     */
11031    protected void onSizeChanged(int w, int h, int oldw, int oldh) {
11032    }
11033
11034    /**
11035     * Called by draw to draw the child views. This may be overridden
11036     * by derived classes to gain control just before its children are drawn
11037     * (but after its own view has been drawn).
11038     * @param canvas the canvas on which to draw the view
11039     */
11040    protected void dispatchDraw(Canvas canvas) {
11041
11042    }
11043
11044    /**
11045     * Gets the parent of this view. Note that the parent is a
11046     * ViewParent and not necessarily a View.
11047     *
11048     * @return Parent of this view.
11049     */
11050    public final ViewParent getParent() {
11051        return mParent;
11052    }
11053
11054    /**
11055     * Set the horizontal scrolled position of your view. This will cause a call to
11056     * {@link #onScrollChanged(int, int, int, int)} and the view will be
11057     * invalidated.
11058     * @param value the x position to scroll to
11059     */
11060    public void setScrollX(int value) {
11061        scrollTo(value, mScrollY);
11062    }
11063
11064    /**
11065     * Set the vertical scrolled position of your view. This will cause a call to
11066     * {@link #onScrollChanged(int, int, int, int)} and the view will be
11067     * invalidated.
11068     * @param value the y position to scroll to
11069     */
11070    public void setScrollY(int value) {
11071        scrollTo(mScrollX, value);
11072    }
11073
11074    /**
11075     * Return the scrolled left position of this view. This is the left edge of
11076     * the displayed part of your view. You do not need to draw any pixels
11077     * farther left, since those are outside of the frame of your view on
11078     * screen.
11079     *
11080     * @return The left edge of the displayed part of your view, in pixels.
11081     */
11082    public final int getScrollX() {
11083        return mScrollX;
11084    }
11085
11086    /**
11087     * Return the scrolled top position of this view. This is the top edge of
11088     * the displayed part of your view. You do not need to draw any pixels above
11089     * it, since those are outside of the frame of your view on screen.
11090     *
11091     * @return The top edge of the displayed part of your view, in pixels.
11092     */
11093    public final int getScrollY() {
11094        return mScrollY;
11095    }
11096
11097    /**
11098     * Return the width of the your view.
11099     *
11100     * @return The width of your view, in pixels.
11101     */
11102    @ViewDebug.ExportedProperty(category = "layout")
11103    public final int getWidth() {
11104        return mRight - mLeft;
11105    }
11106
11107    /**
11108     * Return the height of your view.
11109     *
11110     * @return The height of your view, in pixels.
11111     */
11112    @ViewDebug.ExportedProperty(category = "layout")
11113    public final int getHeight() {
11114        return mBottom - mTop;
11115    }
11116
11117    /**
11118     * Return the visible drawing bounds of your view. Fills in the output
11119     * rectangle with the values from getScrollX(), getScrollY(),
11120     * getWidth(), and getHeight(). These bounds do not account for any
11121     * transformation properties currently set on the view, such as
11122     * {@link #setScaleX(float)} or {@link #setRotation(float)}.
11123     *
11124     * @param outRect The (scrolled) drawing bounds of the view.
11125     */
11126    public void getDrawingRect(Rect outRect) {
11127        outRect.left = mScrollX;
11128        outRect.top = mScrollY;
11129        outRect.right = mScrollX + (mRight - mLeft);
11130        outRect.bottom = mScrollY + (mBottom - mTop);
11131    }
11132
11133    /**
11134     * Like {@link #getMeasuredWidthAndState()}, but only returns the
11135     * raw width component (that is the result is masked by
11136     * {@link #MEASURED_SIZE_MASK}).
11137     *
11138     * @return The raw measured width of this view.
11139     */
11140    public final int getMeasuredWidth() {
11141        return mMeasuredWidth & MEASURED_SIZE_MASK;
11142    }
11143
11144    /**
11145     * Return the full width measurement information for this view as computed
11146     * by the most recent call to {@link #measure(int, int)}.  This result is a bit mask
11147     * as defined by {@link #MEASURED_SIZE_MASK} and {@link #MEASURED_STATE_TOO_SMALL}.
11148     * This should be used during measurement and layout calculations only. Use
11149     * {@link #getWidth()} to see how wide a view is after layout.
11150     *
11151     * @return The measured width of this view as a bit mask.
11152     */
11153    @ViewDebug.ExportedProperty(category = "measurement", flagMapping = {
11154            @ViewDebug.FlagToString(mask = MEASURED_STATE_MASK, equals = MEASURED_STATE_TOO_SMALL,
11155                    name = "MEASURED_STATE_TOO_SMALL"),
11156    })
11157    public final int getMeasuredWidthAndState() {
11158        return mMeasuredWidth;
11159    }
11160
11161    /**
11162     * Like {@link #getMeasuredHeightAndState()}, but only returns the
11163     * raw width component (that is the result is masked by
11164     * {@link #MEASURED_SIZE_MASK}).
11165     *
11166     * @return The raw measured height of this view.
11167     */
11168    public final int getMeasuredHeight() {
11169        return mMeasuredHeight & MEASURED_SIZE_MASK;
11170    }
11171
11172    /**
11173     * Return the full height measurement information for this view as computed
11174     * by the most recent call to {@link #measure(int, int)}.  This result is a bit mask
11175     * as defined by {@link #MEASURED_SIZE_MASK} and {@link #MEASURED_STATE_TOO_SMALL}.
11176     * This should be used during measurement and layout calculations only. Use
11177     * {@link #getHeight()} to see how wide a view is after layout.
11178     *
11179     * @return The measured width of this view as a bit mask.
11180     */
11181    @ViewDebug.ExportedProperty(category = "measurement", flagMapping = {
11182            @ViewDebug.FlagToString(mask = MEASURED_STATE_MASK, equals = MEASURED_STATE_TOO_SMALL,
11183                    name = "MEASURED_STATE_TOO_SMALL"),
11184    })
11185    public final int getMeasuredHeightAndState() {
11186        return mMeasuredHeight;
11187    }
11188
11189    /**
11190     * Return only the state bits of {@link #getMeasuredWidthAndState()}
11191     * and {@link #getMeasuredHeightAndState()}, combined into one integer.
11192     * The width component is in the regular bits {@link #MEASURED_STATE_MASK}
11193     * and the height component is at the shifted bits
11194     * {@link #MEASURED_HEIGHT_STATE_SHIFT}>>{@link #MEASURED_STATE_MASK}.
11195     */
11196    public final int getMeasuredState() {
11197        return (mMeasuredWidth&MEASURED_STATE_MASK)
11198                | ((mMeasuredHeight>>MEASURED_HEIGHT_STATE_SHIFT)
11199                        & (MEASURED_STATE_MASK>>MEASURED_HEIGHT_STATE_SHIFT));
11200    }
11201
11202    /**
11203     * The transform matrix of this view, which is calculated based on the current
11204     * rotation, scale, and pivot properties.
11205     *
11206     * @see #getRotation()
11207     * @see #getScaleX()
11208     * @see #getScaleY()
11209     * @see #getPivotX()
11210     * @see #getPivotY()
11211     * @return The current transform matrix for the view
11212     */
11213    public Matrix getMatrix() {
11214        ensureTransformationInfo();
11215        final Matrix matrix = mTransformationInfo.mMatrix;
11216        mRenderNode.getMatrix(matrix);
11217        return matrix;
11218    }
11219
11220    /**
11221     * Returns true if the transform matrix is the identity matrix.
11222     * Recomputes the matrix if necessary.
11223     *
11224     * @return True if the transform matrix is the identity matrix, false otherwise.
11225     */
11226    final boolean hasIdentityMatrix() {
11227        return mRenderNode.hasIdentityMatrix();
11228    }
11229
11230    void ensureTransformationInfo() {
11231        if (mTransformationInfo == null) {
11232            mTransformationInfo = new TransformationInfo();
11233        }
11234    }
11235
11236   /**
11237     * Utility method to retrieve the inverse of the current mMatrix property.
11238     * We cache the matrix to avoid recalculating it when transform properties
11239     * have not changed.
11240     *
11241     * @return The inverse of the current matrix of this view.
11242     * @hide
11243     */
11244    public final Matrix getInverseMatrix() {
11245        ensureTransformationInfo();
11246        if (mTransformationInfo.mInverseMatrix == null) {
11247            mTransformationInfo.mInverseMatrix = new Matrix();
11248        }
11249        final Matrix matrix = mTransformationInfo.mInverseMatrix;
11250        mRenderNode.getInverseMatrix(matrix);
11251        return matrix;
11252    }
11253
11254    /**
11255     * Gets the distance along the Z axis from the camera to this view.
11256     *
11257     * @see #setCameraDistance(float)
11258     *
11259     * @return The distance along the Z axis.
11260     */
11261    public float getCameraDistance() {
11262        final float dpi = mResources.getDisplayMetrics().densityDpi;
11263        return -(mRenderNode.getCameraDistance() * dpi);
11264    }
11265
11266    /**
11267     * <p>Sets the distance along the Z axis (orthogonal to the X/Y plane on which
11268     * views are drawn) from the camera to this view. The camera's distance
11269     * affects 3D transformations, for instance rotations around the X and Y
11270     * axis. If the rotationX or rotationY properties are changed and this view is
11271     * large (more than half the size of the screen), it is recommended to always
11272     * use a camera distance that's greater than the height (X axis rotation) or
11273     * the width (Y axis rotation) of this view.</p>
11274     *
11275     * <p>The distance of the camera from the view plane can have an affect on the
11276     * perspective distortion of the view when it is rotated around the x or y axis.
11277     * For example, a large distance will result in a large viewing angle, and there
11278     * will not be much perspective distortion of the view as it rotates. A short
11279     * distance may cause much more perspective distortion upon rotation, and can
11280     * also result in some drawing artifacts if the rotated view ends up partially
11281     * behind the camera (which is why the recommendation is to use a distance at
11282     * least as far as the size of the view, if the view is to be rotated.)</p>
11283     *
11284     * <p>The distance is expressed in "depth pixels." The default distance depends
11285     * on the screen density. For instance, on a medium density display, the
11286     * default distance is 1280. On a high density display, the default distance
11287     * is 1920.</p>
11288     *
11289     * <p>If you want to specify a distance that leads to visually consistent
11290     * results across various densities, use the following formula:</p>
11291     * <pre>
11292     * float scale = context.getResources().getDisplayMetrics().density;
11293     * view.setCameraDistance(distance * scale);
11294     * </pre>
11295     *
11296     * <p>The density scale factor of a high density display is 1.5,
11297     * and 1920 = 1280 * 1.5.</p>
11298     *
11299     * @param distance The distance in "depth pixels", if negative the opposite
11300     *        value is used
11301     *
11302     * @see #setRotationX(float)
11303     * @see #setRotationY(float)
11304     */
11305    public void setCameraDistance(float distance) {
11306        final float dpi = mResources.getDisplayMetrics().densityDpi;
11307
11308        invalidateViewProperty(true, false);
11309        mRenderNode.setCameraDistance(-Math.abs(distance) / dpi);
11310        invalidateViewProperty(false, false);
11311
11312        invalidateParentIfNeededAndWasQuickRejected();
11313    }
11314
11315    /**
11316     * The degrees that the view is rotated around the pivot point.
11317     *
11318     * @see #setRotation(float)
11319     * @see #getPivotX()
11320     * @see #getPivotY()
11321     *
11322     * @return The degrees of rotation.
11323     */
11324    @ViewDebug.ExportedProperty(category = "drawing")
11325    public float getRotation() {
11326        return mRenderNode.getRotation();
11327    }
11328
11329    /**
11330     * Sets the degrees that the view is rotated around the pivot point. Increasing values
11331     * result in clockwise rotation.
11332     *
11333     * @param rotation The degrees of rotation.
11334     *
11335     * @see #getRotation()
11336     * @see #getPivotX()
11337     * @see #getPivotY()
11338     * @see #setRotationX(float)
11339     * @see #setRotationY(float)
11340     *
11341     * @attr ref android.R.styleable#View_rotation
11342     */
11343    public void setRotation(float rotation) {
11344        if (rotation != getRotation()) {
11345            // Double-invalidation is necessary to capture view's old and new areas
11346            invalidateViewProperty(true, false);
11347            mRenderNode.setRotation(rotation);
11348            invalidateViewProperty(false, true);
11349
11350            invalidateParentIfNeededAndWasQuickRejected();
11351            notifySubtreeAccessibilityStateChangedIfNeeded();
11352        }
11353    }
11354
11355    /**
11356     * The degrees that the view is rotated around the vertical axis through the pivot point.
11357     *
11358     * @see #getPivotX()
11359     * @see #getPivotY()
11360     * @see #setRotationY(float)
11361     *
11362     * @return The degrees of Y rotation.
11363     */
11364    @ViewDebug.ExportedProperty(category = "drawing")
11365    public float getRotationY() {
11366        return mRenderNode.getRotationY();
11367    }
11368
11369    /**
11370     * Sets the degrees that the view is rotated around the vertical axis through the pivot point.
11371     * Increasing values result in counter-clockwise rotation from the viewpoint of looking
11372     * down the y axis.
11373     *
11374     * When rotating large views, it is recommended to adjust the camera distance
11375     * accordingly. Refer to {@link #setCameraDistance(float)} for more information.
11376     *
11377     * @param rotationY The degrees of Y rotation.
11378     *
11379     * @see #getRotationY()
11380     * @see #getPivotX()
11381     * @see #getPivotY()
11382     * @see #setRotation(float)
11383     * @see #setRotationX(float)
11384     * @see #setCameraDistance(float)
11385     *
11386     * @attr ref android.R.styleable#View_rotationY
11387     */
11388    public void setRotationY(float rotationY) {
11389        if (rotationY != getRotationY()) {
11390            invalidateViewProperty(true, false);
11391            mRenderNode.setRotationY(rotationY);
11392            invalidateViewProperty(false, true);
11393
11394            invalidateParentIfNeededAndWasQuickRejected();
11395            notifySubtreeAccessibilityStateChangedIfNeeded();
11396        }
11397    }
11398
11399    /**
11400     * The degrees that the view is rotated around the horizontal axis through the pivot point.
11401     *
11402     * @see #getPivotX()
11403     * @see #getPivotY()
11404     * @see #setRotationX(float)
11405     *
11406     * @return The degrees of X rotation.
11407     */
11408    @ViewDebug.ExportedProperty(category = "drawing")
11409    public float getRotationX() {
11410        return mRenderNode.getRotationX();
11411    }
11412
11413    /**
11414     * Sets the degrees that the view is rotated around the horizontal axis through the pivot point.
11415     * Increasing values result in clockwise rotation from the viewpoint of looking down the
11416     * x axis.
11417     *
11418     * When rotating large views, it is recommended to adjust the camera distance
11419     * accordingly. Refer to {@link #setCameraDistance(float)} for more information.
11420     *
11421     * @param rotationX The degrees of X rotation.
11422     *
11423     * @see #getRotationX()
11424     * @see #getPivotX()
11425     * @see #getPivotY()
11426     * @see #setRotation(float)
11427     * @see #setRotationY(float)
11428     * @see #setCameraDistance(float)
11429     *
11430     * @attr ref android.R.styleable#View_rotationX
11431     */
11432    public void setRotationX(float rotationX) {
11433        if (rotationX != getRotationX()) {
11434            invalidateViewProperty(true, false);
11435            mRenderNode.setRotationX(rotationX);
11436            invalidateViewProperty(false, true);
11437
11438            invalidateParentIfNeededAndWasQuickRejected();
11439            notifySubtreeAccessibilityStateChangedIfNeeded();
11440        }
11441    }
11442
11443    /**
11444     * The amount that the view is scaled in x around the pivot point, as a proportion of
11445     * the view's unscaled width. A value of 1, the default, means that no scaling is applied.
11446     *
11447     * <p>By default, this is 1.0f.
11448     *
11449     * @see #getPivotX()
11450     * @see #getPivotY()
11451     * @return The scaling factor.
11452     */
11453    @ViewDebug.ExportedProperty(category = "drawing")
11454    public float getScaleX() {
11455        return mRenderNode.getScaleX();
11456    }
11457
11458    /**
11459     * Sets the amount that the view is scaled in x around the pivot point, as a proportion of
11460     * the view's unscaled width. A value of 1 means that no scaling is applied.
11461     *
11462     * @param scaleX The scaling factor.
11463     * @see #getPivotX()
11464     * @see #getPivotY()
11465     *
11466     * @attr ref android.R.styleable#View_scaleX
11467     */
11468    public void setScaleX(float scaleX) {
11469        if (scaleX != getScaleX()) {
11470            invalidateViewProperty(true, false);
11471            mRenderNode.setScaleX(scaleX);
11472            invalidateViewProperty(false, true);
11473
11474            invalidateParentIfNeededAndWasQuickRejected();
11475            notifySubtreeAccessibilityStateChangedIfNeeded();
11476        }
11477    }
11478
11479    /**
11480     * The amount that the view is scaled in y around the pivot point, as a proportion of
11481     * the view's unscaled height. A value of 1, the default, means that no scaling is applied.
11482     *
11483     * <p>By default, this is 1.0f.
11484     *
11485     * @see #getPivotX()
11486     * @see #getPivotY()
11487     * @return The scaling factor.
11488     */
11489    @ViewDebug.ExportedProperty(category = "drawing")
11490    public float getScaleY() {
11491        return mRenderNode.getScaleY();
11492    }
11493
11494    /**
11495     * Sets the amount that the view is scaled in Y around the pivot point, as a proportion of
11496     * the view's unscaled width. A value of 1 means that no scaling is applied.
11497     *
11498     * @param scaleY The scaling factor.
11499     * @see #getPivotX()
11500     * @see #getPivotY()
11501     *
11502     * @attr ref android.R.styleable#View_scaleY
11503     */
11504    public void setScaleY(float scaleY) {
11505        if (scaleY != getScaleY()) {
11506            invalidateViewProperty(true, false);
11507            mRenderNode.setScaleY(scaleY);
11508            invalidateViewProperty(false, true);
11509
11510            invalidateParentIfNeededAndWasQuickRejected();
11511            notifySubtreeAccessibilityStateChangedIfNeeded();
11512        }
11513    }
11514
11515    /**
11516     * The x location of the point around which the view is {@link #setRotation(float) rotated}
11517     * and {@link #setScaleX(float) scaled}.
11518     *
11519     * @see #getRotation()
11520     * @see #getScaleX()
11521     * @see #getScaleY()
11522     * @see #getPivotY()
11523     * @return The x location of the pivot point.
11524     *
11525     * @attr ref android.R.styleable#View_transformPivotX
11526     */
11527    @ViewDebug.ExportedProperty(category = "drawing")
11528    public float getPivotX() {
11529        return mRenderNode.getPivotX();
11530    }
11531
11532    /**
11533     * Sets the x location of the point around which the view is
11534     * {@link #setRotation(float) rotated} and {@link #setScaleX(float) scaled}.
11535     * By default, the pivot point is centered on the object.
11536     * Setting this property disables this behavior and causes the view to use only the
11537     * explicitly set pivotX and pivotY values.
11538     *
11539     * @param pivotX The x location of the pivot point.
11540     * @see #getRotation()
11541     * @see #getScaleX()
11542     * @see #getScaleY()
11543     * @see #getPivotY()
11544     *
11545     * @attr ref android.R.styleable#View_transformPivotX
11546     */
11547    public void setPivotX(float pivotX) {
11548        if (!mRenderNode.isPivotExplicitlySet() || pivotX != getPivotX()) {
11549            invalidateViewProperty(true, false);
11550            mRenderNode.setPivotX(pivotX);
11551            invalidateViewProperty(false, true);
11552
11553            invalidateParentIfNeededAndWasQuickRejected();
11554        }
11555    }
11556
11557    /**
11558     * The y location of the point around which the view is {@link #setRotation(float) rotated}
11559     * and {@link #setScaleY(float) scaled}.
11560     *
11561     * @see #getRotation()
11562     * @see #getScaleX()
11563     * @see #getScaleY()
11564     * @see #getPivotY()
11565     * @return The y location of the pivot point.
11566     *
11567     * @attr ref android.R.styleable#View_transformPivotY
11568     */
11569    @ViewDebug.ExportedProperty(category = "drawing")
11570    public float getPivotY() {
11571        return mRenderNode.getPivotY();
11572    }
11573
11574    /**
11575     * Sets the y location of the point around which the view is {@link #setRotation(float) rotated}
11576     * and {@link #setScaleY(float) scaled}. By default, the pivot point is centered on the object.
11577     * Setting this property disables this behavior and causes the view to use only the
11578     * explicitly set pivotX and pivotY values.
11579     *
11580     * @param pivotY The y location of the pivot point.
11581     * @see #getRotation()
11582     * @see #getScaleX()
11583     * @see #getScaleY()
11584     * @see #getPivotY()
11585     *
11586     * @attr ref android.R.styleable#View_transformPivotY
11587     */
11588    public void setPivotY(float pivotY) {
11589        if (!mRenderNode.isPivotExplicitlySet() || pivotY != getPivotY()) {
11590            invalidateViewProperty(true, false);
11591            mRenderNode.setPivotY(pivotY);
11592            invalidateViewProperty(false, true);
11593
11594            invalidateParentIfNeededAndWasQuickRejected();
11595        }
11596    }
11597
11598    /**
11599     * The opacity of the view. This is a value from 0 to 1, where 0 means the view is
11600     * completely transparent and 1 means the view is completely opaque.
11601     *
11602     * <p>By default this is 1.0f.
11603     * @return The opacity of the view.
11604     */
11605    @ViewDebug.ExportedProperty(category = "drawing")
11606    public float getAlpha() {
11607        return mTransformationInfo != null ? mTransformationInfo.mAlpha : 1;
11608    }
11609
11610    /**
11611     * Returns whether this View has content which overlaps.
11612     *
11613     * <p>This function, intended to be overridden by specific View types, is an optimization when
11614     * alpha is set on a view. If rendering overlaps in a view with alpha < 1, that view is drawn to
11615     * an offscreen buffer and then composited into place, which can be expensive. If the view has
11616     * no overlapping rendering, the view can draw each primitive with the appropriate alpha value
11617     * directly. An example of overlapping rendering is a TextView with a background image, such as
11618     * a Button. An example of non-overlapping rendering is a TextView with no background, or an
11619     * ImageView with only the foreground image. The default implementation returns true; subclasses
11620     * should override if they have cases which can be optimized.</p>
11621     *
11622     * <p>The current implementation of the saveLayer and saveLayerAlpha methods in {@link Canvas}
11623     * necessitates that a View return true if it uses the methods internally without passing the
11624     * {@link Canvas#CLIP_TO_LAYER_SAVE_FLAG}.</p>
11625     *
11626     * @return true if the content in this view might overlap, false otherwise.
11627     */
11628    @ViewDebug.ExportedProperty(category = "drawing")
11629    public boolean hasOverlappingRendering() {
11630        return true;
11631    }
11632
11633    /**
11634     * Sets the opacity of the view to a value from 0 to 1, where 0 means the view is
11635     * completely transparent and 1 means the view is completely opaque.
11636     *
11637     * <p class="note"><strong>Note:</strong> setting alpha to a translucent value (0 < alpha < 1)
11638     * can have significant performance implications, especially for large views. It is best to use
11639     * the alpha property sparingly and transiently, as in the case of fading animations.</p>
11640     *
11641     * <p>For a view with a frequently changing alpha, such as during a fading animation, it is
11642     * strongly recommended for performance reasons to either override
11643     * {@link #hasOverlappingRendering()} to return <code>false</code> if appropriate, or setting a
11644     * {@link #setLayerType(int, android.graphics.Paint) layer type} on the view for the duration
11645     * of the animation. On versions {@link android.os.Build.VERSION_CODES#M} and below,
11646     * the default path for rendering an unlayered View with alpha could add multiple milliseconds
11647     * of rendering cost, even for simple or small views. Starting with
11648     * {@link android.os.Build.VERSION_CODES#M}, {@link #LAYER_TYPE_HARDWARE} is automatically
11649     * applied to the view at the rendering level.</p>
11650     *
11651     * <p>If this view overrides {@link #onSetAlpha(int)} to return true, then this view is
11652     * responsible for applying the opacity itself.</p>
11653     *
11654     * <p>On versions {@link android.os.Build.VERSION_CODES#LOLLIPOP_MR1} and below, note that if
11655     * the view is backed by a {@link #setLayerType(int, android.graphics.Paint) layer} and is
11656     * associated with a {@link #setLayerPaint(android.graphics.Paint) layer paint}, setting an
11657     * alpha value less than 1.0 will supersede the alpha of the layer paint.</p>
11658     *
11659     * <p>Starting with {@link android.os.Build.VERSION_CODES#M}, setting a translucent alpha
11660     * value will clip a View to its bounds, unless the View returns <code>false</code> from
11661     * {@link #hasOverlappingRendering}.</p>
11662     *
11663     * @param alpha The opacity of the view.
11664     *
11665     * @see #hasOverlappingRendering()
11666     * @see #setLayerType(int, android.graphics.Paint)
11667     *
11668     * @attr ref android.R.styleable#View_alpha
11669     */
11670    public void setAlpha(@FloatRange(from=0.0, to=1.0) float alpha) {
11671        ensureTransformationInfo();
11672        if (mTransformationInfo.mAlpha != alpha) {
11673            mTransformationInfo.mAlpha = alpha;
11674            if (onSetAlpha((int) (alpha * 255))) {
11675                mPrivateFlags |= PFLAG_ALPHA_SET;
11676                // subclass is handling alpha - don't optimize rendering cache invalidation
11677                invalidateParentCaches();
11678                invalidate(true);
11679            } else {
11680                mPrivateFlags &= ~PFLAG_ALPHA_SET;
11681                invalidateViewProperty(true, false);
11682                mRenderNode.setAlpha(getFinalAlpha());
11683                notifyViewAccessibilityStateChangedIfNeeded(
11684                        AccessibilityEvent.CONTENT_CHANGE_TYPE_UNDEFINED);
11685            }
11686        }
11687    }
11688
11689    /**
11690     * Faster version of setAlpha() which performs the same steps except there are
11691     * no calls to invalidate(). The caller of this function should perform proper invalidation
11692     * on the parent and this object. The return value indicates whether the subclass handles
11693     * alpha (the return value for onSetAlpha()).
11694     *
11695     * @param alpha The new value for the alpha property
11696     * @return true if the View subclass handles alpha (the return value for onSetAlpha()) and
11697     *         the new value for the alpha property is different from the old value
11698     */
11699    boolean setAlphaNoInvalidation(float alpha) {
11700        ensureTransformationInfo();
11701        if (mTransformationInfo.mAlpha != alpha) {
11702            mTransformationInfo.mAlpha = alpha;
11703            boolean subclassHandlesAlpha = onSetAlpha((int) (alpha * 255));
11704            if (subclassHandlesAlpha) {
11705                mPrivateFlags |= PFLAG_ALPHA_SET;
11706                return true;
11707            } else {
11708                mPrivateFlags &= ~PFLAG_ALPHA_SET;
11709                mRenderNode.setAlpha(getFinalAlpha());
11710            }
11711        }
11712        return false;
11713    }
11714
11715    /**
11716     * This property is hidden and intended only for use by the Fade transition, which
11717     * animates it to produce a visual translucency that does not side-effect (or get
11718     * affected by) the real alpha property. This value is composited with the other
11719     * alpha value (and the AlphaAnimation value, when that is present) to produce
11720     * a final visual translucency result, which is what is passed into the DisplayList.
11721     *
11722     * @hide
11723     */
11724    public void setTransitionAlpha(float alpha) {
11725        ensureTransformationInfo();
11726        if (mTransformationInfo.mTransitionAlpha != alpha) {
11727            mTransformationInfo.mTransitionAlpha = alpha;
11728            mPrivateFlags &= ~PFLAG_ALPHA_SET;
11729            invalidateViewProperty(true, false);
11730            mRenderNode.setAlpha(getFinalAlpha());
11731        }
11732    }
11733
11734    /**
11735     * Calculates the visual alpha of this view, which is a combination of the actual
11736     * alpha value and the transitionAlpha value (if set).
11737     */
11738    private float getFinalAlpha() {
11739        if (mTransformationInfo != null) {
11740            return mTransformationInfo.mAlpha * mTransformationInfo.mTransitionAlpha;
11741        }
11742        return 1;
11743    }
11744
11745    /**
11746     * This property is hidden and intended only for use by the Fade transition, which
11747     * animates it to produce a visual translucency that does not side-effect (or get
11748     * affected by) the real alpha property. This value is composited with the other
11749     * alpha value (and the AlphaAnimation value, when that is present) to produce
11750     * a final visual translucency result, which is what is passed into the DisplayList.
11751     *
11752     * @hide
11753     */
11754    @ViewDebug.ExportedProperty(category = "drawing")
11755    public float getTransitionAlpha() {
11756        return mTransformationInfo != null ? mTransformationInfo.mTransitionAlpha : 1;
11757    }
11758
11759    /**
11760     * Top position of this view relative to its parent.
11761     *
11762     * @return The top of this view, in pixels.
11763     */
11764    @ViewDebug.CapturedViewProperty
11765    public final int getTop() {
11766        return mTop;
11767    }
11768
11769    /**
11770     * Sets the top position of this view relative to its parent. This method is meant to be called
11771     * by the layout system and should not generally be called otherwise, because the property
11772     * may be changed at any time by the layout.
11773     *
11774     * @param top The top of this view, in pixels.
11775     */
11776    public final void setTop(int top) {
11777        if (top != mTop) {
11778            final boolean matrixIsIdentity = hasIdentityMatrix();
11779            if (matrixIsIdentity) {
11780                if (mAttachInfo != null) {
11781                    int minTop;
11782                    int yLoc;
11783                    if (top < mTop) {
11784                        minTop = top;
11785                        yLoc = top - mTop;
11786                    } else {
11787                        minTop = mTop;
11788                        yLoc = 0;
11789                    }
11790                    invalidate(0, yLoc, mRight - mLeft, mBottom - minTop);
11791                }
11792            } else {
11793                // Double-invalidation is necessary to capture view's old and new areas
11794                invalidate(true);
11795            }
11796
11797            int width = mRight - mLeft;
11798            int oldHeight = mBottom - mTop;
11799
11800            mTop = top;
11801            mRenderNode.setTop(mTop);
11802
11803            sizeChange(width, mBottom - mTop, width, oldHeight);
11804
11805            if (!matrixIsIdentity) {
11806                mPrivateFlags |= PFLAG_DRAWN; // force another invalidation with the new orientation
11807                invalidate(true);
11808            }
11809            mBackgroundSizeChanged = true;
11810            if (mForegroundInfo != null) {
11811                mForegroundInfo.mBoundsChanged = true;
11812            }
11813            invalidateParentIfNeeded();
11814            if ((mPrivateFlags2 & PFLAG2_VIEW_QUICK_REJECTED) == PFLAG2_VIEW_QUICK_REJECTED) {
11815                // View was rejected last time it was drawn by its parent; this may have changed
11816                invalidateParentIfNeeded();
11817            }
11818        }
11819    }
11820
11821    /**
11822     * Bottom position of this view relative to its parent.
11823     *
11824     * @return The bottom of this view, in pixels.
11825     */
11826    @ViewDebug.CapturedViewProperty
11827    public final int getBottom() {
11828        return mBottom;
11829    }
11830
11831    /**
11832     * True if this view has changed since the last time being drawn.
11833     *
11834     * @return The dirty state of this view.
11835     */
11836    public boolean isDirty() {
11837        return (mPrivateFlags & PFLAG_DIRTY_MASK) != 0;
11838    }
11839
11840    /**
11841     * Sets the bottom position of this view relative to its parent. This method is meant to be
11842     * called by the layout system and should not generally be called otherwise, because the
11843     * property may be changed at any time by the layout.
11844     *
11845     * @param bottom The bottom of this view, in pixels.
11846     */
11847    public final void setBottom(int bottom) {
11848        if (bottom != mBottom) {
11849            final boolean matrixIsIdentity = hasIdentityMatrix();
11850            if (matrixIsIdentity) {
11851                if (mAttachInfo != null) {
11852                    int maxBottom;
11853                    if (bottom < mBottom) {
11854                        maxBottom = mBottom;
11855                    } else {
11856                        maxBottom = bottom;
11857                    }
11858                    invalidate(0, 0, mRight - mLeft, maxBottom - mTop);
11859                }
11860            } else {
11861                // Double-invalidation is necessary to capture view's old and new areas
11862                invalidate(true);
11863            }
11864
11865            int width = mRight - mLeft;
11866            int oldHeight = mBottom - mTop;
11867
11868            mBottom = bottom;
11869            mRenderNode.setBottom(mBottom);
11870
11871            sizeChange(width, mBottom - mTop, width, oldHeight);
11872
11873            if (!matrixIsIdentity) {
11874                mPrivateFlags |= PFLAG_DRAWN; // force another invalidation with the new orientation
11875                invalidate(true);
11876            }
11877            mBackgroundSizeChanged = true;
11878            if (mForegroundInfo != null) {
11879                mForegroundInfo.mBoundsChanged = true;
11880            }
11881            invalidateParentIfNeeded();
11882            if ((mPrivateFlags2 & PFLAG2_VIEW_QUICK_REJECTED) == PFLAG2_VIEW_QUICK_REJECTED) {
11883                // View was rejected last time it was drawn by its parent; this may have changed
11884                invalidateParentIfNeeded();
11885            }
11886        }
11887    }
11888
11889    /**
11890     * Left position of this view relative to its parent.
11891     *
11892     * @return The left edge of this view, in pixels.
11893     */
11894    @ViewDebug.CapturedViewProperty
11895    public final int getLeft() {
11896        return mLeft;
11897    }
11898
11899    /**
11900     * Sets the left position of this view relative to its parent. This method is meant to be called
11901     * by the layout system and should not generally be called otherwise, because the property
11902     * may be changed at any time by the layout.
11903     *
11904     * @param left The left of this view, in pixels.
11905     */
11906    public final void setLeft(int left) {
11907        if (left != mLeft) {
11908            final boolean matrixIsIdentity = hasIdentityMatrix();
11909            if (matrixIsIdentity) {
11910                if (mAttachInfo != null) {
11911                    int minLeft;
11912                    int xLoc;
11913                    if (left < mLeft) {
11914                        minLeft = left;
11915                        xLoc = left - mLeft;
11916                    } else {
11917                        minLeft = mLeft;
11918                        xLoc = 0;
11919                    }
11920                    invalidate(xLoc, 0, mRight - minLeft, mBottom - mTop);
11921                }
11922            } else {
11923                // Double-invalidation is necessary to capture view's old and new areas
11924                invalidate(true);
11925            }
11926
11927            int oldWidth = mRight - mLeft;
11928            int height = mBottom - mTop;
11929
11930            mLeft = left;
11931            mRenderNode.setLeft(left);
11932
11933            sizeChange(mRight - mLeft, height, oldWidth, height);
11934
11935            if (!matrixIsIdentity) {
11936                mPrivateFlags |= PFLAG_DRAWN; // force another invalidation with the new orientation
11937                invalidate(true);
11938            }
11939            mBackgroundSizeChanged = true;
11940            if (mForegroundInfo != null) {
11941                mForegroundInfo.mBoundsChanged = true;
11942            }
11943            invalidateParentIfNeeded();
11944            if ((mPrivateFlags2 & PFLAG2_VIEW_QUICK_REJECTED) == PFLAG2_VIEW_QUICK_REJECTED) {
11945                // View was rejected last time it was drawn by its parent; this may have changed
11946                invalidateParentIfNeeded();
11947            }
11948        }
11949    }
11950
11951    /**
11952     * Right position of this view relative to its parent.
11953     *
11954     * @return The right edge of this view, in pixels.
11955     */
11956    @ViewDebug.CapturedViewProperty
11957    public final int getRight() {
11958        return mRight;
11959    }
11960
11961    /**
11962     * Sets the right position of this view relative to its parent. This method is meant to be called
11963     * by the layout system and should not generally be called otherwise, because the property
11964     * may be changed at any time by the layout.
11965     *
11966     * @param right The right of this view, in pixels.
11967     */
11968    public final void setRight(int right) {
11969        if (right != mRight) {
11970            final boolean matrixIsIdentity = hasIdentityMatrix();
11971            if (matrixIsIdentity) {
11972                if (mAttachInfo != null) {
11973                    int maxRight;
11974                    if (right < mRight) {
11975                        maxRight = mRight;
11976                    } else {
11977                        maxRight = right;
11978                    }
11979                    invalidate(0, 0, maxRight - mLeft, mBottom - mTop);
11980                }
11981            } else {
11982                // Double-invalidation is necessary to capture view's old and new areas
11983                invalidate(true);
11984            }
11985
11986            int oldWidth = mRight - mLeft;
11987            int height = mBottom - mTop;
11988
11989            mRight = right;
11990            mRenderNode.setRight(mRight);
11991
11992            sizeChange(mRight - mLeft, height, oldWidth, height);
11993
11994            if (!matrixIsIdentity) {
11995                mPrivateFlags |= PFLAG_DRAWN; // force another invalidation with the new orientation
11996                invalidate(true);
11997            }
11998            mBackgroundSizeChanged = true;
11999            if (mForegroundInfo != null) {
12000                mForegroundInfo.mBoundsChanged = true;
12001            }
12002            invalidateParentIfNeeded();
12003            if ((mPrivateFlags2 & PFLAG2_VIEW_QUICK_REJECTED) == PFLAG2_VIEW_QUICK_REJECTED) {
12004                // View was rejected last time it was drawn by its parent; this may have changed
12005                invalidateParentIfNeeded();
12006            }
12007        }
12008    }
12009
12010    /**
12011     * The visual x position of this view, in pixels. This is equivalent to the
12012     * {@link #setTranslationX(float) translationX} property plus the current
12013     * {@link #getLeft() left} property.
12014     *
12015     * @return The visual x position of this view, in pixels.
12016     */
12017    @ViewDebug.ExportedProperty(category = "drawing")
12018    public float getX() {
12019        return mLeft + getTranslationX();
12020    }
12021
12022    /**
12023     * Sets the visual x position of this view, in pixels. This is equivalent to setting the
12024     * {@link #setTranslationX(float) translationX} property to be the difference between
12025     * the x value passed in and the current {@link #getLeft() left} property.
12026     *
12027     * @param x The visual x position of this view, in pixels.
12028     */
12029    public void setX(float x) {
12030        setTranslationX(x - mLeft);
12031    }
12032
12033    /**
12034     * The visual y position of this view, in pixels. This is equivalent to the
12035     * {@link #setTranslationY(float) translationY} property plus the current
12036     * {@link #getTop() top} property.
12037     *
12038     * @return The visual y position of this view, in pixels.
12039     */
12040    @ViewDebug.ExportedProperty(category = "drawing")
12041    public float getY() {
12042        return mTop + getTranslationY();
12043    }
12044
12045    /**
12046     * Sets the visual y position of this view, in pixels. This is equivalent to setting the
12047     * {@link #setTranslationY(float) translationY} property to be the difference between
12048     * the y value passed in and the current {@link #getTop() top} property.
12049     *
12050     * @param y The visual y position of this view, in pixels.
12051     */
12052    public void setY(float y) {
12053        setTranslationY(y - mTop);
12054    }
12055
12056    /**
12057     * The visual z position of this view, in pixels. This is equivalent to the
12058     * {@link #setTranslationZ(float) translationZ} property plus the current
12059     * {@link #getElevation() elevation} property.
12060     *
12061     * @return The visual z position of this view, in pixels.
12062     */
12063    @ViewDebug.ExportedProperty(category = "drawing")
12064    public float getZ() {
12065        return getElevation() + getTranslationZ();
12066    }
12067
12068    /**
12069     * Sets the visual z position of this view, in pixels. This is equivalent to setting the
12070     * {@link #setTranslationZ(float) translationZ} property to be the difference between
12071     * the x value passed in and the current {@link #getElevation() elevation} property.
12072     *
12073     * @param z The visual z position of this view, in pixels.
12074     */
12075    public void setZ(float z) {
12076        setTranslationZ(z - getElevation());
12077    }
12078
12079    /**
12080     * The base elevation of this view relative to its parent, in pixels.
12081     *
12082     * @return The base depth position of the view, in pixels.
12083     */
12084    @ViewDebug.ExportedProperty(category = "drawing")
12085    public float getElevation() {
12086        return mRenderNode.getElevation();
12087    }
12088
12089    /**
12090     * Sets the base elevation of this view, in pixels.
12091     *
12092     * @attr ref android.R.styleable#View_elevation
12093     */
12094    public void setElevation(float elevation) {
12095        if (elevation != getElevation()) {
12096            invalidateViewProperty(true, false);
12097            mRenderNode.setElevation(elevation);
12098            invalidateViewProperty(false, true);
12099
12100            invalidateParentIfNeededAndWasQuickRejected();
12101        }
12102    }
12103
12104    /**
12105     * The horizontal location of this view relative to its {@link #getLeft() left} position.
12106     * This position is post-layout, in addition to wherever the object's
12107     * layout placed it.
12108     *
12109     * @return The horizontal position of this view relative to its left position, in pixels.
12110     */
12111    @ViewDebug.ExportedProperty(category = "drawing")
12112    public float getTranslationX() {
12113        return mRenderNode.getTranslationX();
12114    }
12115
12116    /**
12117     * Sets the horizontal location of this view relative to its {@link #getLeft() left} position.
12118     * This effectively positions the object post-layout, in addition to wherever the object's
12119     * layout placed it.
12120     *
12121     * @param translationX The horizontal position of this view relative to its left position,
12122     * in pixels.
12123     *
12124     * @attr ref android.R.styleable#View_translationX
12125     */
12126    public void setTranslationX(float translationX) {
12127        if (translationX != getTranslationX()) {
12128            invalidateViewProperty(true, false);
12129            mRenderNode.setTranslationX(translationX);
12130            invalidateViewProperty(false, true);
12131
12132            invalidateParentIfNeededAndWasQuickRejected();
12133            notifySubtreeAccessibilityStateChangedIfNeeded();
12134        }
12135    }
12136
12137    /**
12138     * The vertical location of this view relative to its {@link #getTop() top} position.
12139     * This position is post-layout, in addition to wherever the object's
12140     * layout placed it.
12141     *
12142     * @return The vertical position of this view relative to its top position,
12143     * in pixels.
12144     */
12145    @ViewDebug.ExportedProperty(category = "drawing")
12146    public float getTranslationY() {
12147        return mRenderNode.getTranslationY();
12148    }
12149
12150    /**
12151     * Sets the vertical location of this view relative to its {@link #getTop() top} position.
12152     * This effectively positions the object post-layout, in addition to wherever the object's
12153     * layout placed it.
12154     *
12155     * @param translationY The vertical position of this view relative to its top position,
12156     * in pixels.
12157     *
12158     * @attr ref android.R.styleable#View_translationY
12159     */
12160    public void setTranslationY(float translationY) {
12161        if (translationY != getTranslationY()) {
12162            invalidateViewProperty(true, false);
12163            mRenderNode.setTranslationY(translationY);
12164            invalidateViewProperty(false, true);
12165
12166            invalidateParentIfNeededAndWasQuickRejected();
12167            notifySubtreeAccessibilityStateChangedIfNeeded();
12168        }
12169    }
12170
12171    /**
12172     * The depth location of this view relative to its {@link #getElevation() elevation}.
12173     *
12174     * @return The depth of this view relative to its elevation.
12175     */
12176    @ViewDebug.ExportedProperty(category = "drawing")
12177    public float getTranslationZ() {
12178        return mRenderNode.getTranslationZ();
12179    }
12180
12181    /**
12182     * Sets the depth location of this view relative to its {@link #getElevation() elevation}.
12183     *
12184     * @attr ref android.R.styleable#View_translationZ
12185     */
12186    public void setTranslationZ(float translationZ) {
12187        if (translationZ != getTranslationZ()) {
12188            invalidateViewProperty(true, false);
12189            mRenderNode.setTranslationZ(translationZ);
12190            invalidateViewProperty(false, true);
12191
12192            invalidateParentIfNeededAndWasQuickRejected();
12193        }
12194    }
12195
12196    /** @hide */
12197    public void setAnimationMatrix(Matrix matrix) {
12198        invalidateViewProperty(true, false);
12199        mRenderNode.setAnimationMatrix(matrix);
12200        invalidateViewProperty(false, true);
12201
12202        invalidateParentIfNeededAndWasQuickRejected();
12203    }
12204
12205    /**
12206     * Returns the current StateListAnimator if exists.
12207     *
12208     * @return StateListAnimator or null if it does not exists
12209     * @see    #setStateListAnimator(android.animation.StateListAnimator)
12210     */
12211    public StateListAnimator getStateListAnimator() {
12212        return mStateListAnimator;
12213    }
12214
12215    /**
12216     * Attaches the provided StateListAnimator to this View.
12217     * <p>
12218     * Any previously attached StateListAnimator will be detached.
12219     *
12220     * @param stateListAnimator The StateListAnimator to update the view
12221     * @see {@link android.animation.StateListAnimator}
12222     */
12223    public void setStateListAnimator(StateListAnimator stateListAnimator) {
12224        if (mStateListAnimator == stateListAnimator) {
12225            return;
12226        }
12227        if (mStateListAnimator != null) {
12228            mStateListAnimator.setTarget(null);
12229        }
12230        mStateListAnimator = stateListAnimator;
12231        if (stateListAnimator != null) {
12232            stateListAnimator.setTarget(this);
12233            if (isAttachedToWindow()) {
12234                stateListAnimator.setState(getDrawableState());
12235            }
12236        }
12237    }
12238
12239    /**
12240     * Returns whether the Outline should be used to clip the contents of the View.
12241     * <p>
12242     * Note that this flag will only be respected if the View's Outline returns true from
12243     * {@link Outline#canClip()}.
12244     *
12245     * @see #setOutlineProvider(ViewOutlineProvider)
12246     * @see #setClipToOutline(boolean)
12247     */
12248    public final boolean getClipToOutline() {
12249        return mRenderNode.getClipToOutline();
12250    }
12251
12252    /**
12253     * Sets whether the View's Outline should be used to clip the contents of the View.
12254     * <p>
12255     * Only a single non-rectangular clip can be applied on a View at any time.
12256     * Circular clips from a {@link ViewAnimationUtils#createCircularReveal(View, int, int, float, float)
12257     * circular reveal} animation take priority over Outline clipping, and
12258     * child Outline clipping takes priority over Outline clipping done by a
12259     * parent.
12260     * <p>
12261     * Note that this flag will only be respected if the View's Outline returns true from
12262     * {@link Outline#canClip()}.
12263     *
12264     * @see #setOutlineProvider(ViewOutlineProvider)
12265     * @see #getClipToOutline()
12266     */
12267    public void setClipToOutline(boolean clipToOutline) {
12268        damageInParent();
12269        if (getClipToOutline() != clipToOutline) {
12270            mRenderNode.setClipToOutline(clipToOutline);
12271        }
12272    }
12273
12274    // correspond to the enum values of View_outlineProvider
12275    private static final int PROVIDER_BACKGROUND = 0;
12276    private static final int PROVIDER_NONE = 1;
12277    private static final int PROVIDER_BOUNDS = 2;
12278    private static final int PROVIDER_PADDED_BOUNDS = 3;
12279    private void setOutlineProviderFromAttribute(int providerInt) {
12280        switch (providerInt) {
12281            case PROVIDER_BACKGROUND:
12282                setOutlineProvider(ViewOutlineProvider.BACKGROUND);
12283                break;
12284            case PROVIDER_NONE:
12285                setOutlineProvider(null);
12286                break;
12287            case PROVIDER_BOUNDS:
12288                setOutlineProvider(ViewOutlineProvider.BOUNDS);
12289                break;
12290            case PROVIDER_PADDED_BOUNDS:
12291                setOutlineProvider(ViewOutlineProvider.PADDED_BOUNDS);
12292                break;
12293        }
12294    }
12295
12296    /**
12297     * Sets the {@link ViewOutlineProvider} of the view, which generates the Outline that defines
12298     * the shape of the shadow it casts, and enables outline clipping.
12299     * <p>
12300     * The default ViewOutlineProvider, {@link ViewOutlineProvider#BACKGROUND}, queries the Outline
12301     * from the View's background drawable, via {@link Drawable#getOutline(Outline)}. Changing the
12302     * outline provider with this method allows this behavior to be overridden.
12303     * <p>
12304     * If the ViewOutlineProvider is null, if querying it for an outline returns false,
12305     * or if the produced Outline is {@link Outline#isEmpty()}, shadows will not be cast.
12306     * <p>
12307     * Only outlines that return true from {@link Outline#canClip()} may be used for clipping.
12308     *
12309     * @see #setClipToOutline(boolean)
12310     * @see #getClipToOutline()
12311     * @see #getOutlineProvider()
12312     */
12313    public void setOutlineProvider(ViewOutlineProvider provider) {
12314        mOutlineProvider = provider;
12315        invalidateOutline();
12316    }
12317
12318    /**
12319     * Returns the current {@link ViewOutlineProvider} of the view, which generates the Outline
12320     * that defines the shape of the shadow it casts, and enables outline clipping.
12321     *
12322     * @see #setOutlineProvider(ViewOutlineProvider)
12323     */
12324    public ViewOutlineProvider getOutlineProvider() {
12325        return mOutlineProvider;
12326    }
12327
12328    /**
12329     * Called to rebuild this View's Outline from its {@link ViewOutlineProvider outline provider}
12330     *
12331     * @see #setOutlineProvider(ViewOutlineProvider)
12332     */
12333    public void invalidateOutline() {
12334        rebuildOutline();
12335
12336        notifySubtreeAccessibilityStateChangedIfNeeded();
12337        invalidateViewProperty(false, false);
12338    }
12339
12340    /**
12341     * Internal version of {@link #invalidateOutline()} which invalidates the
12342     * outline without invalidating the view itself. This is intended to be called from
12343     * within methods in the View class itself which are the result of the view being
12344     * invalidated already. For example, when we are drawing the background of a View,
12345     * we invalidate the outline in case it changed in the meantime, but we do not
12346     * need to invalidate the view because we're already drawing the background as part
12347     * of drawing the view in response to an earlier invalidation of the view.
12348     */
12349    private void rebuildOutline() {
12350        // Unattached views ignore this signal, and outline is recomputed in onAttachedToWindow()
12351        if (mAttachInfo == null) return;
12352
12353        if (mOutlineProvider == null) {
12354            // no provider, remove outline
12355            mRenderNode.setOutline(null);
12356        } else {
12357            final Outline outline = mAttachInfo.mTmpOutline;
12358            outline.setEmpty();
12359            outline.setAlpha(1.0f);
12360
12361            mOutlineProvider.getOutline(this, outline);
12362            mRenderNode.setOutline(outline);
12363        }
12364    }
12365
12366    /**
12367     * HierarchyViewer only
12368     *
12369     * @hide
12370     */
12371    @ViewDebug.ExportedProperty(category = "drawing")
12372    public boolean hasShadow() {
12373        return mRenderNode.hasShadow();
12374    }
12375
12376
12377    /** @hide */
12378    public void setRevealClip(boolean shouldClip, float x, float y, float radius) {
12379        mRenderNode.setRevealClip(shouldClip, x, y, radius);
12380        invalidateViewProperty(false, false);
12381    }
12382
12383    /**
12384     * Hit rectangle in parent's coordinates
12385     *
12386     * @param outRect The hit rectangle of the view.
12387     */
12388    public void getHitRect(Rect outRect) {
12389        if (hasIdentityMatrix() || mAttachInfo == null) {
12390            outRect.set(mLeft, mTop, mRight, mBottom);
12391        } else {
12392            final RectF tmpRect = mAttachInfo.mTmpTransformRect;
12393            tmpRect.set(0, 0, getWidth(), getHeight());
12394            getMatrix().mapRect(tmpRect); // TODO: mRenderNode.mapRect(tmpRect)
12395            outRect.set((int) tmpRect.left + mLeft, (int) tmpRect.top + mTop,
12396                    (int) tmpRect.right + mLeft, (int) tmpRect.bottom + mTop);
12397        }
12398    }
12399
12400    /**
12401     * Determines whether the given point, in local coordinates is inside the view.
12402     */
12403    /*package*/ final boolean pointInView(float localX, float localY) {
12404        return localX >= 0 && localX < (mRight - mLeft)
12405                && localY >= 0 && localY < (mBottom - mTop);
12406    }
12407
12408    /**
12409     * Utility method to determine whether the given point, in local coordinates,
12410     * is inside the view, where the area of the view is expanded by the slop factor.
12411     * This method is called while processing touch-move events to determine if the event
12412     * is still within the view.
12413     *
12414     * @hide
12415     */
12416    public boolean pointInView(float localX, float localY, float slop) {
12417        return localX >= -slop && localY >= -slop && localX < ((mRight - mLeft) + slop) &&
12418                localY < ((mBottom - mTop) + slop);
12419    }
12420
12421    /**
12422     * When a view has focus and the user navigates away from it, the next view is searched for
12423     * starting from the rectangle filled in by this method.
12424     *
12425     * By default, the rectangle is the {@link #getDrawingRect(android.graphics.Rect)})
12426     * of the view.  However, if your view maintains some idea of internal selection,
12427     * such as a cursor, or a selected row or column, you should override this method and
12428     * fill in a more specific rectangle.
12429     *
12430     * @param r The rectangle to fill in, in this view's coordinates.
12431     */
12432    public void getFocusedRect(Rect r) {
12433        getDrawingRect(r);
12434    }
12435
12436    /**
12437     * If some part of this view is not clipped by any of its parents, then
12438     * return that area in r in global (root) coordinates. To convert r to local
12439     * coordinates (without taking possible View rotations into account), offset
12440     * it by -globalOffset (e.g. r.offset(-globalOffset.x, -globalOffset.y)).
12441     * If the view is completely clipped or translated out, return false.
12442     *
12443     * @param r If true is returned, r holds the global coordinates of the
12444     *        visible portion of this view.
12445     * @param globalOffset If true is returned, globalOffset holds the dx,dy
12446     *        between this view and its root. globalOffet may be null.
12447     * @return true if r is non-empty (i.e. part of the view is visible at the
12448     *         root level.
12449     */
12450    public boolean getGlobalVisibleRect(Rect r, Point globalOffset) {
12451        int width = mRight - mLeft;
12452        int height = mBottom - mTop;
12453        if (width > 0 && height > 0) {
12454            r.set(0, 0, width, height);
12455            if (globalOffset != null) {
12456                globalOffset.set(-mScrollX, -mScrollY);
12457            }
12458            return mParent == null || mParent.getChildVisibleRect(this, r, globalOffset);
12459        }
12460        return false;
12461    }
12462
12463    public final boolean getGlobalVisibleRect(Rect r) {
12464        return getGlobalVisibleRect(r, null);
12465    }
12466
12467    public final boolean getLocalVisibleRect(Rect r) {
12468        final Point offset = mAttachInfo != null ? mAttachInfo.mPoint : new Point();
12469        if (getGlobalVisibleRect(r, offset)) {
12470            r.offset(-offset.x, -offset.y); // make r local
12471            return true;
12472        }
12473        return false;
12474    }
12475
12476    /**
12477     * Offset this view's vertical location by the specified number of pixels.
12478     *
12479     * @param offset the number of pixels to offset the view by
12480     */
12481    public void offsetTopAndBottom(int offset) {
12482        if (offset != 0) {
12483            final boolean matrixIsIdentity = hasIdentityMatrix();
12484            if (matrixIsIdentity) {
12485                if (isHardwareAccelerated()) {
12486                    invalidateViewProperty(false, false);
12487                } else {
12488                    final ViewParent p = mParent;
12489                    if (p != null && mAttachInfo != null) {
12490                        final Rect r = mAttachInfo.mTmpInvalRect;
12491                        int minTop;
12492                        int maxBottom;
12493                        int yLoc;
12494                        if (offset < 0) {
12495                            minTop = mTop + offset;
12496                            maxBottom = mBottom;
12497                            yLoc = offset;
12498                        } else {
12499                            minTop = mTop;
12500                            maxBottom = mBottom + offset;
12501                            yLoc = 0;
12502                        }
12503                        r.set(0, yLoc, mRight - mLeft, maxBottom - minTop);
12504                        p.invalidateChild(this, r);
12505                    }
12506                }
12507            } else {
12508                invalidateViewProperty(false, false);
12509            }
12510
12511            mTop += offset;
12512            mBottom += offset;
12513            mRenderNode.offsetTopAndBottom(offset);
12514            if (isHardwareAccelerated()) {
12515                invalidateViewProperty(false, false);
12516                invalidateParentIfNeededAndWasQuickRejected();
12517            } else {
12518                if (!matrixIsIdentity) {
12519                    invalidateViewProperty(false, true);
12520                }
12521                invalidateParentIfNeeded();
12522            }
12523            notifySubtreeAccessibilityStateChangedIfNeeded();
12524        }
12525    }
12526
12527    /**
12528     * Offset this view's horizontal location by the specified amount of pixels.
12529     *
12530     * @param offset the number of pixels to offset the view by
12531     */
12532    public void offsetLeftAndRight(int offset) {
12533        if (offset != 0) {
12534            final boolean matrixIsIdentity = hasIdentityMatrix();
12535            if (matrixIsIdentity) {
12536                if (isHardwareAccelerated()) {
12537                    invalidateViewProperty(false, false);
12538                } else {
12539                    final ViewParent p = mParent;
12540                    if (p != null && mAttachInfo != null) {
12541                        final Rect r = mAttachInfo.mTmpInvalRect;
12542                        int minLeft;
12543                        int maxRight;
12544                        if (offset < 0) {
12545                            minLeft = mLeft + offset;
12546                            maxRight = mRight;
12547                        } else {
12548                            minLeft = mLeft;
12549                            maxRight = mRight + offset;
12550                        }
12551                        r.set(0, 0, maxRight - minLeft, mBottom - mTop);
12552                        p.invalidateChild(this, r);
12553                    }
12554                }
12555            } else {
12556                invalidateViewProperty(false, false);
12557            }
12558
12559            mLeft += offset;
12560            mRight += offset;
12561            mRenderNode.offsetLeftAndRight(offset);
12562            if (isHardwareAccelerated()) {
12563                invalidateViewProperty(false, false);
12564                invalidateParentIfNeededAndWasQuickRejected();
12565            } else {
12566                if (!matrixIsIdentity) {
12567                    invalidateViewProperty(false, true);
12568                }
12569                invalidateParentIfNeeded();
12570            }
12571            notifySubtreeAccessibilityStateChangedIfNeeded();
12572        }
12573    }
12574
12575    /**
12576     * Get the LayoutParams associated with this view. All views should have
12577     * layout parameters. These supply parameters to the <i>parent</i> of this
12578     * view specifying how it should be arranged. There are many subclasses of
12579     * ViewGroup.LayoutParams, and these correspond to the different subclasses
12580     * of ViewGroup that are responsible for arranging their children.
12581     *
12582     * This method may return null if this View is not attached to a parent
12583     * ViewGroup or {@link #setLayoutParams(android.view.ViewGroup.LayoutParams)}
12584     * was not invoked successfully. When a View is attached to a parent
12585     * ViewGroup, this method must not return null.
12586     *
12587     * @return The LayoutParams associated with this view, or null if no
12588     *         parameters have been set yet
12589     */
12590    @ViewDebug.ExportedProperty(deepExport = true, prefix = "layout_")
12591    public ViewGroup.LayoutParams getLayoutParams() {
12592        return mLayoutParams;
12593    }
12594
12595    /**
12596     * Set the layout parameters associated with this view. These supply
12597     * parameters to the <i>parent</i> of this view specifying how it should be
12598     * arranged. There are many subclasses of ViewGroup.LayoutParams, and these
12599     * correspond to the different subclasses of ViewGroup that are responsible
12600     * for arranging their children.
12601     *
12602     * @param params The layout parameters for this view, cannot be null
12603     */
12604    public void setLayoutParams(ViewGroup.LayoutParams params) {
12605        if (params == null) {
12606            throw new NullPointerException("Layout parameters cannot be null");
12607        }
12608        mLayoutParams = params;
12609        resolveLayoutParams();
12610        if (mParent instanceof ViewGroup) {
12611            ((ViewGroup) mParent).onSetLayoutParams(this, params);
12612        }
12613        requestLayout();
12614    }
12615
12616    /**
12617     * Resolve the layout parameters depending on the resolved layout direction
12618     *
12619     * @hide
12620     */
12621    public void resolveLayoutParams() {
12622        if (mLayoutParams != null) {
12623            mLayoutParams.resolveLayoutDirection(getLayoutDirection());
12624        }
12625    }
12626
12627    /**
12628     * Set the scrolled position of your view. This will cause a call to
12629     * {@link #onScrollChanged(int, int, int, int)} and the view will be
12630     * invalidated.
12631     * @param x the x position to scroll to
12632     * @param y the y position to scroll to
12633     */
12634    public void scrollTo(int x, int y) {
12635        if (mScrollX != x || mScrollY != y) {
12636            int oldX = mScrollX;
12637            int oldY = mScrollY;
12638            mScrollX = x;
12639            mScrollY = y;
12640            invalidateParentCaches();
12641            onScrollChanged(mScrollX, mScrollY, oldX, oldY);
12642            if (!awakenScrollBars()) {
12643                postInvalidateOnAnimation();
12644            }
12645        }
12646    }
12647
12648    /**
12649     * Move the scrolled position of your view. This will cause a call to
12650     * {@link #onScrollChanged(int, int, int, int)} and the view will be
12651     * invalidated.
12652     * @param x the amount of pixels to scroll by horizontally
12653     * @param y the amount of pixels to scroll by vertically
12654     */
12655    public void scrollBy(int x, int y) {
12656        scrollTo(mScrollX + x, mScrollY + y);
12657    }
12658
12659    /**
12660     * <p>Trigger the scrollbars to draw. When invoked this method starts an
12661     * animation to fade the scrollbars out after a default delay. If a subclass
12662     * provides animated scrolling, the start delay should equal the duration
12663     * of the scrolling animation.</p>
12664     *
12665     * <p>The animation starts only if at least one of the scrollbars is
12666     * enabled, as specified by {@link #isHorizontalScrollBarEnabled()} and
12667     * {@link #isVerticalScrollBarEnabled()}. When the animation is started,
12668     * this method returns true, and false otherwise. If the animation is
12669     * started, this method calls {@link #invalidate()}; in that case the
12670     * caller should not call {@link #invalidate()}.</p>
12671     *
12672     * <p>This method should be invoked every time a subclass directly updates
12673     * the scroll parameters.</p>
12674     *
12675     * <p>This method is automatically invoked by {@link #scrollBy(int, int)}
12676     * and {@link #scrollTo(int, int)}.</p>
12677     *
12678     * @return true if the animation is played, false otherwise
12679     *
12680     * @see #awakenScrollBars(int)
12681     * @see #scrollBy(int, int)
12682     * @see #scrollTo(int, int)
12683     * @see #isHorizontalScrollBarEnabled()
12684     * @see #isVerticalScrollBarEnabled()
12685     * @see #setHorizontalScrollBarEnabled(boolean)
12686     * @see #setVerticalScrollBarEnabled(boolean)
12687     */
12688    protected boolean awakenScrollBars() {
12689        return mScrollCache != null &&
12690                awakenScrollBars(mScrollCache.scrollBarDefaultDelayBeforeFade, true);
12691    }
12692
12693    /**
12694     * Trigger the scrollbars to draw.
12695     * This method differs from awakenScrollBars() only in its default duration.
12696     * initialAwakenScrollBars() will show the scroll bars for longer than
12697     * usual to give the user more of a chance to notice them.
12698     *
12699     * @return true if the animation is played, false otherwise.
12700     */
12701    private boolean initialAwakenScrollBars() {
12702        return mScrollCache != null &&
12703                awakenScrollBars(mScrollCache.scrollBarDefaultDelayBeforeFade * 4, true);
12704    }
12705
12706    /**
12707     * <p>
12708     * Trigger the scrollbars to draw. When invoked this method starts an
12709     * animation to fade the scrollbars out after a fixed delay. If a subclass
12710     * provides animated scrolling, the start delay should equal the duration of
12711     * the scrolling animation.
12712     * </p>
12713     *
12714     * <p>
12715     * The animation starts only if at least one of the scrollbars is enabled,
12716     * as specified by {@link #isHorizontalScrollBarEnabled()} and
12717     * {@link #isVerticalScrollBarEnabled()}. When the animation is started,
12718     * this method returns true, and false otherwise. If the animation is
12719     * started, this method calls {@link #invalidate()}; in that case the caller
12720     * should not call {@link #invalidate()}.
12721     * </p>
12722     *
12723     * <p>
12724     * This method should be invoked every time a subclass directly updates the
12725     * scroll parameters.
12726     * </p>
12727     *
12728     * @param startDelay the delay, in milliseconds, after which the animation
12729     *        should start; when the delay is 0, the animation starts
12730     *        immediately
12731     * @return true if the animation is played, false otherwise
12732     *
12733     * @see #scrollBy(int, int)
12734     * @see #scrollTo(int, int)
12735     * @see #isHorizontalScrollBarEnabled()
12736     * @see #isVerticalScrollBarEnabled()
12737     * @see #setHorizontalScrollBarEnabled(boolean)
12738     * @see #setVerticalScrollBarEnabled(boolean)
12739     */
12740    protected boolean awakenScrollBars(int startDelay) {
12741        return awakenScrollBars(startDelay, true);
12742    }
12743
12744    /**
12745     * <p>
12746     * Trigger the scrollbars to draw. When invoked this method starts an
12747     * animation to fade the scrollbars out after a fixed delay. If a subclass
12748     * provides animated scrolling, the start delay should equal the duration of
12749     * the scrolling animation.
12750     * </p>
12751     *
12752     * <p>
12753     * The animation starts only if at least one of the scrollbars is enabled,
12754     * as specified by {@link #isHorizontalScrollBarEnabled()} and
12755     * {@link #isVerticalScrollBarEnabled()}. When the animation is started,
12756     * this method returns true, and false otherwise. If the animation is
12757     * started, this method calls {@link #invalidate()} if the invalidate parameter
12758     * is set to true; in that case the caller
12759     * should not call {@link #invalidate()}.
12760     * </p>
12761     *
12762     * <p>
12763     * This method should be invoked every time a subclass directly updates the
12764     * scroll parameters.
12765     * </p>
12766     *
12767     * @param startDelay the delay, in milliseconds, after which the animation
12768     *        should start; when the delay is 0, the animation starts
12769     *        immediately
12770     *
12771     * @param invalidate Whether this method should call invalidate
12772     *
12773     * @return true if the animation is played, false otherwise
12774     *
12775     * @see #scrollBy(int, int)
12776     * @see #scrollTo(int, int)
12777     * @see #isHorizontalScrollBarEnabled()
12778     * @see #isVerticalScrollBarEnabled()
12779     * @see #setHorizontalScrollBarEnabled(boolean)
12780     * @see #setVerticalScrollBarEnabled(boolean)
12781     */
12782    protected boolean awakenScrollBars(int startDelay, boolean invalidate) {
12783        final ScrollabilityCache scrollCache = mScrollCache;
12784
12785        if (scrollCache == null || !scrollCache.fadeScrollBars) {
12786            return false;
12787        }
12788
12789        if (scrollCache.scrollBar == null) {
12790            scrollCache.scrollBar = new ScrollBarDrawable();
12791            scrollCache.scrollBar.setCallback(this);
12792            scrollCache.scrollBar.setState(getDrawableState());
12793        }
12794
12795        if (isHorizontalScrollBarEnabled() || isVerticalScrollBarEnabled()) {
12796
12797            if (invalidate) {
12798                // Invalidate to show the scrollbars
12799                postInvalidateOnAnimation();
12800            }
12801
12802            if (scrollCache.state == ScrollabilityCache.OFF) {
12803                // FIXME: this is copied from WindowManagerService.
12804                // We should get this value from the system when it
12805                // is possible to do so.
12806                final int KEY_REPEAT_FIRST_DELAY = 750;
12807                startDelay = Math.max(KEY_REPEAT_FIRST_DELAY, startDelay);
12808            }
12809
12810            // Tell mScrollCache when we should start fading. This may
12811            // extend the fade start time if one was already scheduled
12812            long fadeStartTime = AnimationUtils.currentAnimationTimeMillis() + startDelay;
12813            scrollCache.fadeStartTime = fadeStartTime;
12814            scrollCache.state = ScrollabilityCache.ON;
12815
12816            // Schedule our fader to run, unscheduling any old ones first
12817            if (mAttachInfo != null) {
12818                mAttachInfo.mHandler.removeCallbacks(scrollCache);
12819                mAttachInfo.mHandler.postAtTime(scrollCache, fadeStartTime);
12820            }
12821
12822            return true;
12823        }
12824
12825        return false;
12826    }
12827
12828    /**
12829     * Do not invalidate views which are not visible and which are not running an animation. They
12830     * will not get drawn and they should not set dirty flags as if they will be drawn
12831     */
12832    private boolean skipInvalidate() {
12833        return (mViewFlags & VISIBILITY_MASK) != VISIBLE && mCurrentAnimation == null &&
12834                (!(mParent instanceof ViewGroup) ||
12835                        !((ViewGroup) mParent).isViewTransitioning(this));
12836    }
12837
12838    /**
12839     * Mark the area defined by dirty as needing to be drawn. If the view is
12840     * visible, {@link #onDraw(android.graphics.Canvas)} will be called at some
12841     * point in the future.
12842     * <p>
12843     * This must be called from a UI thread. To call from a non-UI thread, call
12844     * {@link #postInvalidate()}.
12845     * <p>
12846     * <b>WARNING:</b> In API 19 and below, this method may be destructive to
12847     * {@code dirty}.
12848     *
12849     * @param dirty the rectangle representing the bounds of the dirty region
12850     */
12851    public void invalidate(Rect dirty) {
12852        final int scrollX = mScrollX;
12853        final int scrollY = mScrollY;
12854        invalidateInternal(dirty.left - scrollX, dirty.top - scrollY,
12855                dirty.right - scrollX, dirty.bottom - scrollY, true, false);
12856    }
12857
12858    /**
12859     * Mark the area defined by the rect (l,t,r,b) as needing to be drawn. The
12860     * coordinates of the dirty rect are relative to the view. If the view is
12861     * visible, {@link #onDraw(android.graphics.Canvas)} will be called at some
12862     * point in the future.
12863     * <p>
12864     * This must be called from a UI thread. To call from a non-UI thread, call
12865     * {@link #postInvalidate()}.
12866     *
12867     * @param l the left position of the dirty region
12868     * @param t the top position of the dirty region
12869     * @param r the right position of the dirty region
12870     * @param b the bottom position of the dirty region
12871     */
12872    public void invalidate(int l, int t, int r, int b) {
12873        final int scrollX = mScrollX;
12874        final int scrollY = mScrollY;
12875        invalidateInternal(l - scrollX, t - scrollY, r - scrollX, b - scrollY, true, false);
12876    }
12877
12878    /**
12879     * Invalidate the whole view. If the view is visible,
12880     * {@link #onDraw(android.graphics.Canvas)} will be called at some point in
12881     * the future.
12882     * <p>
12883     * This must be called from a UI thread. To call from a non-UI thread, call
12884     * {@link #postInvalidate()}.
12885     */
12886    public void invalidate() {
12887        invalidate(true);
12888    }
12889
12890    /**
12891     * This is where the invalidate() work actually happens. A full invalidate()
12892     * causes the drawing cache to be invalidated, but this function can be
12893     * called with invalidateCache set to false to skip that invalidation step
12894     * for cases that do not need it (for example, a component that remains at
12895     * the same dimensions with the same content).
12896     *
12897     * @param invalidateCache Whether the drawing cache for this view should be
12898     *            invalidated as well. This is usually true for a full
12899     *            invalidate, but may be set to false if the View's contents or
12900     *            dimensions have not changed.
12901     */
12902    void invalidate(boolean invalidateCache) {
12903        invalidateInternal(0, 0, mRight - mLeft, mBottom - mTop, invalidateCache, true);
12904    }
12905
12906    void invalidateInternal(int l, int t, int r, int b, boolean invalidateCache,
12907            boolean fullInvalidate) {
12908        if (mGhostView != null) {
12909            mGhostView.invalidate(true);
12910            return;
12911        }
12912
12913        if (skipInvalidate()) {
12914            return;
12915        }
12916
12917        if ((mPrivateFlags & (PFLAG_DRAWN | PFLAG_HAS_BOUNDS)) == (PFLAG_DRAWN | PFLAG_HAS_BOUNDS)
12918                || (invalidateCache && (mPrivateFlags & PFLAG_DRAWING_CACHE_VALID) == PFLAG_DRAWING_CACHE_VALID)
12919                || (mPrivateFlags & PFLAG_INVALIDATED) != PFLAG_INVALIDATED
12920                || (fullInvalidate && isOpaque() != mLastIsOpaque)) {
12921            if (fullInvalidate) {
12922                mLastIsOpaque = isOpaque();
12923                mPrivateFlags &= ~PFLAG_DRAWN;
12924            }
12925
12926            mPrivateFlags |= PFLAG_DIRTY;
12927
12928            if (invalidateCache) {
12929                mPrivateFlags |= PFLAG_INVALIDATED;
12930                mPrivateFlags &= ~PFLAG_DRAWING_CACHE_VALID;
12931            }
12932
12933            // Propagate the damage rectangle to the parent view.
12934            final AttachInfo ai = mAttachInfo;
12935            final ViewParent p = mParent;
12936            if (p != null && ai != null && l < r && t < b) {
12937                final Rect damage = ai.mTmpInvalRect;
12938                damage.set(l, t, r, b);
12939                p.invalidateChild(this, damage);
12940            }
12941
12942            // Damage the entire projection receiver, if necessary.
12943            if (mBackground != null && mBackground.isProjected()) {
12944                final View receiver = getProjectionReceiver();
12945                if (receiver != null) {
12946                    receiver.damageInParent();
12947                }
12948            }
12949
12950            // Damage the entire IsolatedZVolume receiving this view's shadow.
12951            if (isHardwareAccelerated() && getZ() != 0) {
12952                damageShadowReceiver();
12953            }
12954        }
12955    }
12956
12957    /**
12958     * @return this view's projection receiver, or {@code null} if none exists
12959     */
12960    private View getProjectionReceiver() {
12961        ViewParent p = getParent();
12962        while (p != null && p instanceof View) {
12963            final View v = (View) p;
12964            if (v.isProjectionReceiver()) {
12965                return v;
12966            }
12967            p = p.getParent();
12968        }
12969
12970        return null;
12971    }
12972
12973    /**
12974     * @return whether the view is a projection receiver
12975     */
12976    private boolean isProjectionReceiver() {
12977        return mBackground != null;
12978    }
12979
12980    /**
12981     * Damage area of the screen that can be covered by this View's shadow.
12982     *
12983     * This method will guarantee that any changes to shadows cast by a View
12984     * are damaged on the screen for future redraw.
12985     */
12986    private void damageShadowReceiver() {
12987        final AttachInfo ai = mAttachInfo;
12988        if (ai != null) {
12989            ViewParent p = getParent();
12990            if (p != null && p instanceof ViewGroup) {
12991                final ViewGroup vg = (ViewGroup) p;
12992                vg.damageInParent();
12993            }
12994        }
12995    }
12996
12997    /**
12998     * Quick invalidation for View property changes (alpha, translationXY, etc.). We don't want to
12999     * set any flags or handle all of the cases handled by the default invalidation methods.
13000     * Instead, we just want to schedule a traversal in ViewRootImpl with the appropriate
13001     * dirty rect. This method calls into fast invalidation methods in ViewGroup that
13002     * walk up the hierarchy, transforming the dirty rect as necessary.
13003     *
13004     * The method also handles normal invalidation logic if display list properties are not
13005     * being used in this view. The invalidateParent and forceRedraw flags are used by that
13006     * backup approach, to handle these cases used in the various property-setting methods.
13007     *
13008     * @param invalidateParent Force a call to invalidateParentCaches() if display list properties
13009     * are not being used in this view
13010     * @param forceRedraw Mark the view as DRAWN to force the invalidation to propagate, if display
13011     * list properties are not being used in this view
13012     */
13013    void invalidateViewProperty(boolean invalidateParent, boolean forceRedraw) {
13014        if (!isHardwareAccelerated()
13015                || !mRenderNode.isValid()
13016                || (mPrivateFlags & PFLAG_DRAW_ANIMATION) != 0) {
13017            if (invalidateParent) {
13018                invalidateParentCaches();
13019            }
13020            if (forceRedraw) {
13021                mPrivateFlags |= PFLAG_DRAWN; // force another invalidation with the new orientation
13022            }
13023            invalidate(false);
13024        } else {
13025            damageInParent();
13026        }
13027        if (isHardwareAccelerated() && invalidateParent && getZ() != 0) {
13028            damageShadowReceiver();
13029        }
13030    }
13031
13032    /**
13033     * Tells the parent view to damage this view's bounds.
13034     *
13035     * @hide
13036     */
13037    protected void damageInParent() {
13038        final AttachInfo ai = mAttachInfo;
13039        final ViewParent p = mParent;
13040        if (p != null && ai != null) {
13041            final Rect r = ai.mTmpInvalRect;
13042            r.set(0, 0, mRight - mLeft, mBottom - mTop);
13043            if (mParent instanceof ViewGroup) {
13044                ((ViewGroup) mParent).damageChild(this, r);
13045            } else {
13046                mParent.invalidateChild(this, r);
13047            }
13048        }
13049    }
13050
13051    /**
13052     * Utility method to transform a given Rect by the current matrix of this view.
13053     */
13054    void transformRect(final Rect rect) {
13055        if (!getMatrix().isIdentity()) {
13056            RectF boundingRect = mAttachInfo.mTmpTransformRect;
13057            boundingRect.set(rect);
13058            getMatrix().mapRect(boundingRect);
13059            rect.set((int) Math.floor(boundingRect.left),
13060                    (int) Math.floor(boundingRect.top),
13061                    (int) Math.ceil(boundingRect.right),
13062                    (int) Math.ceil(boundingRect.bottom));
13063        }
13064    }
13065
13066    /**
13067     * Used to indicate that the parent of this view should clear its caches. This functionality
13068     * is used to force the parent to rebuild its display list (when hardware-accelerated),
13069     * which is necessary when various parent-managed properties of the view change, such as
13070     * alpha, translationX/Y, scrollX/Y, scaleX/Y, and rotation/X/Y. This method only
13071     * clears the parent caches and does not causes an invalidate event.
13072     *
13073     * @hide
13074     */
13075    protected void invalidateParentCaches() {
13076        if (mParent instanceof View) {
13077            ((View) mParent).mPrivateFlags |= PFLAG_INVALIDATED;
13078        }
13079    }
13080
13081    /**
13082     * Used to indicate that the parent of this view should be invalidated. This functionality
13083     * is used to force the parent to rebuild its display list (when hardware-accelerated),
13084     * which is necessary when various parent-managed properties of the view change, such as
13085     * alpha, translationX/Y, scrollX/Y, scaleX/Y, and rotation/X/Y. This method will propagate
13086     * an invalidation event to the parent.
13087     *
13088     * @hide
13089     */
13090    protected void invalidateParentIfNeeded() {
13091        if (isHardwareAccelerated() && mParent instanceof View) {
13092            ((View) mParent).invalidate(true);
13093        }
13094    }
13095
13096    /**
13097     * @hide
13098     */
13099    protected void invalidateParentIfNeededAndWasQuickRejected() {
13100        if ((mPrivateFlags2 & PFLAG2_VIEW_QUICK_REJECTED) != 0) {
13101            // View was rejected last time it was drawn by its parent; this may have changed
13102            invalidateParentIfNeeded();
13103        }
13104    }
13105
13106    /**
13107     * Indicates whether this View is opaque. An opaque View guarantees that it will
13108     * draw all the pixels overlapping its bounds using a fully opaque color.
13109     *
13110     * Subclasses of View should override this method whenever possible to indicate
13111     * whether an instance is opaque. Opaque Views are treated in a special way by
13112     * the View hierarchy, possibly allowing it to perform optimizations during
13113     * invalidate/draw passes.
13114     *
13115     * @return True if this View is guaranteed to be fully opaque, false otherwise.
13116     */
13117    @ViewDebug.ExportedProperty(category = "drawing")
13118    public boolean isOpaque() {
13119        return (mPrivateFlags & PFLAG_OPAQUE_MASK) == PFLAG_OPAQUE_MASK &&
13120                getFinalAlpha() >= 1.0f;
13121    }
13122
13123    /**
13124     * @hide
13125     */
13126    protected void computeOpaqueFlags() {
13127        // Opaque if:
13128        //   - Has a background
13129        //   - Background is opaque
13130        //   - Doesn't have scrollbars or scrollbars overlay
13131
13132        if (mBackground != null && mBackground.getOpacity() == PixelFormat.OPAQUE) {
13133            mPrivateFlags |= PFLAG_OPAQUE_BACKGROUND;
13134        } else {
13135            mPrivateFlags &= ~PFLAG_OPAQUE_BACKGROUND;
13136        }
13137
13138        final int flags = mViewFlags;
13139        if (((flags & SCROLLBARS_VERTICAL) == 0 && (flags & SCROLLBARS_HORIZONTAL) == 0) ||
13140                (flags & SCROLLBARS_STYLE_MASK) == SCROLLBARS_INSIDE_OVERLAY ||
13141                (flags & SCROLLBARS_STYLE_MASK) == SCROLLBARS_OUTSIDE_OVERLAY) {
13142            mPrivateFlags |= PFLAG_OPAQUE_SCROLLBARS;
13143        } else {
13144            mPrivateFlags &= ~PFLAG_OPAQUE_SCROLLBARS;
13145        }
13146    }
13147
13148    /**
13149     * @hide
13150     */
13151    protected boolean hasOpaqueScrollbars() {
13152        return (mPrivateFlags & PFLAG_OPAQUE_SCROLLBARS) == PFLAG_OPAQUE_SCROLLBARS;
13153    }
13154
13155    /**
13156     * @return A handler associated with the thread running the View. This
13157     * handler can be used to pump events in the UI events queue.
13158     */
13159    public Handler getHandler() {
13160        final AttachInfo attachInfo = mAttachInfo;
13161        if (attachInfo != null) {
13162            return attachInfo.mHandler;
13163        }
13164        return null;
13165    }
13166
13167    /**
13168     * Returns the queue of runnable for this view.
13169     *
13170     * @return the queue of runnables for this view
13171     */
13172    private HandlerActionQueue getRunQueue() {
13173        if (mRunQueue == null) {
13174            mRunQueue = new HandlerActionQueue();
13175        }
13176        return mRunQueue;
13177    }
13178
13179    /**
13180     * Gets the view root associated with the View.
13181     * @return The view root, or null if none.
13182     * @hide
13183     */
13184    public ViewRootImpl getViewRootImpl() {
13185        if (mAttachInfo != null) {
13186            return mAttachInfo.mViewRootImpl;
13187        }
13188        return null;
13189    }
13190
13191    /**
13192     * @hide
13193     */
13194    public HardwareRenderer getHardwareRenderer() {
13195        return mAttachInfo != null ? mAttachInfo.mHardwareRenderer : null;
13196    }
13197
13198    /**
13199     * <p>Causes the Runnable to be added to the message queue.
13200     * The runnable will be run on the user interface thread.</p>
13201     *
13202     * @param action The Runnable that will be executed.
13203     *
13204     * @return Returns true if the Runnable was successfully placed in to the
13205     *         message queue.  Returns false on failure, usually because the
13206     *         looper processing the message queue is exiting.
13207     *
13208     * @see #postDelayed
13209     * @see #removeCallbacks
13210     */
13211    public boolean post(Runnable action) {
13212        final AttachInfo attachInfo = mAttachInfo;
13213        if (attachInfo != null) {
13214            return attachInfo.mHandler.post(action);
13215        }
13216
13217        // Postpone the runnable until we know on which thread it needs to run.
13218        // Assume that the runnable will be successfully placed after attach.
13219        getRunQueue().post(action);
13220        return true;
13221    }
13222
13223    /**
13224     * <p>Causes the Runnable to be added to the message queue, to be run
13225     * after the specified amount of time elapses.
13226     * The runnable will be run on the user interface thread.</p>
13227     *
13228     * @param action The Runnable that will be executed.
13229     * @param delayMillis The delay (in milliseconds) until the Runnable
13230     *        will be executed.
13231     *
13232     * @return true if the Runnable was successfully placed in to the
13233     *         message queue.  Returns false on failure, usually because the
13234     *         looper processing the message queue is exiting.  Note that a
13235     *         result of true does not mean the Runnable will be processed --
13236     *         if the looper is quit before the delivery time of the message
13237     *         occurs then the message will be dropped.
13238     *
13239     * @see #post
13240     * @see #removeCallbacks
13241     */
13242    public boolean postDelayed(Runnable action, long delayMillis) {
13243        final AttachInfo attachInfo = mAttachInfo;
13244        if (attachInfo != null) {
13245            return attachInfo.mHandler.postDelayed(action, delayMillis);
13246        }
13247
13248        // Postpone the runnable until we know on which thread it needs to run.
13249        // Assume that the runnable will be successfully placed after attach.
13250        getRunQueue().postDelayed(action, delayMillis);
13251        return true;
13252    }
13253
13254    /**
13255     * <p>Causes the Runnable to execute on the next animation time step.
13256     * The runnable will be run on the user interface thread.</p>
13257     *
13258     * @param action The Runnable that will be executed.
13259     *
13260     * @see #postOnAnimationDelayed
13261     * @see #removeCallbacks
13262     */
13263    public void postOnAnimation(Runnable action) {
13264        final AttachInfo attachInfo = mAttachInfo;
13265        if (attachInfo != null) {
13266            attachInfo.mViewRootImpl.mChoreographer.postCallback(
13267                    Choreographer.CALLBACK_ANIMATION, action, null);
13268        } else {
13269            // Postpone the runnable until we know
13270            // on which thread it needs to run.
13271            getRunQueue().post(action);
13272        }
13273    }
13274
13275    /**
13276     * <p>Causes the Runnable to execute on the next animation time step,
13277     * after the specified amount of time elapses.
13278     * The runnable will be run on the user interface thread.</p>
13279     *
13280     * @param action The Runnable that will be executed.
13281     * @param delayMillis The delay (in milliseconds) until the Runnable
13282     *        will be executed.
13283     *
13284     * @see #postOnAnimation
13285     * @see #removeCallbacks
13286     */
13287    public void postOnAnimationDelayed(Runnable action, long delayMillis) {
13288        final AttachInfo attachInfo = mAttachInfo;
13289        if (attachInfo != null) {
13290            attachInfo.mViewRootImpl.mChoreographer.postCallbackDelayed(
13291                    Choreographer.CALLBACK_ANIMATION, action, null, delayMillis);
13292        } else {
13293            // Postpone the runnable until we know
13294            // on which thread it needs to run.
13295            getRunQueue().postDelayed(action, delayMillis);
13296        }
13297    }
13298
13299    /**
13300     * <p>Removes the specified Runnable from the message queue.</p>
13301     *
13302     * @param action The Runnable to remove from the message handling queue
13303     *
13304     * @return true if this view could ask the Handler to remove the Runnable,
13305     *         false otherwise. When the returned value is true, the Runnable
13306     *         may or may not have been actually removed from the message queue
13307     *         (for instance, if the Runnable was not in the queue already.)
13308     *
13309     * @see #post
13310     * @see #postDelayed
13311     * @see #postOnAnimation
13312     * @see #postOnAnimationDelayed
13313     */
13314    public boolean removeCallbacks(Runnable action) {
13315        if (action != null) {
13316            final AttachInfo attachInfo = mAttachInfo;
13317            if (attachInfo != null) {
13318                attachInfo.mHandler.removeCallbacks(action);
13319                attachInfo.mViewRootImpl.mChoreographer.removeCallbacks(
13320                        Choreographer.CALLBACK_ANIMATION, action, null);
13321            }
13322            getRunQueue().removeCallbacks(action);
13323        }
13324        return true;
13325    }
13326
13327    /**
13328     * <p>Cause an invalidate to happen on a subsequent cycle through the event loop.
13329     * Use this to invalidate the View from a non-UI thread.</p>
13330     *
13331     * <p>This method can be invoked from outside of the UI thread
13332     * only when this View is attached to a window.</p>
13333     *
13334     * @see #invalidate()
13335     * @see #postInvalidateDelayed(long)
13336     */
13337    public void postInvalidate() {
13338        postInvalidateDelayed(0);
13339    }
13340
13341    /**
13342     * <p>Cause an invalidate of the specified area to happen on a subsequent cycle
13343     * through the event loop. Use this to invalidate the View from a non-UI thread.</p>
13344     *
13345     * <p>This method can be invoked from outside of the UI thread
13346     * only when this View is attached to a window.</p>
13347     *
13348     * @param left The left coordinate of the rectangle to invalidate.
13349     * @param top The top coordinate of the rectangle to invalidate.
13350     * @param right The right coordinate of the rectangle to invalidate.
13351     * @param bottom The bottom coordinate of the rectangle to invalidate.
13352     *
13353     * @see #invalidate(int, int, int, int)
13354     * @see #invalidate(Rect)
13355     * @see #postInvalidateDelayed(long, int, int, int, int)
13356     */
13357    public void postInvalidate(int left, int top, int right, int bottom) {
13358        postInvalidateDelayed(0, left, top, right, bottom);
13359    }
13360
13361    /**
13362     * <p>Cause an invalidate to happen on a subsequent cycle through the event
13363     * loop. Waits for the specified amount of time.</p>
13364     *
13365     * <p>This method can be invoked from outside of the UI thread
13366     * only when this View is attached to a window.</p>
13367     *
13368     * @param delayMilliseconds the duration in milliseconds to delay the
13369     *         invalidation by
13370     *
13371     * @see #invalidate()
13372     * @see #postInvalidate()
13373     */
13374    public void postInvalidateDelayed(long delayMilliseconds) {
13375        // We try only with the AttachInfo because there's no point in invalidating
13376        // if we are not attached to our window
13377        final AttachInfo attachInfo = mAttachInfo;
13378        if (attachInfo != null) {
13379            attachInfo.mViewRootImpl.dispatchInvalidateDelayed(this, delayMilliseconds);
13380        }
13381    }
13382
13383    /**
13384     * <p>Cause an invalidate of the specified area to happen on a subsequent cycle
13385     * through the event loop. Waits for the specified amount of time.</p>
13386     *
13387     * <p>This method can be invoked from outside of the UI thread
13388     * only when this View is attached to a window.</p>
13389     *
13390     * @param delayMilliseconds the duration in milliseconds to delay the
13391     *         invalidation by
13392     * @param left The left coordinate of the rectangle to invalidate.
13393     * @param top The top coordinate of the rectangle to invalidate.
13394     * @param right The right coordinate of the rectangle to invalidate.
13395     * @param bottom The bottom coordinate of the rectangle to invalidate.
13396     *
13397     * @see #invalidate(int, int, int, int)
13398     * @see #invalidate(Rect)
13399     * @see #postInvalidate(int, int, int, int)
13400     */
13401    public void postInvalidateDelayed(long delayMilliseconds, int left, int top,
13402            int right, int bottom) {
13403
13404        // We try only with the AttachInfo because there's no point in invalidating
13405        // if we are not attached to our window
13406        final AttachInfo attachInfo = mAttachInfo;
13407        if (attachInfo != null) {
13408            final AttachInfo.InvalidateInfo info = AttachInfo.InvalidateInfo.obtain();
13409            info.target = this;
13410            info.left = left;
13411            info.top = top;
13412            info.right = right;
13413            info.bottom = bottom;
13414
13415            attachInfo.mViewRootImpl.dispatchInvalidateRectDelayed(info, delayMilliseconds);
13416        }
13417    }
13418
13419    /**
13420     * <p>Cause an invalidate to happen on the next animation time step, typically the
13421     * next display frame.</p>
13422     *
13423     * <p>This method can be invoked from outside of the UI thread
13424     * only when this View is attached to a window.</p>
13425     *
13426     * @see #invalidate()
13427     */
13428    public void postInvalidateOnAnimation() {
13429        // We try only with the AttachInfo because there's no point in invalidating
13430        // if we are not attached to our window
13431        final AttachInfo attachInfo = mAttachInfo;
13432        if (attachInfo != null) {
13433            attachInfo.mViewRootImpl.dispatchInvalidateOnAnimation(this);
13434        }
13435    }
13436
13437    /**
13438     * <p>Cause an invalidate of the specified area to happen on the next animation
13439     * time step, typically the next display frame.</p>
13440     *
13441     * <p>This method can be invoked from outside of the UI thread
13442     * only when this View is attached to a window.</p>
13443     *
13444     * @param left The left coordinate of the rectangle to invalidate.
13445     * @param top The top coordinate of the rectangle to invalidate.
13446     * @param right The right coordinate of the rectangle to invalidate.
13447     * @param bottom The bottom coordinate of the rectangle to invalidate.
13448     *
13449     * @see #invalidate(int, int, int, int)
13450     * @see #invalidate(Rect)
13451     */
13452    public void postInvalidateOnAnimation(int left, int top, int right, int bottom) {
13453        // We try only with the AttachInfo because there's no point in invalidating
13454        // if we are not attached to our window
13455        final AttachInfo attachInfo = mAttachInfo;
13456        if (attachInfo != null) {
13457            final AttachInfo.InvalidateInfo info = AttachInfo.InvalidateInfo.obtain();
13458            info.target = this;
13459            info.left = left;
13460            info.top = top;
13461            info.right = right;
13462            info.bottom = bottom;
13463
13464            attachInfo.mViewRootImpl.dispatchInvalidateRectOnAnimation(info);
13465        }
13466    }
13467
13468    /**
13469     * Post a callback to send a {@link AccessibilityEvent#TYPE_VIEW_SCROLLED} event.
13470     * This event is sent at most once every
13471     * {@link ViewConfiguration#getSendRecurringAccessibilityEventsInterval()}.
13472     */
13473    private void postSendViewScrolledAccessibilityEventCallback() {
13474        if (mSendViewScrolledAccessibilityEvent == null) {
13475            mSendViewScrolledAccessibilityEvent = new SendViewScrolledAccessibilityEvent();
13476        }
13477        if (!mSendViewScrolledAccessibilityEvent.mIsPending) {
13478            mSendViewScrolledAccessibilityEvent.mIsPending = true;
13479            postDelayed(mSendViewScrolledAccessibilityEvent,
13480                    ViewConfiguration.getSendRecurringAccessibilityEventsInterval());
13481        }
13482    }
13483
13484    /**
13485     * Called by a parent to request that a child update its values for mScrollX
13486     * and mScrollY if necessary. This will typically be done if the child is
13487     * animating a scroll using a {@link android.widget.Scroller Scroller}
13488     * object.
13489     */
13490    public void computeScroll() {
13491    }
13492
13493    /**
13494     * <p>Indicate whether the horizontal edges are faded when the view is
13495     * scrolled horizontally.</p>
13496     *
13497     * @return true if the horizontal edges should are faded on scroll, false
13498     *         otherwise
13499     *
13500     * @see #setHorizontalFadingEdgeEnabled(boolean)
13501     *
13502     * @attr ref android.R.styleable#View_requiresFadingEdge
13503     */
13504    public boolean isHorizontalFadingEdgeEnabled() {
13505        return (mViewFlags & FADING_EDGE_HORIZONTAL) == FADING_EDGE_HORIZONTAL;
13506    }
13507
13508    /**
13509     * <p>Define whether the horizontal edges should be faded when this view
13510     * is scrolled horizontally.</p>
13511     *
13512     * @param horizontalFadingEdgeEnabled true if the horizontal edges should
13513     *                                    be faded when the view is scrolled
13514     *                                    horizontally
13515     *
13516     * @see #isHorizontalFadingEdgeEnabled()
13517     *
13518     * @attr ref android.R.styleable#View_requiresFadingEdge
13519     */
13520    public void setHorizontalFadingEdgeEnabled(boolean horizontalFadingEdgeEnabled) {
13521        if (isHorizontalFadingEdgeEnabled() != horizontalFadingEdgeEnabled) {
13522            if (horizontalFadingEdgeEnabled) {
13523                initScrollCache();
13524            }
13525
13526            mViewFlags ^= FADING_EDGE_HORIZONTAL;
13527        }
13528    }
13529
13530    /**
13531     * <p>Indicate whether the vertical edges are faded when the view is
13532     * scrolled horizontally.</p>
13533     *
13534     * @return true if the vertical edges should are faded on scroll, false
13535     *         otherwise
13536     *
13537     * @see #setVerticalFadingEdgeEnabled(boolean)
13538     *
13539     * @attr ref android.R.styleable#View_requiresFadingEdge
13540     */
13541    public boolean isVerticalFadingEdgeEnabled() {
13542        return (mViewFlags & FADING_EDGE_VERTICAL) == FADING_EDGE_VERTICAL;
13543    }
13544
13545    /**
13546     * <p>Define whether the vertical edges should be faded when this view
13547     * is scrolled vertically.</p>
13548     *
13549     * @param verticalFadingEdgeEnabled true if the vertical edges should
13550     *                                  be faded when the view is scrolled
13551     *                                  vertically
13552     *
13553     * @see #isVerticalFadingEdgeEnabled()
13554     *
13555     * @attr ref android.R.styleable#View_requiresFadingEdge
13556     */
13557    public void setVerticalFadingEdgeEnabled(boolean verticalFadingEdgeEnabled) {
13558        if (isVerticalFadingEdgeEnabled() != verticalFadingEdgeEnabled) {
13559            if (verticalFadingEdgeEnabled) {
13560                initScrollCache();
13561            }
13562
13563            mViewFlags ^= FADING_EDGE_VERTICAL;
13564        }
13565    }
13566
13567    /**
13568     * Returns the strength, or intensity, of the top faded edge. The strength is
13569     * a value between 0.0 (no fade) and 1.0 (full fade). The default implementation
13570     * returns 0.0 or 1.0 but no value in between.
13571     *
13572     * Subclasses should override this method to provide a smoother fade transition
13573     * when scrolling occurs.
13574     *
13575     * @return the intensity of the top fade as a float between 0.0f and 1.0f
13576     */
13577    protected float getTopFadingEdgeStrength() {
13578        return computeVerticalScrollOffset() > 0 ? 1.0f : 0.0f;
13579    }
13580
13581    /**
13582     * Returns the strength, or intensity, of the bottom faded edge. The strength is
13583     * a value between 0.0 (no fade) and 1.0 (full fade). The default implementation
13584     * returns 0.0 or 1.0 but no value in between.
13585     *
13586     * Subclasses should override this method to provide a smoother fade transition
13587     * when scrolling occurs.
13588     *
13589     * @return the intensity of the bottom fade as a float between 0.0f and 1.0f
13590     */
13591    protected float getBottomFadingEdgeStrength() {
13592        return computeVerticalScrollOffset() + computeVerticalScrollExtent() <
13593                computeVerticalScrollRange() ? 1.0f : 0.0f;
13594    }
13595
13596    /**
13597     * Returns the strength, or intensity, of the left faded edge. The strength is
13598     * a value between 0.0 (no fade) and 1.0 (full fade). The default implementation
13599     * returns 0.0 or 1.0 but no value in between.
13600     *
13601     * Subclasses should override this method to provide a smoother fade transition
13602     * when scrolling occurs.
13603     *
13604     * @return the intensity of the left fade as a float between 0.0f and 1.0f
13605     */
13606    protected float getLeftFadingEdgeStrength() {
13607        return computeHorizontalScrollOffset() > 0 ? 1.0f : 0.0f;
13608    }
13609
13610    /**
13611     * Returns the strength, or intensity, of the right 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 right fade as a float between 0.0f and 1.0f
13619     */
13620    protected float getRightFadingEdgeStrength() {
13621        return computeHorizontalScrollOffset() + computeHorizontalScrollExtent() <
13622                computeHorizontalScrollRange() ? 1.0f : 0.0f;
13623    }
13624
13625    /**
13626     * <p>Indicate whether the horizontal scrollbar should be drawn or not. The
13627     * scrollbar is not drawn by default.</p>
13628     *
13629     * @return true if the horizontal scrollbar should be painted, false
13630     *         otherwise
13631     *
13632     * @see #setHorizontalScrollBarEnabled(boolean)
13633     */
13634    public boolean isHorizontalScrollBarEnabled() {
13635        return (mViewFlags & SCROLLBARS_HORIZONTAL) == SCROLLBARS_HORIZONTAL;
13636    }
13637
13638    /**
13639     * <p>Define whether the horizontal scrollbar should be drawn or not. The
13640     * scrollbar is not drawn by default.</p>
13641     *
13642     * @param horizontalScrollBarEnabled true if the horizontal scrollbar should
13643     *                                   be painted
13644     *
13645     * @see #isHorizontalScrollBarEnabled()
13646     */
13647    public void setHorizontalScrollBarEnabled(boolean horizontalScrollBarEnabled) {
13648        if (isHorizontalScrollBarEnabled() != horizontalScrollBarEnabled) {
13649            mViewFlags ^= SCROLLBARS_HORIZONTAL;
13650            computeOpaqueFlags();
13651            resolvePadding();
13652        }
13653    }
13654
13655    /**
13656     * <p>Indicate whether the vertical scrollbar should be drawn or not. The
13657     * scrollbar is not drawn by default.</p>
13658     *
13659     * @return true if the vertical scrollbar should be painted, false
13660     *         otherwise
13661     *
13662     * @see #setVerticalScrollBarEnabled(boolean)
13663     */
13664    public boolean isVerticalScrollBarEnabled() {
13665        return (mViewFlags & SCROLLBARS_VERTICAL) == SCROLLBARS_VERTICAL;
13666    }
13667
13668    /**
13669     * <p>Define whether the vertical scrollbar should be drawn or not. The
13670     * scrollbar is not drawn by default.</p>
13671     *
13672     * @param verticalScrollBarEnabled true if the vertical scrollbar should
13673     *                                 be painted
13674     *
13675     * @see #isVerticalScrollBarEnabled()
13676     */
13677    public void setVerticalScrollBarEnabled(boolean verticalScrollBarEnabled) {
13678        if (isVerticalScrollBarEnabled() != verticalScrollBarEnabled) {
13679            mViewFlags ^= SCROLLBARS_VERTICAL;
13680            computeOpaqueFlags();
13681            resolvePadding();
13682        }
13683    }
13684
13685    /**
13686     * @hide
13687     */
13688    protected void recomputePadding() {
13689        internalSetPadding(mUserPaddingLeft, mPaddingTop, mUserPaddingRight, mUserPaddingBottom);
13690    }
13691
13692    /**
13693     * Define whether scrollbars will fade when the view is not scrolling.
13694     *
13695     * @param fadeScrollbars whether to enable fading
13696     *
13697     * @attr ref android.R.styleable#View_fadeScrollbars
13698     */
13699    public void setScrollbarFadingEnabled(boolean fadeScrollbars) {
13700        initScrollCache();
13701        final ScrollabilityCache scrollabilityCache = mScrollCache;
13702        scrollabilityCache.fadeScrollBars = fadeScrollbars;
13703        if (fadeScrollbars) {
13704            scrollabilityCache.state = ScrollabilityCache.OFF;
13705        } else {
13706            scrollabilityCache.state = ScrollabilityCache.ON;
13707        }
13708    }
13709
13710    /**
13711     *
13712     * Returns true if scrollbars will fade when this view is not scrolling
13713     *
13714     * @return true if scrollbar fading is enabled
13715     *
13716     * @attr ref android.R.styleable#View_fadeScrollbars
13717     */
13718    public boolean isScrollbarFadingEnabled() {
13719        return mScrollCache != null && mScrollCache.fadeScrollBars;
13720    }
13721
13722    /**
13723     *
13724     * Returns the delay before scrollbars fade.
13725     *
13726     * @return the delay before scrollbars fade
13727     *
13728     * @attr ref android.R.styleable#View_scrollbarDefaultDelayBeforeFade
13729     */
13730    public int getScrollBarDefaultDelayBeforeFade() {
13731        return mScrollCache == null ? ViewConfiguration.getScrollDefaultDelay() :
13732                mScrollCache.scrollBarDefaultDelayBeforeFade;
13733    }
13734
13735    /**
13736     * Define the delay before scrollbars fade.
13737     *
13738     * @param scrollBarDefaultDelayBeforeFade - the delay before scrollbars fade
13739     *
13740     * @attr ref android.R.styleable#View_scrollbarDefaultDelayBeforeFade
13741     */
13742    public void setScrollBarDefaultDelayBeforeFade(int scrollBarDefaultDelayBeforeFade) {
13743        getScrollCache().scrollBarDefaultDelayBeforeFade = scrollBarDefaultDelayBeforeFade;
13744    }
13745
13746    /**
13747     *
13748     * Returns the scrollbar fade duration.
13749     *
13750     * @return the scrollbar fade duration
13751     *
13752     * @attr ref android.R.styleable#View_scrollbarFadeDuration
13753     */
13754    public int getScrollBarFadeDuration() {
13755        return mScrollCache == null ? ViewConfiguration.getScrollBarFadeDuration() :
13756                mScrollCache.scrollBarFadeDuration;
13757    }
13758
13759    /**
13760     * Define the scrollbar fade duration.
13761     *
13762     * @param scrollBarFadeDuration - the scrollbar fade duration
13763     *
13764     * @attr ref android.R.styleable#View_scrollbarFadeDuration
13765     */
13766    public void setScrollBarFadeDuration(int scrollBarFadeDuration) {
13767        getScrollCache().scrollBarFadeDuration = scrollBarFadeDuration;
13768    }
13769
13770    /**
13771     *
13772     * Returns the scrollbar size.
13773     *
13774     * @return the scrollbar size
13775     *
13776     * @attr ref android.R.styleable#View_scrollbarSize
13777     */
13778    public int getScrollBarSize() {
13779        return mScrollCache == null ? ViewConfiguration.get(mContext).getScaledScrollBarSize() :
13780                mScrollCache.scrollBarSize;
13781    }
13782
13783    /**
13784     * Define the scrollbar size.
13785     *
13786     * @param scrollBarSize - the scrollbar size
13787     *
13788     * @attr ref android.R.styleable#View_scrollbarSize
13789     */
13790    public void setScrollBarSize(int scrollBarSize) {
13791        getScrollCache().scrollBarSize = scrollBarSize;
13792    }
13793
13794    /**
13795     * <p>Specify the style of the scrollbars. The scrollbars can be overlaid or
13796     * inset. When inset, they add to the padding of the view. And the scrollbars
13797     * can be drawn inside the padding area or on the edge of the view. For example,
13798     * if a view has a background drawable and you want to draw the scrollbars
13799     * inside the padding specified by the drawable, you can use
13800     * SCROLLBARS_INSIDE_OVERLAY or SCROLLBARS_INSIDE_INSET. If you want them to
13801     * appear at the edge of the view, ignoring the padding, then you can use
13802     * SCROLLBARS_OUTSIDE_OVERLAY or SCROLLBARS_OUTSIDE_INSET.</p>
13803     * @param style the style of the scrollbars. Should be one of
13804     * SCROLLBARS_INSIDE_OVERLAY, SCROLLBARS_INSIDE_INSET,
13805     * SCROLLBARS_OUTSIDE_OVERLAY or SCROLLBARS_OUTSIDE_INSET.
13806     * @see #SCROLLBARS_INSIDE_OVERLAY
13807     * @see #SCROLLBARS_INSIDE_INSET
13808     * @see #SCROLLBARS_OUTSIDE_OVERLAY
13809     * @see #SCROLLBARS_OUTSIDE_INSET
13810     *
13811     * @attr ref android.R.styleable#View_scrollbarStyle
13812     */
13813    public void setScrollBarStyle(@ScrollBarStyle int style) {
13814        if (style != (mViewFlags & SCROLLBARS_STYLE_MASK)) {
13815            mViewFlags = (mViewFlags & ~SCROLLBARS_STYLE_MASK) | (style & SCROLLBARS_STYLE_MASK);
13816            computeOpaqueFlags();
13817            resolvePadding();
13818        }
13819    }
13820
13821    /**
13822     * <p>Returns the current scrollbar style.</p>
13823     * @return the current scrollbar style
13824     * @see #SCROLLBARS_INSIDE_OVERLAY
13825     * @see #SCROLLBARS_INSIDE_INSET
13826     * @see #SCROLLBARS_OUTSIDE_OVERLAY
13827     * @see #SCROLLBARS_OUTSIDE_INSET
13828     *
13829     * @attr ref android.R.styleable#View_scrollbarStyle
13830     */
13831    @ViewDebug.ExportedProperty(mapping = {
13832            @ViewDebug.IntToString(from = SCROLLBARS_INSIDE_OVERLAY, to = "INSIDE_OVERLAY"),
13833            @ViewDebug.IntToString(from = SCROLLBARS_INSIDE_INSET, to = "INSIDE_INSET"),
13834            @ViewDebug.IntToString(from = SCROLLBARS_OUTSIDE_OVERLAY, to = "OUTSIDE_OVERLAY"),
13835            @ViewDebug.IntToString(from = SCROLLBARS_OUTSIDE_INSET, to = "OUTSIDE_INSET")
13836    })
13837    @ScrollBarStyle
13838    public int getScrollBarStyle() {
13839        return mViewFlags & SCROLLBARS_STYLE_MASK;
13840    }
13841
13842    /**
13843     * <p>Compute the horizontal range that the horizontal scrollbar
13844     * represents.</p>
13845     *
13846     * <p>The range is expressed in arbitrary units that must be the same as the
13847     * units used by {@link #computeHorizontalScrollExtent()} and
13848     * {@link #computeHorizontalScrollOffset()}.</p>
13849     *
13850     * <p>The default range is the drawing width of this view.</p>
13851     *
13852     * @return the total horizontal range represented by the horizontal
13853     *         scrollbar
13854     *
13855     * @see #computeHorizontalScrollExtent()
13856     * @see #computeHorizontalScrollOffset()
13857     * @see android.widget.ScrollBarDrawable
13858     */
13859    protected int computeHorizontalScrollRange() {
13860        return getWidth();
13861    }
13862
13863    /**
13864     * <p>Compute the horizontal offset of the horizontal scrollbar's thumb
13865     * within the horizontal range. This value is used to compute the position
13866     * of the thumb within the scrollbar's track.</p>
13867     *
13868     * <p>The range is expressed in arbitrary units that must be the same as the
13869     * units used by {@link #computeHorizontalScrollRange()} and
13870     * {@link #computeHorizontalScrollExtent()}.</p>
13871     *
13872     * <p>The default offset is the scroll offset of this view.</p>
13873     *
13874     * @return the horizontal offset of the scrollbar's thumb
13875     *
13876     * @see #computeHorizontalScrollRange()
13877     * @see #computeHorizontalScrollExtent()
13878     * @see android.widget.ScrollBarDrawable
13879     */
13880    protected int computeHorizontalScrollOffset() {
13881        return mScrollX;
13882    }
13883
13884    /**
13885     * <p>Compute the horizontal extent of the horizontal scrollbar's thumb
13886     * within the horizontal range. This value is used to compute the length
13887     * of the thumb within the scrollbar's track.</p>
13888     *
13889     * <p>The range is expressed in arbitrary units that must be the same as the
13890     * units used by {@link #computeHorizontalScrollRange()} and
13891     * {@link #computeHorizontalScrollOffset()}.</p>
13892     *
13893     * <p>The default extent is the drawing width of this view.</p>
13894     *
13895     * @return the horizontal extent of the scrollbar's thumb
13896     *
13897     * @see #computeHorizontalScrollRange()
13898     * @see #computeHorizontalScrollOffset()
13899     * @see android.widget.ScrollBarDrawable
13900     */
13901    protected int computeHorizontalScrollExtent() {
13902        return getWidth();
13903    }
13904
13905    /**
13906     * <p>Compute the vertical range that the vertical scrollbar represents.</p>
13907     *
13908     * <p>The range is expressed in arbitrary units that must be the same as the
13909     * units used by {@link #computeVerticalScrollExtent()} and
13910     * {@link #computeVerticalScrollOffset()}.</p>
13911     *
13912     * @return the total vertical range represented by the vertical scrollbar
13913     *
13914     * <p>The default range is the drawing height of this view.</p>
13915     *
13916     * @see #computeVerticalScrollExtent()
13917     * @see #computeVerticalScrollOffset()
13918     * @see android.widget.ScrollBarDrawable
13919     */
13920    protected int computeVerticalScrollRange() {
13921        return getHeight();
13922    }
13923
13924    /**
13925     * <p>Compute the vertical offset of the vertical scrollbar's thumb
13926     * within the horizontal range. This value is used to compute the position
13927     * of the thumb within the scrollbar's track.</p>
13928     *
13929     * <p>The range is expressed in arbitrary units that must be the same as the
13930     * units used by {@link #computeVerticalScrollRange()} and
13931     * {@link #computeVerticalScrollExtent()}.</p>
13932     *
13933     * <p>The default offset is the scroll offset of this view.</p>
13934     *
13935     * @return the vertical offset of the scrollbar's thumb
13936     *
13937     * @see #computeVerticalScrollRange()
13938     * @see #computeVerticalScrollExtent()
13939     * @see android.widget.ScrollBarDrawable
13940     */
13941    protected int computeVerticalScrollOffset() {
13942        return mScrollY;
13943    }
13944
13945    /**
13946     * <p>Compute the vertical extent of the vertical scrollbar's thumb
13947     * within the vertical range. This value is used to compute the length
13948     * of the thumb within the scrollbar's track.</p>
13949     *
13950     * <p>The range is expressed in arbitrary units that must be the same as the
13951     * units used by {@link #computeVerticalScrollRange()} and
13952     * {@link #computeVerticalScrollOffset()}.</p>
13953     *
13954     * <p>The default extent is the drawing height of this view.</p>
13955     *
13956     * @return the vertical extent of the scrollbar's thumb
13957     *
13958     * @see #computeVerticalScrollRange()
13959     * @see #computeVerticalScrollOffset()
13960     * @see android.widget.ScrollBarDrawable
13961     */
13962    protected int computeVerticalScrollExtent() {
13963        return getHeight();
13964    }
13965
13966    /**
13967     * Check if this view can be scrolled horizontally in a certain direction.
13968     *
13969     * @param direction Negative to check scrolling left, positive to check scrolling right.
13970     * @return true if this view can be scrolled in the specified direction, false otherwise.
13971     */
13972    public boolean canScrollHorizontally(int direction) {
13973        final int offset = computeHorizontalScrollOffset();
13974        final int range = computeHorizontalScrollRange() - computeHorizontalScrollExtent();
13975        if (range == 0) return false;
13976        if (direction < 0) {
13977            return offset > 0;
13978        } else {
13979            return offset < range - 1;
13980        }
13981    }
13982
13983    /**
13984     * Check if this view can be scrolled vertically in a certain direction.
13985     *
13986     * @param direction Negative to check scrolling up, positive to check scrolling down.
13987     * @return true if this view can be scrolled in the specified direction, false otherwise.
13988     */
13989    public boolean canScrollVertically(int direction) {
13990        final int offset = computeVerticalScrollOffset();
13991        final int range = computeVerticalScrollRange() - computeVerticalScrollExtent();
13992        if (range == 0) return false;
13993        if (direction < 0) {
13994            return offset > 0;
13995        } else {
13996            return offset < range - 1;
13997        }
13998    }
13999
14000    void getScrollIndicatorBounds(@NonNull Rect out) {
14001        out.left = mScrollX;
14002        out.right = mScrollX + mRight - mLeft;
14003        out.top = mScrollY;
14004        out.bottom = mScrollY + mBottom - mTop;
14005    }
14006
14007    private void onDrawScrollIndicators(Canvas c) {
14008        if ((mPrivateFlags3 & SCROLL_INDICATORS_PFLAG3_MASK) == 0) {
14009            // No scroll indicators enabled.
14010            return;
14011        }
14012
14013        final Drawable dr = mScrollIndicatorDrawable;
14014        if (dr == null) {
14015            // Scroll indicators aren't supported here.
14016            return;
14017        }
14018
14019        final int h = dr.getIntrinsicHeight();
14020        final int w = dr.getIntrinsicWidth();
14021        final Rect rect = mAttachInfo.mTmpInvalRect;
14022        getScrollIndicatorBounds(rect);
14023
14024        if ((mPrivateFlags3 & PFLAG3_SCROLL_INDICATOR_TOP) != 0) {
14025            final boolean canScrollUp = canScrollVertically(-1);
14026            if (canScrollUp) {
14027                dr.setBounds(rect.left, rect.top, rect.right, rect.top + h);
14028                dr.draw(c);
14029            }
14030        }
14031
14032        if ((mPrivateFlags3 & PFLAG3_SCROLL_INDICATOR_BOTTOM) != 0) {
14033            final boolean canScrollDown = canScrollVertically(1);
14034            if (canScrollDown) {
14035                dr.setBounds(rect.left, rect.bottom - h, rect.right, rect.bottom);
14036                dr.draw(c);
14037            }
14038        }
14039
14040        final int leftRtl;
14041        final int rightRtl;
14042        if (getLayoutDirection() == LAYOUT_DIRECTION_RTL) {
14043            leftRtl = PFLAG3_SCROLL_INDICATOR_END;
14044            rightRtl = PFLAG3_SCROLL_INDICATOR_START;
14045        } else {
14046            leftRtl = PFLAG3_SCROLL_INDICATOR_START;
14047            rightRtl = PFLAG3_SCROLL_INDICATOR_END;
14048        }
14049
14050        final int leftMask = PFLAG3_SCROLL_INDICATOR_LEFT | leftRtl;
14051        if ((mPrivateFlags3 & leftMask) != 0) {
14052            final boolean canScrollLeft = canScrollHorizontally(-1);
14053            if (canScrollLeft) {
14054                dr.setBounds(rect.left, rect.top, rect.left + w, rect.bottom);
14055                dr.draw(c);
14056            }
14057        }
14058
14059        final int rightMask = PFLAG3_SCROLL_INDICATOR_RIGHT | rightRtl;
14060        if ((mPrivateFlags3 & rightMask) != 0) {
14061            final boolean canScrollRight = canScrollHorizontally(1);
14062            if (canScrollRight) {
14063                dr.setBounds(rect.right - w, rect.top, rect.right, rect.bottom);
14064                dr.draw(c);
14065            }
14066        }
14067    }
14068
14069    /**
14070     * <p>Request the drawing of the horizontal and the vertical scrollbar. The
14071     * scrollbars are painted only if they have been awakened first.</p>
14072     *
14073     * @param canvas the canvas on which to draw the scrollbars
14074     *
14075     * @see #awakenScrollBars(int)
14076     */
14077    protected final void onDrawScrollBars(Canvas canvas) {
14078        // scrollbars are drawn only when the animation is running
14079        final ScrollabilityCache cache = mScrollCache;
14080        if (cache != null) {
14081
14082            int state = cache.state;
14083
14084            if (state == ScrollabilityCache.OFF) {
14085                return;
14086            }
14087
14088            boolean invalidate = false;
14089
14090            if (state == ScrollabilityCache.FADING) {
14091                // We're fading -- get our fade interpolation
14092                if (cache.interpolatorValues == null) {
14093                    cache.interpolatorValues = new float[1];
14094                }
14095
14096                float[] values = cache.interpolatorValues;
14097
14098                // Stops the animation if we're done
14099                if (cache.scrollBarInterpolator.timeToValues(values) ==
14100                        Interpolator.Result.FREEZE_END) {
14101                    cache.state = ScrollabilityCache.OFF;
14102                } else {
14103                    cache.scrollBar.mutate().setAlpha(Math.round(values[0]));
14104                }
14105
14106                // This will make the scroll bars inval themselves after
14107                // drawing. We only want this when we're fading so that
14108                // we prevent excessive redraws
14109                invalidate = true;
14110            } else {
14111                // We're just on -- but we may have been fading before so
14112                // reset alpha
14113                cache.scrollBar.mutate().setAlpha(255);
14114            }
14115
14116
14117            final int viewFlags = mViewFlags;
14118
14119            final boolean drawHorizontalScrollBar =
14120                (viewFlags & SCROLLBARS_HORIZONTAL) == SCROLLBARS_HORIZONTAL;
14121            final boolean drawVerticalScrollBar =
14122                (viewFlags & SCROLLBARS_VERTICAL) == SCROLLBARS_VERTICAL
14123                && !isVerticalScrollBarHidden();
14124
14125            if (drawVerticalScrollBar || drawHorizontalScrollBar) {
14126                final int width = mRight - mLeft;
14127                final int height = mBottom - mTop;
14128
14129                final ScrollBarDrawable scrollBar = cache.scrollBar;
14130
14131                final int scrollX = mScrollX;
14132                final int scrollY = mScrollY;
14133                final int inside = (viewFlags & SCROLLBARS_OUTSIDE_MASK) == 0 ? ~0 : 0;
14134
14135                int left;
14136                int top;
14137                int right;
14138                int bottom;
14139
14140                if (drawHorizontalScrollBar) {
14141                    int size = scrollBar.getSize(false);
14142                    if (size <= 0) {
14143                        size = cache.scrollBarSize;
14144                    }
14145
14146                    scrollBar.setParameters(computeHorizontalScrollRange(),
14147                                            computeHorizontalScrollOffset(),
14148                                            computeHorizontalScrollExtent(), false);
14149                    final int verticalScrollBarGap = drawVerticalScrollBar ?
14150                            getVerticalScrollbarWidth() : 0;
14151                    top = scrollY + height - size - (mUserPaddingBottom & inside);
14152                    left = scrollX + (mPaddingLeft & inside);
14153                    right = scrollX + width - (mUserPaddingRight & inside) - verticalScrollBarGap;
14154                    bottom = top + size;
14155                    onDrawHorizontalScrollBar(canvas, scrollBar, left, top, right, bottom);
14156                    if (invalidate) {
14157                        invalidate(left, top, right, bottom);
14158                    }
14159                }
14160
14161                if (drawVerticalScrollBar) {
14162                    int size = scrollBar.getSize(true);
14163                    if (size <= 0) {
14164                        size = cache.scrollBarSize;
14165                    }
14166
14167                    scrollBar.setParameters(computeVerticalScrollRange(),
14168                                            computeVerticalScrollOffset(),
14169                                            computeVerticalScrollExtent(), true);
14170                    int verticalScrollbarPosition = mVerticalScrollbarPosition;
14171                    if (verticalScrollbarPosition == SCROLLBAR_POSITION_DEFAULT) {
14172                        verticalScrollbarPosition = isLayoutRtl() ?
14173                                SCROLLBAR_POSITION_LEFT : SCROLLBAR_POSITION_RIGHT;
14174                    }
14175                    switch (verticalScrollbarPosition) {
14176                        default:
14177                        case SCROLLBAR_POSITION_RIGHT:
14178                            left = scrollX + width - size - (mUserPaddingRight & inside);
14179                            break;
14180                        case SCROLLBAR_POSITION_LEFT:
14181                            left = scrollX + (mUserPaddingLeft & inside);
14182                            break;
14183                    }
14184                    top = scrollY + (mPaddingTop & inside);
14185                    right = left + size;
14186                    bottom = scrollY + height - (mUserPaddingBottom & inside);
14187                    onDrawVerticalScrollBar(canvas, scrollBar, left, top, right, bottom);
14188                    if (invalidate) {
14189                        invalidate(left, top, right, bottom);
14190                    }
14191                }
14192            }
14193        }
14194    }
14195
14196    /**
14197     * Override this if the vertical scrollbar needs to be hidden in a subclass, like when
14198     * FastScroller is visible.
14199     * @return whether to temporarily hide the vertical scrollbar
14200     * @hide
14201     */
14202    protected boolean isVerticalScrollBarHidden() {
14203        return false;
14204    }
14205
14206    /**
14207     * <p>Draw the horizontal scrollbar if
14208     * {@link #isHorizontalScrollBarEnabled()} returns true.</p>
14209     *
14210     * @param canvas the canvas on which to draw the scrollbar
14211     * @param scrollBar the scrollbar's drawable
14212     *
14213     * @see #isHorizontalScrollBarEnabled()
14214     * @see #computeHorizontalScrollRange()
14215     * @see #computeHorizontalScrollExtent()
14216     * @see #computeHorizontalScrollOffset()
14217     * @see android.widget.ScrollBarDrawable
14218     * @hide
14219     */
14220    protected void onDrawHorizontalScrollBar(Canvas canvas, Drawable scrollBar,
14221            int l, int t, int r, int b) {
14222        scrollBar.setBounds(l, t, r, b);
14223        scrollBar.draw(canvas);
14224    }
14225
14226    /**
14227     * <p>Draw the vertical scrollbar if {@link #isVerticalScrollBarEnabled()}
14228     * returns true.</p>
14229     *
14230     * @param canvas the canvas on which to draw the scrollbar
14231     * @param scrollBar the scrollbar's drawable
14232     *
14233     * @see #isVerticalScrollBarEnabled()
14234     * @see #computeVerticalScrollRange()
14235     * @see #computeVerticalScrollExtent()
14236     * @see #computeVerticalScrollOffset()
14237     * @see android.widget.ScrollBarDrawable
14238     * @hide
14239     */
14240    protected void onDrawVerticalScrollBar(Canvas canvas, Drawable scrollBar,
14241            int l, int t, int r, int b) {
14242        scrollBar.setBounds(l, t, r, b);
14243        scrollBar.draw(canvas);
14244    }
14245
14246    /**
14247     * Implement this to do your drawing.
14248     *
14249     * @param canvas the canvas on which the background will be drawn
14250     */
14251    protected void onDraw(Canvas canvas) {
14252    }
14253
14254    /*
14255     * Caller is responsible for calling requestLayout if necessary.
14256     * (This allows addViewInLayout to not request a new layout.)
14257     */
14258    void assignParent(ViewParent parent) {
14259        if (mParent == null) {
14260            mParent = parent;
14261        } else if (parent == null) {
14262            mParent = null;
14263        } else {
14264            throw new RuntimeException("view " + this + " being added, but"
14265                    + " it already has a parent");
14266        }
14267    }
14268
14269    /**
14270     * This is called when the view is attached to a window.  At this point it
14271     * has a Surface and will start drawing.  Note that this function is
14272     * guaranteed to be called before {@link #onDraw(android.graphics.Canvas)},
14273     * however it may be called any time before the first onDraw -- including
14274     * before or after {@link #onMeasure(int, int)}.
14275     *
14276     * @see #onDetachedFromWindow()
14277     */
14278    @CallSuper
14279    protected void onAttachedToWindow() {
14280        if ((mPrivateFlags & PFLAG_REQUEST_TRANSPARENT_REGIONS) != 0) {
14281            mParent.requestTransparentRegion(this);
14282        }
14283
14284        mPrivateFlags3 &= ~PFLAG3_IS_LAID_OUT;
14285
14286        jumpDrawablesToCurrentState();
14287
14288        resetSubtreeAccessibilityStateChanged();
14289
14290        // rebuild, since Outline not maintained while View is detached
14291        rebuildOutline();
14292
14293        if (isFocused()) {
14294            InputMethodManager imm = InputMethodManager.peekInstance();
14295            if (imm != null) {
14296                imm.focusIn(this);
14297            }
14298        }
14299    }
14300
14301    /**
14302     * Resolve all RTL related properties.
14303     *
14304     * @return true if resolution of RTL properties has been done
14305     *
14306     * @hide
14307     */
14308    public boolean resolveRtlPropertiesIfNeeded() {
14309        if (!needRtlPropertiesResolution()) return false;
14310
14311        // Order is important here: LayoutDirection MUST be resolved first
14312        if (!isLayoutDirectionResolved()) {
14313            resolveLayoutDirection();
14314            resolveLayoutParams();
14315        }
14316        // ... then we can resolve the others properties depending on the resolved LayoutDirection.
14317        if (!isTextDirectionResolved()) {
14318            resolveTextDirection();
14319        }
14320        if (!isTextAlignmentResolved()) {
14321            resolveTextAlignment();
14322        }
14323        // Should resolve Drawables before Padding because we need the layout direction of the
14324        // Drawable to correctly resolve Padding.
14325        if (!areDrawablesResolved()) {
14326            resolveDrawables();
14327        }
14328        if (!isPaddingResolved()) {
14329            resolvePadding();
14330        }
14331        onRtlPropertiesChanged(getLayoutDirection());
14332        return true;
14333    }
14334
14335    /**
14336     * Reset resolution of all RTL related properties.
14337     *
14338     * @hide
14339     */
14340    public void resetRtlProperties() {
14341        resetResolvedLayoutDirection();
14342        resetResolvedTextDirection();
14343        resetResolvedTextAlignment();
14344        resetResolvedPadding();
14345        resetResolvedDrawables();
14346    }
14347
14348    /**
14349     * @see #onScreenStateChanged(int)
14350     */
14351    void dispatchScreenStateChanged(int screenState) {
14352        onScreenStateChanged(screenState);
14353    }
14354
14355    /**
14356     * This method is called whenever the state of the screen this view is
14357     * attached to changes. A state change will usually occurs when the screen
14358     * turns on or off (whether it happens automatically or the user does it
14359     * manually.)
14360     *
14361     * @param screenState The new state of the screen. Can be either
14362     *                    {@link #SCREEN_STATE_ON} or {@link #SCREEN_STATE_OFF}
14363     */
14364    public void onScreenStateChanged(int screenState) {
14365    }
14366
14367    /**
14368     * Return true if the application tag in the AndroidManifest has set "supportRtl" to true
14369     */
14370    private boolean hasRtlSupport() {
14371        return mContext.getApplicationInfo().hasRtlSupport();
14372    }
14373
14374    /**
14375     * Return true if we are in RTL compatibility mode (either before Jelly Bean MR1 or
14376     * RTL not supported)
14377     */
14378    private boolean isRtlCompatibilityMode() {
14379        final int targetSdkVersion = getContext().getApplicationInfo().targetSdkVersion;
14380        return targetSdkVersion < JELLY_BEAN_MR1 || !hasRtlSupport();
14381    }
14382
14383    /**
14384     * @return true if RTL properties need resolution.
14385     *
14386     */
14387    private boolean needRtlPropertiesResolution() {
14388        return (mPrivateFlags2 & ALL_RTL_PROPERTIES_RESOLVED) != ALL_RTL_PROPERTIES_RESOLVED;
14389    }
14390
14391    /**
14392     * Called when any RTL property (layout direction or text direction or text alignment) has
14393     * been changed.
14394     *
14395     * Subclasses need to override this method to take care of cached information that depends on the
14396     * resolved layout direction, or to inform child views that inherit their layout direction.
14397     *
14398     * The default implementation does nothing.
14399     *
14400     * @param layoutDirection the direction of the layout
14401     *
14402     * @see #LAYOUT_DIRECTION_LTR
14403     * @see #LAYOUT_DIRECTION_RTL
14404     */
14405    public void onRtlPropertiesChanged(@ResolvedLayoutDir int layoutDirection) {
14406    }
14407
14408    /**
14409     * Resolve and cache the layout direction. LTR is set initially. This is implicitly supposing
14410     * that the parent directionality can and will be resolved before its children.
14411     *
14412     * @return true if resolution has been done, false otherwise.
14413     *
14414     * @hide
14415     */
14416    public boolean resolveLayoutDirection() {
14417        // Clear any previous layout direction resolution
14418        mPrivateFlags2 &= ~PFLAG2_LAYOUT_DIRECTION_RESOLVED_MASK;
14419
14420        if (hasRtlSupport()) {
14421            // Set resolved depending on layout direction
14422            switch ((mPrivateFlags2 & PFLAG2_LAYOUT_DIRECTION_MASK) >>
14423                    PFLAG2_LAYOUT_DIRECTION_MASK_SHIFT) {
14424                case LAYOUT_DIRECTION_INHERIT:
14425                    // We cannot resolve yet. LTR is by default and let the resolution happen again
14426                    // later to get the correct resolved value
14427                    if (!canResolveLayoutDirection()) return false;
14428
14429                    // Parent has not yet resolved, LTR is still the default
14430                    try {
14431                        if (!mParent.isLayoutDirectionResolved()) return false;
14432
14433                        if (mParent.getLayoutDirection() == LAYOUT_DIRECTION_RTL) {
14434                            mPrivateFlags2 |= PFLAG2_LAYOUT_DIRECTION_RESOLVED_RTL;
14435                        }
14436                    } catch (AbstractMethodError e) {
14437                        Log.e(VIEW_LOG_TAG, mParent.getClass().getSimpleName() +
14438                                " does not fully implement ViewParent", e);
14439                    }
14440                    break;
14441                case LAYOUT_DIRECTION_RTL:
14442                    mPrivateFlags2 |= PFLAG2_LAYOUT_DIRECTION_RESOLVED_RTL;
14443                    break;
14444                case LAYOUT_DIRECTION_LOCALE:
14445                    if((LAYOUT_DIRECTION_RTL ==
14446                            TextUtils.getLayoutDirectionFromLocale(Locale.getDefault()))) {
14447                        mPrivateFlags2 |= PFLAG2_LAYOUT_DIRECTION_RESOLVED_RTL;
14448                    }
14449                    break;
14450                default:
14451                    // Nothing to do, LTR by default
14452            }
14453        }
14454
14455        // Set to resolved
14456        mPrivateFlags2 |= PFLAG2_LAYOUT_DIRECTION_RESOLVED;
14457        return true;
14458    }
14459
14460    /**
14461     * Check if layout direction resolution can be done.
14462     *
14463     * @return true if layout direction resolution can be done otherwise return false.
14464     */
14465    public boolean canResolveLayoutDirection() {
14466        switch (getRawLayoutDirection()) {
14467            case LAYOUT_DIRECTION_INHERIT:
14468                if (mParent != null) {
14469                    try {
14470                        return mParent.canResolveLayoutDirection();
14471                    } catch (AbstractMethodError e) {
14472                        Log.e(VIEW_LOG_TAG, mParent.getClass().getSimpleName() +
14473                                " does not fully implement ViewParent", e);
14474                    }
14475                }
14476                return false;
14477
14478            default:
14479                return true;
14480        }
14481    }
14482
14483    /**
14484     * Reset the resolved layout direction. Layout direction will be resolved during a call to
14485     * {@link #onMeasure(int, int)}.
14486     *
14487     * @hide
14488     */
14489    public void resetResolvedLayoutDirection() {
14490        // Reset the current resolved bits
14491        mPrivateFlags2 &= ~PFLAG2_LAYOUT_DIRECTION_RESOLVED_MASK;
14492    }
14493
14494    /**
14495     * @return true if the layout direction is inherited.
14496     *
14497     * @hide
14498     */
14499    public boolean isLayoutDirectionInherited() {
14500        return (getRawLayoutDirection() == LAYOUT_DIRECTION_INHERIT);
14501    }
14502
14503    /**
14504     * @return true if layout direction has been resolved.
14505     */
14506    public boolean isLayoutDirectionResolved() {
14507        return (mPrivateFlags2 & PFLAG2_LAYOUT_DIRECTION_RESOLVED) == PFLAG2_LAYOUT_DIRECTION_RESOLVED;
14508    }
14509
14510    /**
14511     * Return if padding has been resolved
14512     *
14513     * @hide
14514     */
14515    boolean isPaddingResolved() {
14516        return (mPrivateFlags2 & PFLAG2_PADDING_RESOLVED) == PFLAG2_PADDING_RESOLVED;
14517    }
14518
14519    /**
14520     * Resolves padding depending on layout direction, if applicable, and
14521     * recomputes internal padding values to adjust for scroll bars.
14522     *
14523     * @hide
14524     */
14525    public void resolvePadding() {
14526        final int resolvedLayoutDirection = getLayoutDirection();
14527
14528        if (!isRtlCompatibilityMode()) {
14529            // Post Jelly Bean MR1 case: we need to take the resolved layout direction into account.
14530            // If start / end padding are defined, they will be resolved (hence overriding) to
14531            // left / right or right / left depending on the resolved layout direction.
14532            // If start / end padding are not defined, use the left / right ones.
14533            if (mBackground != null && (!mLeftPaddingDefined || !mRightPaddingDefined)) {
14534                Rect padding = sThreadLocal.get();
14535                if (padding == null) {
14536                    padding = new Rect();
14537                    sThreadLocal.set(padding);
14538                }
14539                mBackground.getPadding(padding);
14540                if (!mLeftPaddingDefined) {
14541                    mUserPaddingLeftInitial = padding.left;
14542                }
14543                if (!mRightPaddingDefined) {
14544                    mUserPaddingRightInitial = padding.right;
14545                }
14546            }
14547            switch (resolvedLayoutDirection) {
14548                case LAYOUT_DIRECTION_RTL:
14549                    if (mUserPaddingStart != UNDEFINED_PADDING) {
14550                        mUserPaddingRight = mUserPaddingStart;
14551                    } else {
14552                        mUserPaddingRight = mUserPaddingRightInitial;
14553                    }
14554                    if (mUserPaddingEnd != UNDEFINED_PADDING) {
14555                        mUserPaddingLeft = mUserPaddingEnd;
14556                    } else {
14557                        mUserPaddingLeft = mUserPaddingLeftInitial;
14558                    }
14559                    break;
14560                case LAYOUT_DIRECTION_LTR:
14561                default:
14562                    if (mUserPaddingStart != UNDEFINED_PADDING) {
14563                        mUserPaddingLeft = mUserPaddingStart;
14564                    } else {
14565                        mUserPaddingLeft = mUserPaddingLeftInitial;
14566                    }
14567                    if (mUserPaddingEnd != UNDEFINED_PADDING) {
14568                        mUserPaddingRight = mUserPaddingEnd;
14569                    } else {
14570                        mUserPaddingRight = mUserPaddingRightInitial;
14571                    }
14572            }
14573
14574            mUserPaddingBottom = (mUserPaddingBottom >= 0) ? mUserPaddingBottom : mPaddingBottom;
14575        }
14576
14577        internalSetPadding(mUserPaddingLeft, mPaddingTop, mUserPaddingRight, mUserPaddingBottom);
14578        onRtlPropertiesChanged(resolvedLayoutDirection);
14579
14580        mPrivateFlags2 |= PFLAG2_PADDING_RESOLVED;
14581    }
14582
14583    /**
14584     * Reset the resolved layout direction.
14585     *
14586     * @hide
14587     */
14588    public void resetResolvedPadding() {
14589        resetResolvedPaddingInternal();
14590    }
14591
14592    /**
14593     * Used when we only want to reset *this* view's padding and not trigger overrides
14594     * in ViewGroup that reset children too.
14595     */
14596    void resetResolvedPaddingInternal() {
14597        mPrivateFlags2 &= ~PFLAG2_PADDING_RESOLVED;
14598    }
14599
14600    /**
14601     * This is called when the view is detached from a window.  At this point it
14602     * no longer has a surface for drawing.
14603     *
14604     * @see #onAttachedToWindow()
14605     */
14606    @CallSuper
14607    protected void onDetachedFromWindow() {
14608    }
14609
14610    /**
14611     * This is a framework-internal mirror of onDetachedFromWindow() that's called
14612     * after onDetachedFromWindow().
14613     *
14614     * If you override this you *MUST* call super.onDetachedFromWindowInternal()!
14615     * The super method should be called at the end of the overridden method to ensure
14616     * subclasses are destroyed first
14617     *
14618     * @hide
14619     */
14620    @CallSuper
14621    protected void onDetachedFromWindowInternal() {
14622        mPrivateFlags &= ~PFLAG_CANCEL_NEXT_UP_EVENT;
14623        mPrivateFlags3 &= ~PFLAG3_IS_LAID_OUT;
14624
14625        removeUnsetPressCallback();
14626        removeLongPressCallback();
14627        removePerformClickCallback();
14628        removeSendViewScrolledAccessibilityEventCallback();
14629        stopNestedScroll();
14630
14631        // Anything that started animating right before detach should already
14632        // be in its final state when re-attached.
14633        jumpDrawablesToCurrentState();
14634
14635        destroyDrawingCache();
14636
14637        cleanupDraw();
14638        mCurrentAnimation = null;
14639    }
14640
14641    private void cleanupDraw() {
14642        resetDisplayList();
14643        if (mAttachInfo != null) {
14644            mAttachInfo.mViewRootImpl.cancelInvalidate(this);
14645        }
14646    }
14647
14648    void invalidateInheritedLayoutMode(int layoutModeOfRoot) {
14649    }
14650
14651    /**
14652     * @return The number of times this view has been attached to a window
14653     */
14654    protected int getWindowAttachCount() {
14655        return mWindowAttachCount;
14656    }
14657
14658    /**
14659     * Retrieve a unique token identifying the window this view is attached to.
14660     * @return Return the window's token for use in
14661     * {@link WindowManager.LayoutParams#token WindowManager.LayoutParams.token}.
14662     */
14663    public IBinder getWindowToken() {
14664        return mAttachInfo != null ? mAttachInfo.mWindowToken : null;
14665    }
14666
14667    /**
14668     * Retrieve the {@link WindowId} for the window this view is
14669     * currently attached to.
14670     */
14671    public WindowId getWindowId() {
14672        if (mAttachInfo == null) {
14673            return null;
14674        }
14675        if (mAttachInfo.mWindowId == null) {
14676            try {
14677                mAttachInfo.mIWindowId = mAttachInfo.mSession.getWindowId(
14678                        mAttachInfo.mWindowToken);
14679                mAttachInfo.mWindowId = new WindowId(
14680                        mAttachInfo.mIWindowId);
14681            } catch (RemoteException e) {
14682            }
14683        }
14684        return mAttachInfo.mWindowId;
14685    }
14686
14687    /**
14688     * Retrieve a unique token identifying the top-level "real" window of
14689     * the window that this view is attached to.  That is, this is like
14690     * {@link #getWindowToken}, except if the window this view in is a panel
14691     * window (attached to another containing window), then the token of
14692     * the containing window is returned instead.
14693     *
14694     * @return Returns the associated window token, either
14695     * {@link #getWindowToken()} or the containing window's token.
14696     */
14697    public IBinder getApplicationWindowToken() {
14698        AttachInfo ai = mAttachInfo;
14699        if (ai != null) {
14700            IBinder appWindowToken = ai.mPanelParentWindowToken;
14701            if (appWindowToken == null) {
14702                appWindowToken = ai.mWindowToken;
14703            }
14704            return appWindowToken;
14705        }
14706        return null;
14707    }
14708
14709    /**
14710     * Gets the logical display to which the view's window has been attached.
14711     *
14712     * @return The logical display, or null if the view is not currently attached to a window.
14713     */
14714    public Display getDisplay() {
14715        return mAttachInfo != null ? mAttachInfo.mDisplay : null;
14716    }
14717
14718    /**
14719     * Retrieve private session object this view hierarchy is using to
14720     * communicate with the window manager.
14721     * @return the session object to communicate with the window manager
14722     */
14723    /*package*/ IWindowSession getWindowSession() {
14724        return mAttachInfo != null ? mAttachInfo.mSession : null;
14725    }
14726
14727    /**
14728     * Return the visibility value of the least visible component passed.
14729     */
14730    int combineVisibility(int vis1, int vis2) {
14731        // This works because VISIBLE < INVISIBLE < GONE.
14732        return Math.max(vis1, vis2);
14733    }
14734
14735    /**
14736     * @param info the {@link android.view.View.AttachInfo} to associated with
14737     *        this view
14738     */
14739    void dispatchAttachedToWindow(AttachInfo info, int visibility) {
14740        mAttachInfo = info;
14741        if (mOverlay != null) {
14742            mOverlay.getOverlayView().dispatchAttachedToWindow(info, visibility);
14743        }
14744        mWindowAttachCount++;
14745        // We will need to evaluate the drawable state at least once.
14746        mPrivateFlags |= PFLAG_DRAWABLE_STATE_DIRTY;
14747        if (mFloatingTreeObserver != null) {
14748            info.mTreeObserver.merge(mFloatingTreeObserver);
14749            mFloatingTreeObserver = null;
14750        }
14751        if ((mPrivateFlags&PFLAG_SCROLL_CONTAINER) != 0) {
14752            mAttachInfo.mScrollContainers.add(this);
14753            mPrivateFlags |= PFLAG_SCROLL_CONTAINER_ADDED;
14754        }
14755        // Transfer all pending runnables.
14756        if (mRunQueue != null) {
14757            mRunQueue.executeActions(info.mHandler);
14758            mRunQueue = null;
14759        }
14760        performCollectViewAttributes(mAttachInfo, visibility);
14761        onAttachedToWindow();
14762
14763        ListenerInfo li = mListenerInfo;
14764        final CopyOnWriteArrayList<OnAttachStateChangeListener> listeners =
14765                li != null ? li.mOnAttachStateChangeListeners : null;
14766        if (listeners != null && listeners.size() > 0) {
14767            // NOTE: because of the use of CopyOnWriteArrayList, we *must* use an iterator to
14768            // perform the dispatching. The iterator is a safe guard against listeners that
14769            // could mutate the list by calling the various add/remove methods. This prevents
14770            // the array from being modified while we iterate it.
14771            for (OnAttachStateChangeListener listener : listeners) {
14772                listener.onViewAttachedToWindow(this);
14773            }
14774        }
14775
14776        int vis = info.mWindowVisibility;
14777        if (vis != GONE) {
14778            onWindowVisibilityChanged(vis);
14779        }
14780
14781        // Send onVisibilityChanged directly instead of dispatchVisibilityChanged.
14782        // As all views in the subtree will already receive dispatchAttachedToWindow
14783        // traversing the subtree again here is not desired.
14784        onVisibilityChanged(this, visibility);
14785
14786        if ((mPrivateFlags&PFLAG_DRAWABLE_STATE_DIRTY) != 0) {
14787            // If nobody has evaluated the drawable state yet, then do it now.
14788            refreshDrawableState();
14789        }
14790        needGlobalAttributesUpdate(false);
14791    }
14792
14793    void dispatchDetachedFromWindow() {
14794        AttachInfo info = mAttachInfo;
14795        if (info != null) {
14796            int vis = info.mWindowVisibility;
14797            if (vis != GONE) {
14798                onWindowVisibilityChanged(GONE);
14799            }
14800        }
14801
14802        onDetachedFromWindow();
14803        onDetachedFromWindowInternal();
14804
14805        InputMethodManager imm = InputMethodManager.peekInstance();
14806        if (imm != null) {
14807            imm.onViewDetachedFromWindow(this);
14808        }
14809
14810        ListenerInfo li = mListenerInfo;
14811        final CopyOnWriteArrayList<OnAttachStateChangeListener> listeners =
14812                li != null ? li.mOnAttachStateChangeListeners : null;
14813        if (listeners != null && listeners.size() > 0) {
14814            // NOTE: because of the use of CopyOnWriteArrayList, we *must* use an iterator to
14815            // perform the dispatching. The iterator is a safe guard against listeners that
14816            // could mutate the list by calling the various add/remove methods. This prevents
14817            // the array from being modified while we iterate it.
14818            for (OnAttachStateChangeListener listener : listeners) {
14819                listener.onViewDetachedFromWindow(this);
14820            }
14821        }
14822
14823        if ((mPrivateFlags & PFLAG_SCROLL_CONTAINER_ADDED) != 0) {
14824            mAttachInfo.mScrollContainers.remove(this);
14825            mPrivateFlags &= ~PFLAG_SCROLL_CONTAINER_ADDED;
14826        }
14827
14828        mAttachInfo = null;
14829        if (mOverlay != null) {
14830            mOverlay.getOverlayView().dispatchDetachedFromWindow();
14831        }
14832    }
14833
14834    /**
14835     * Cancel any deferred high-level input events that were previously posted to the event queue.
14836     *
14837     * <p>Many views post high-level events such as click handlers to the event queue
14838     * to run deferred in order to preserve a desired user experience - clearing visible
14839     * pressed states before executing, etc. This method will abort any events of this nature
14840     * that are currently in flight.</p>
14841     *
14842     * <p>Custom views that generate their own high-level deferred input events should override
14843     * {@link #onCancelPendingInputEvents()} and remove those pending events from the queue.</p>
14844     *
14845     * <p>This will also cancel pending input events for any child views.</p>
14846     *
14847     * <p>Note that this may not be sufficient as a debouncing strategy for clicks in all cases.
14848     * This will not impact newer events posted after this call that may occur as a result of
14849     * lower-level input events still waiting in the queue. If you are trying to prevent
14850     * double-submitted  events for the duration of some sort of asynchronous transaction
14851     * you should also take other steps to protect against unexpected double inputs e.g. calling
14852     * {@link #setEnabled(boolean) setEnabled(false)} and re-enabling the view when
14853     * the transaction completes, tracking already submitted transaction IDs, etc.</p>
14854     */
14855    public final void cancelPendingInputEvents() {
14856        dispatchCancelPendingInputEvents();
14857    }
14858
14859    /**
14860     * Called by {@link #cancelPendingInputEvents()} to cancel input events in flight.
14861     * Overridden by ViewGroup to dispatch. Package scoped to prevent app-side meddling.
14862     */
14863    void dispatchCancelPendingInputEvents() {
14864        mPrivateFlags3 &= ~PFLAG3_CALLED_SUPER;
14865        onCancelPendingInputEvents();
14866        if ((mPrivateFlags3 & PFLAG3_CALLED_SUPER) != PFLAG3_CALLED_SUPER) {
14867            throw new SuperNotCalledException("View " + getClass().getSimpleName() +
14868                    " did not call through to super.onCancelPendingInputEvents()");
14869        }
14870    }
14871
14872    /**
14873     * Called as the result of a call to {@link #cancelPendingInputEvents()} on this view or
14874     * a parent view.
14875     *
14876     * <p>This method is responsible for removing any pending high-level input events that were
14877     * posted to the event queue to run later. Custom view classes that post their own deferred
14878     * high-level events via {@link #post(Runnable)}, {@link #postDelayed(Runnable, long)} or
14879     * {@link android.os.Handler} should override this method, call
14880     * <code>super.onCancelPendingInputEvents()</code> and remove those callbacks as appropriate.
14881     * </p>
14882     */
14883    public void onCancelPendingInputEvents() {
14884        removePerformClickCallback();
14885        cancelLongPress();
14886        mPrivateFlags3 |= PFLAG3_CALLED_SUPER;
14887    }
14888
14889    /**
14890     * Store this view hierarchy's frozen state into the given container.
14891     *
14892     * @param container The SparseArray in which to save the view's state.
14893     *
14894     * @see #restoreHierarchyState(android.util.SparseArray)
14895     * @see #dispatchSaveInstanceState(android.util.SparseArray)
14896     * @see #onSaveInstanceState()
14897     */
14898    public void saveHierarchyState(SparseArray<Parcelable> container) {
14899        dispatchSaveInstanceState(container);
14900    }
14901
14902    /**
14903     * Called by {@link #saveHierarchyState(android.util.SparseArray)} to store the state for
14904     * this view and its children. May be overridden to modify how freezing happens to a
14905     * view's children; for example, some views may want to not store state for their children.
14906     *
14907     * @param container The SparseArray in which to save the view's state.
14908     *
14909     * @see #dispatchRestoreInstanceState(android.util.SparseArray)
14910     * @see #saveHierarchyState(android.util.SparseArray)
14911     * @see #onSaveInstanceState()
14912     */
14913    protected void dispatchSaveInstanceState(SparseArray<Parcelable> container) {
14914        if (mID != NO_ID && (mViewFlags & SAVE_DISABLED_MASK) == 0) {
14915            mPrivateFlags &= ~PFLAG_SAVE_STATE_CALLED;
14916            Parcelable state = onSaveInstanceState();
14917            if ((mPrivateFlags & PFLAG_SAVE_STATE_CALLED) == 0) {
14918                throw new IllegalStateException(
14919                        "Derived class did not call super.onSaveInstanceState()");
14920            }
14921            if (state != null) {
14922                // Log.i("View", "Freezing #" + Integer.toHexString(mID)
14923                // + ": " + state);
14924                container.put(mID, state);
14925            }
14926        }
14927    }
14928
14929    /**
14930     * Hook allowing a view to generate a representation of its internal state
14931     * that can later be used to create a new instance with that same state.
14932     * This state should only contain information that is not persistent or can
14933     * not be reconstructed later. For example, you will never store your
14934     * current position on screen because that will be computed again when a
14935     * new instance of the view is placed in its view hierarchy.
14936     * <p>
14937     * Some examples of things you may store here: the current cursor position
14938     * in a text view (but usually not the text itself since that is stored in a
14939     * content provider or other persistent storage), the currently selected
14940     * item in a list view.
14941     *
14942     * @return Returns a Parcelable object containing the view's current dynamic
14943     *         state, or null if there is nothing interesting to save. The
14944     *         default implementation returns null.
14945     * @see #onRestoreInstanceState(android.os.Parcelable)
14946     * @see #saveHierarchyState(android.util.SparseArray)
14947     * @see #dispatchSaveInstanceState(android.util.SparseArray)
14948     * @see #setSaveEnabled(boolean)
14949     */
14950    @CallSuper
14951    protected Parcelable onSaveInstanceState() {
14952        mPrivateFlags |= PFLAG_SAVE_STATE_CALLED;
14953        if (mStartActivityRequestWho != null) {
14954            BaseSavedState state = new BaseSavedState(AbsSavedState.EMPTY_STATE);
14955            state.mStartActivityRequestWhoSaved = mStartActivityRequestWho;
14956            return state;
14957        }
14958        return BaseSavedState.EMPTY_STATE;
14959    }
14960
14961    /**
14962     * Restore this view hierarchy's frozen state from the given container.
14963     *
14964     * @param container The SparseArray which holds previously frozen states.
14965     *
14966     * @see #saveHierarchyState(android.util.SparseArray)
14967     * @see #dispatchRestoreInstanceState(android.util.SparseArray)
14968     * @see #onRestoreInstanceState(android.os.Parcelable)
14969     */
14970    public void restoreHierarchyState(SparseArray<Parcelable> container) {
14971        dispatchRestoreInstanceState(container);
14972    }
14973
14974    /**
14975     * Called by {@link #restoreHierarchyState(android.util.SparseArray)} to retrieve the
14976     * state for this view and its children. May be overridden to modify how restoring
14977     * happens to a view's children; for example, some views may want to not store state
14978     * for their children.
14979     *
14980     * @param container The SparseArray which holds previously saved state.
14981     *
14982     * @see #dispatchSaveInstanceState(android.util.SparseArray)
14983     * @see #restoreHierarchyState(android.util.SparseArray)
14984     * @see #onRestoreInstanceState(android.os.Parcelable)
14985     */
14986    protected void dispatchRestoreInstanceState(SparseArray<Parcelable> container) {
14987        if (mID != NO_ID) {
14988            Parcelable state = container.get(mID);
14989            if (state != null) {
14990                // Log.i("View", "Restoreing #" + Integer.toHexString(mID)
14991                // + ": " + state);
14992                mPrivateFlags &= ~PFLAG_SAVE_STATE_CALLED;
14993                onRestoreInstanceState(state);
14994                if ((mPrivateFlags & PFLAG_SAVE_STATE_CALLED) == 0) {
14995                    throw new IllegalStateException(
14996                            "Derived class did not call super.onRestoreInstanceState()");
14997                }
14998            }
14999        }
15000    }
15001
15002    /**
15003     * Hook allowing a view to re-apply a representation of its internal state that had previously
15004     * been generated by {@link #onSaveInstanceState}. This function will never be called with a
15005     * null state.
15006     *
15007     * @param state The frozen state that had previously been returned by
15008     *        {@link #onSaveInstanceState}.
15009     *
15010     * @see #onSaveInstanceState()
15011     * @see #restoreHierarchyState(android.util.SparseArray)
15012     * @see #dispatchRestoreInstanceState(android.util.SparseArray)
15013     */
15014    @CallSuper
15015    protected void onRestoreInstanceState(Parcelable state) {
15016        mPrivateFlags |= PFLAG_SAVE_STATE_CALLED;
15017        if (state != null && !(state instanceof AbsSavedState)) {
15018            throw new IllegalArgumentException("Wrong state class, expecting View State but "
15019                    + "received " + state.getClass().toString() + " instead. This usually happens "
15020                    + "when two views of different type have the same id in the same hierarchy. "
15021                    + "This view's id is " + ViewDebug.resolveId(mContext, getId()) + ". Make sure "
15022                    + "other views do not use the same id.");
15023        }
15024        if (state != null && state instanceof BaseSavedState) {
15025            mStartActivityRequestWho = ((BaseSavedState) state).mStartActivityRequestWhoSaved;
15026        }
15027    }
15028
15029    /**
15030     * <p>Return the time at which the drawing of the view hierarchy started.</p>
15031     *
15032     * @return the drawing start time in milliseconds
15033     */
15034    public long getDrawingTime() {
15035        return mAttachInfo != null ? mAttachInfo.mDrawingTime : 0;
15036    }
15037
15038    /**
15039     * <p>Enables or disables the duplication of the parent's state into this view. When
15040     * duplication is enabled, this view gets its drawable state from its parent rather
15041     * than from its own internal properties.</p>
15042     *
15043     * <p>Note: in the current implementation, setting this property to true after the
15044     * view was added to a ViewGroup might have no effect at all. This property should
15045     * always be used from XML or set to true before adding this view to a ViewGroup.</p>
15046     *
15047     * <p>Note: if this view's parent addStateFromChildren property is enabled and this
15048     * property is enabled, an exception will be thrown.</p>
15049     *
15050     * <p>Note: if the child view uses and updates additional states which are unknown to the
15051     * parent, these states should not be affected by this method.</p>
15052     *
15053     * @param enabled True to enable duplication of the parent's drawable state, false
15054     *                to disable it.
15055     *
15056     * @see #getDrawableState()
15057     * @see #isDuplicateParentStateEnabled()
15058     */
15059    public void setDuplicateParentStateEnabled(boolean enabled) {
15060        setFlags(enabled ? DUPLICATE_PARENT_STATE : 0, DUPLICATE_PARENT_STATE);
15061    }
15062
15063    /**
15064     * <p>Indicates whether this duplicates its drawable state from its parent.</p>
15065     *
15066     * @return True if this view's drawable state is duplicated from the parent,
15067     *         false otherwise
15068     *
15069     * @see #getDrawableState()
15070     * @see #setDuplicateParentStateEnabled(boolean)
15071     */
15072    public boolean isDuplicateParentStateEnabled() {
15073        return (mViewFlags & DUPLICATE_PARENT_STATE) == DUPLICATE_PARENT_STATE;
15074    }
15075
15076    /**
15077     * <p>Specifies the type of layer backing this view. The layer can be
15078     * {@link #LAYER_TYPE_NONE}, {@link #LAYER_TYPE_SOFTWARE} or
15079     * {@link #LAYER_TYPE_HARDWARE}.</p>
15080     *
15081     * <p>A layer is associated with an optional {@link android.graphics.Paint}
15082     * instance that controls how the layer is composed on screen. The following
15083     * properties of the paint are taken into account when composing the layer:</p>
15084     * <ul>
15085     * <li>{@link android.graphics.Paint#getAlpha() Translucency (alpha)}</li>
15086     * <li>{@link android.graphics.Paint#getXfermode() Blending mode}</li>
15087     * <li>{@link android.graphics.Paint#getColorFilter() Color filter}</li>
15088     * </ul>
15089     *
15090     * <p>If this view has an alpha value set to < 1.0 by calling
15091     * {@link #setAlpha(float)}, the alpha value of the layer's paint is superseded
15092     * by this view's alpha value.</p>
15093     *
15094     * <p>Refer to the documentation of {@link #LAYER_TYPE_NONE},
15095     * {@link #LAYER_TYPE_SOFTWARE} and {@link #LAYER_TYPE_HARDWARE}
15096     * for more information on when and how to use layers.</p>
15097     *
15098     * @param layerType The type of layer to use with this view, must be one of
15099     *        {@link #LAYER_TYPE_NONE}, {@link #LAYER_TYPE_SOFTWARE} or
15100     *        {@link #LAYER_TYPE_HARDWARE}
15101     * @param paint The paint used to compose the layer. This argument is optional
15102     *        and can be null. It is ignored when the layer type is
15103     *        {@link #LAYER_TYPE_NONE}
15104     *
15105     * @see #getLayerType()
15106     * @see #LAYER_TYPE_NONE
15107     * @see #LAYER_TYPE_SOFTWARE
15108     * @see #LAYER_TYPE_HARDWARE
15109     * @see #setAlpha(float)
15110     *
15111     * @attr ref android.R.styleable#View_layerType
15112     */
15113    public void setLayerType(int layerType, Paint paint) {
15114        if (layerType < LAYER_TYPE_NONE || layerType > LAYER_TYPE_HARDWARE) {
15115            throw new IllegalArgumentException("Layer type can only be one of: LAYER_TYPE_NONE, "
15116                    + "LAYER_TYPE_SOFTWARE or LAYER_TYPE_HARDWARE");
15117        }
15118
15119        boolean typeChanged = mRenderNode.setLayerType(layerType);
15120
15121        if (!typeChanged) {
15122            setLayerPaint(paint);
15123            return;
15124        }
15125
15126        // Destroy any previous software drawing cache if needed
15127        if (mLayerType == LAYER_TYPE_SOFTWARE) {
15128            destroyDrawingCache();
15129        }
15130
15131        mLayerType = layerType;
15132        final boolean layerDisabled = (mLayerType == LAYER_TYPE_NONE);
15133        mLayerPaint = layerDisabled ? null : (paint == null ? new Paint() : paint);
15134        mRenderNode.setLayerPaint(mLayerPaint);
15135
15136        // draw() behaves differently if we are on a layer, so we need to
15137        // invalidate() here
15138        invalidateParentCaches();
15139        invalidate(true);
15140    }
15141
15142    /**
15143     * Updates the {@link Paint} object used with the current layer (used only if the current
15144     * layer type is not set to {@link #LAYER_TYPE_NONE}). Changed properties of the Paint
15145     * provided to {@link #setLayerType(int, android.graphics.Paint)} will be used the next time
15146     * the View is redrawn, but {@link #setLayerPaint(android.graphics.Paint)} must be called to
15147     * ensure that the view gets redrawn immediately.
15148     *
15149     * <p>A layer is associated with an optional {@link android.graphics.Paint}
15150     * instance that controls how the layer is composed on screen. The following
15151     * properties of the paint are taken into account when composing the layer:</p>
15152     * <ul>
15153     * <li>{@link android.graphics.Paint#getAlpha() Translucency (alpha)}</li>
15154     * <li>{@link android.graphics.Paint#getXfermode() Blending mode}</li>
15155     * <li>{@link android.graphics.Paint#getColorFilter() Color filter}</li>
15156     * </ul>
15157     *
15158     * <p>If this view has an alpha value set to < 1.0 by calling {@link #setAlpha(float)}, the
15159     * alpha value of the layer's paint is superseded by this view's alpha value.</p>
15160     *
15161     * @param paint The paint used to compose the layer. This argument is optional
15162     *        and can be null. It is ignored when the layer type is
15163     *        {@link #LAYER_TYPE_NONE}
15164     *
15165     * @see #setLayerType(int, android.graphics.Paint)
15166     */
15167    public void setLayerPaint(Paint paint) {
15168        int layerType = getLayerType();
15169        if (layerType != LAYER_TYPE_NONE) {
15170            mLayerPaint = paint == null ? new Paint() : paint;
15171            if (layerType == LAYER_TYPE_HARDWARE) {
15172                if (mRenderNode.setLayerPaint(mLayerPaint)) {
15173                    invalidateViewProperty(false, false);
15174                }
15175            } else {
15176                invalidate();
15177            }
15178        }
15179    }
15180
15181    /**
15182     * Indicates what type of layer is currently associated with this view. By default
15183     * a view does not have a layer, and the layer type is {@link #LAYER_TYPE_NONE}.
15184     * Refer to the documentation of {@link #setLayerType(int, android.graphics.Paint)}
15185     * for more information on the different types of layers.
15186     *
15187     * @return {@link #LAYER_TYPE_NONE}, {@link #LAYER_TYPE_SOFTWARE} or
15188     *         {@link #LAYER_TYPE_HARDWARE}
15189     *
15190     * @see #setLayerType(int, android.graphics.Paint)
15191     * @see #buildLayer()
15192     * @see #LAYER_TYPE_NONE
15193     * @see #LAYER_TYPE_SOFTWARE
15194     * @see #LAYER_TYPE_HARDWARE
15195     */
15196    public int getLayerType() {
15197        return mLayerType;
15198    }
15199
15200    /**
15201     * Forces this view's layer to be created and this view to be rendered
15202     * into its layer. If this view's layer type is set to {@link #LAYER_TYPE_NONE},
15203     * invoking this method will have no effect.
15204     *
15205     * This method can for instance be used to render a view into its layer before
15206     * starting an animation. If this view is complex, rendering into the layer
15207     * before starting the animation will avoid skipping frames.
15208     *
15209     * @throws IllegalStateException If this view is not attached to a window
15210     *
15211     * @see #setLayerType(int, android.graphics.Paint)
15212     */
15213    public void buildLayer() {
15214        if (mLayerType == LAYER_TYPE_NONE) return;
15215
15216        final AttachInfo attachInfo = mAttachInfo;
15217        if (attachInfo == null) {
15218            throw new IllegalStateException("This view must be attached to a window first");
15219        }
15220
15221        if (getWidth() == 0 || getHeight() == 0) {
15222            return;
15223        }
15224
15225        switch (mLayerType) {
15226            case LAYER_TYPE_HARDWARE:
15227                updateDisplayListIfDirty();
15228                if (attachInfo.mHardwareRenderer != null && mRenderNode.isValid()) {
15229                    attachInfo.mHardwareRenderer.buildLayer(mRenderNode);
15230                }
15231                break;
15232            case LAYER_TYPE_SOFTWARE:
15233                buildDrawingCache(true);
15234                break;
15235        }
15236    }
15237
15238    /**
15239     * Destroys all hardware rendering resources. This method is invoked
15240     * when the system needs to reclaim resources. Upon execution of this
15241     * method, you should free any OpenGL resources created by the view.
15242     *
15243     * Note: you <strong>must</strong> call
15244     * <code>super.destroyHardwareResources()</code> when overriding
15245     * this method.
15246     *
15247     * @hide
15248     */
15249    @CallSuper
15250    protected void destroyHardwareResources() {
15251        // Although the Layer will be destroyed by RenderNode, we want to release
15252        // the staging display list, which is also a signal to RenderNode that it's
15253        // safe to free its copy of the display list as it knows that we will
15254        // push an updated DisplayList if we try to draw again
15255        resetDisplayList();
15256    }
15257
15258    /**
15259     * <p>Enables or disables the drawing cache. When the drawing cache is enabled, the next call
15260     * to {@link #getDrawingCache()} or {@link #buildDrawingCache()} will draw the view in a
15261     * bitmap. Calling {@link #draw(android.graphics.Canvas)} will not draw from the cache when
15262     * the cache is enabled. To benefit from the cache, you must request the drawing cache by
15263     * calling {@link #getDrawingCache()} and draw it on screen if the returned bitmap is not
15264     * null.</p>
15265     *
15266     * <p>Enabling the drawing cache is similar to
15267     * {@link #setLayerType(int, android.graphics.Paint) setting a layer} when hardware
15268     * acceleration is turned off. When hardware acceleration is turned on, enabling the
15269     * drawing cache has no effect on rendering because the system uses a different mechanism
15270     * for acceleration which ignores the flag. If you want to use a Bitmap for the view, even
15271     * when hardware acceleration is enabled, see {@link #setLayerType(int, android.graphics.Paint)}
15272     * for information on how to enable software and hardware layers.</p>
15273     *
15274     * <p>This API can be used to manually generate
15275     * a bitmap copy of this view, by setting the flag to <code>true</code> and calling
15276     * {@link #getDrawingCache()}.</p>
15277     *
15278     * @param enabled true to enable the drawing cache, false otherwise
15279     *
15280     * @see #isDrawingCacheEnabled()
15281     * @see #getDrawingCache()
15282     * @see #buildDrawingCache()
15283     * @see #setLayerType(int, android.graphics.Paint)
15284     */
15285    public void setDrawingCacheEnabled(boolean enabled) {
15286        mCachingFailed = false;
15287        setFlags(enabled ? DRAWING_CACHE_ENABLED : 0, DRAWING_CACHE_ENABLED);
15288    }
15289
15290    /**
15291     * <p>Indicates whether the drawing cache is enabled for this view.</p>
15292     *
15293     * @return true if the drawing cache is enabled
15294     *
15295     * @see #setDrawingCacheEnabled(boolean)
15296     * @see #getDrawingCache()
15297     */
15298    @ViewDebug.ExportedProperty(category = "drawing")
15299    public boolean isDrawingCacheEnabled() {
15300        return (mViewFlags & DRAWING_CACHE_ENABLED) == DRAWING_CACHE_ENABLED;
15301    }
15302
15303    /**
15304     * Debugging utility which recursively outputs the dirty state of a view and its
15305     * descendants.
15306     *
15307     * @hide
15308     */
15309    @SuppressWarnings({"UnusedDeclaration"})
15310    public void outputDirtyFlags(String indent, boolean clear, int clearMask) {
15311        Log.d("View", indent + this + "             DIRTY(" + (mPrivateFlags & View.PFLAG_DIRTY_MASK) +
15312                ") DRAWN(" + (mPrivateFlags & PFLAG_DRAWN) + ")" + " CACHE_VALID(" +
15313                (mPrivateFlags & View.PFLAG_DRAWING_CACHE_VALID) +
15314                ") INVALIDATED(" + (mPrivateFlags & PFLAG_INVALIDATED) + ")");
15315        if (clear) {
15316            mPrivateFlags &= clearMask;
15317        }
15318        if (this instanceof ViewGroup) {
15319            ViewGroup parent = (ViewGroup) this;
15320            final int count = parent.getChildCount();
15321            for (int i = 0; i < count; i++) {
15322                final View child = parent.getChildAt(i);
15323                child.outputDirtyFlags(indent + "  ", clear, clearMask);
15324            }
15325        }
15326    }
15327
15328    /**
15329     * This method is used by ViewGroup to cause its children to restore or recreate their
15330     * display lists. It is called by getDisplayList() when the parent ViewGroup does not need
15331     * to recreate its own display list, which would happen if it went through the normal
15332     * draw/dispatchDraw mechanisms.
15333     *
15334     * @hide
15335     */
15336    protected void dispatchGetDisplayList() {}
15337
15338    /**
15339     * A view that is not attached or hardware accelerated cannot create a display list.
15340     * This method checks these conditions and returns the appropriate result.
15341     *
15342     * @return true if view has the ability to create a display list, false otherwise.
15343     *
15344     * @hide
15345     */
15346    public boolean canHaveDisplayList() {
15347        return !(mAttachInfo == null || mAttachInfo.mHardwareRenderer == null);
15348    }
15349
15350    /**
15351     * Gets the RenderNode for the view, and updates its DisplayList (if needed and supported)
15352     * @hide
15353     */
15354    @NonNull
15355    public RenderNode updateDisplayListIfDirty() {
15356        final RenderNode renderNode = mRenderNode;
15357        if (!canHaveDisplayList()) {
15358            // can't populate RenderNode, don't try
15359            return renderNode;
15360        }
15361
15362        if ((mPrivateFlags & PFLAG_DRAWING_CACHE_VALID) == 0
15363                || !renderNode.isValid()
15364                || (mRecreateDisplayList)) {
15365            // Don't need to recreate the display list, just need to tell our
15366            // children to restore/recreate theirs
15367            if (renderNode.isValid()
15368                    && !mRecreateDisplayList) {
15369                mPrivateFlags |= PFLAG_DRAWN | PFLAG_DRAWING_CACHE_VALID;
15370                mPrivateFlags &= ~PFLAG_DIRTY_MASK;
15371                dispatchGetDisplayList();
15372
15373                return renderNode; // no work needed
15374            }
15375
15376            // If we got here, we're recreating it. Mark it as such to ensure that
15377            // we copy in child display lists into ours in drawChild()
15378            mRecreateDisplayList = true;
15379
15380            int width = mRight - mLeft;
15381            int height = mBottom - mTop;
15382            int layerType = getLayerType();
15383
15384            final DisplayListCanvas canvas = renderNode.start(width, height);
15385            canvas.setHighContrastText(mAttachInfo.mHighContrastText);
15386
15387            try {
15388                if (layerType == LAYER_TYPE_SOFTWARE) {
15389                    buildDrawingCache(true);
15390                    Bitmap cache = getDrawingCache(true);
15391                    if (cache != null) {
15392                        canvas.drawBitmap(cache, 0, 0, mLayerPaint);
15393                    }
15394                } else {
15395                    computeScroll();
15396
15397                    canvas.translate(-mScrollX, -mScrollY);
15398                    mPrivateFlags |= PFLAG_DRAWN | PFLAG_DRAWING_CACHE_VALID;
15399                    mPrivateFlags &= ~PFLAG_DIRTY_MASK;
15400
15401                    // Fast path for layouts with no backgrounds
15402                    if ((mPrivateFlags & PFLAG_SKIP_DRAW) == PFLAG_SKIP_DRAW) {
15403                        dispatchDraw(canvas);
15404                        if (mOverlay != null && !mOverlay.isEmpty()) {
15405                            mOverlay.getOverlayView().draw(canvas);
15406                        }
15407                    } else {
15408                        draw(canvas);
15409                    }
15410                }
15411            } finally {
15412                renderNode.end(canvas);
15413                setDisplayListProperties(renderNode);
15414            }
15415        } else {
15416            mPrivateFlags |= PFLAG_DRAWN | PFLAG_DRAWING_CACHE_VALID;
15417            mPrivateFlags &= ~PFLAG_DIRTY_MASK;
15418        }
15419        return renderNode;
15420    }
15421
15422    private void resetDisplayList() {
15423        if (mRenderNode.isValid()) {
15424            mRenderNode.discardDisplayList();
15425        }
15426
15427        if (mBackgroundRenderNode != null && mBackgroundRenderNode.isValid()) {
15428            mBackgroundRenderNode.discardDisplayList();
15429        }
15430    }
15431
15432    /**
15433     * <p>Calling this method is equivalent to calling <code>getDrawingCache(false)</code>.</p>
15434     *
15435     * @return A non-scaled bitmap representing this view or null if cache is disabled.
15436     *
15437     * @see #getDrawingCache(boolean)
15438     */
15439    public Bitmap getDrawingCache() {
15440        return getDrawingCache(false);
15441    }
15442
15443    /**
15444     * <p>Returns the bitmap in which this view drawing is cached. The returned bitmap
15445     * is null when caching is disabled. If caching is enabled and the cache is not ready,
15446     * this method will create it. Calling {@link #draw(android.graphics.Canvas)} will not
15447     * draw from the cache when the cache is enabled. To benefit from the cache, you must
15448     * request the drawing cache by calling this method and draw it on screen if the
15449     * returned bitmap is not null.</p>
15450     *
15451     * <p>Note about auto scaling in compatibility mode: When auto scaling is not enabled,
15452     * this method will create a bitmap of the same size as this view. Because this bitmap
15453     * will be drawn scaled by the parent ViewGroup, the result on screen might show
15454     * scaling artifacts. To avoid such artifacts, you should call this method by setting
15455     * the auto scaling to true. Doing so, however, will generate a bitmap of a different
15456     * size than the view. This implies that your application must be able to handle this
15457     * size.</p>
15458     *
15459     * @param autoScale Indicates whether the generated bitmap should be scaled based on
15460     *        the current density of the screen when the application is in compatibility
15461     *        mode.
15462     *
15463     * @return A bitmap representing this view or null if cache is disabled.
15464     *
15465     * @see #setDrawingCacheEnabled(boolean)
15466     * @see #isDrawingCacheEnabled()
15467     * @see #buildDrawingCache(boolean)
15468     * @see #destroyDrawingCache()
15469     */
15470    public Bitmap getDrawingCache(boolean autoScale) {
15471        if ((mViewFlags & WILL_NOT_CACHE_DRAWING) == WILL_NOT_CACHE_DRAWING) {
15472            return null;
15473        }
15474        if ((mViewFlags & DRAWING_CACHE_ENABLED) == DRAWING_CACHE_ENABLED) {
15475            buildDrawingCache(autoScale);
15476        }
15477        return autoScale ? mDrawingCache : mUnscaledDrawingCache;
15478    }
15479
15480    /**
15481     * <p>Frees the resources used by the drawing cache. If you call
15482     * {@link #buildDrawingCache()} manually without calling
15483     * {@link #setDrawingCacheEnabled(boolean) setDrawingCacheEnabled(true)}, you
15484     * should cleanup the cache with this method afterwards.</p>
15485     *
15486     * @see #setDrawingCacheEnabled(boolean)
15487     * @see #buildDrawingCache()
15488     * @see #getDrawingCache()
15489     */
15490    public void destroyDrawingCache() {
15491        if (mDrawingCache != null) {
15492            mDrawingCache.recycle();
15493            mDrawingCache = null;
15494        }
15495        if (mUnscaledDrawingCache != null) {
15496            mUnscaledDrawingCache.recycle();
15497            mUnscaledDrawingCache = null;
15498        }
15499    }
15500
15501    /**
15502     * Setting a solid background color for the drawing cache's bitmaps will improve
15503     * performance and memory usage. Note, though that this should only be used if this
15504     * view will always be drawn on top of a solid color.
15505     *
15506     * @param color The background color to use for the drawing cache's bitmap
15507     *
15508     * @see #setDrawingCacheEnabled(boolean)
15509     * @see #buildDrawingCache()
15510     * @see #getDrawingCache()
15511     */
15512    public void setDrawingCacheBackgroundColor(@ColorInt int color) {
15513        if (color != mDrawingCacheBackgroundColor) {
15514            mDrawingCacheBackgroundColor = color;
15515            mPrivateFlags &= ~PFLAG_DRAWING_CACHE_VALID;
15516        }
15517    }
15518
15519    /**
15520     * @see #setDrawingCacheBackgroundColor(int)
15521     *
15522     * @return The background color to used for the drawing cache's bitmap
15523     */
15524    @ColorInt
15525    public int getDrawingCacheBackgroundColor() {
15526        return mDrawingCacheBackgroundColor;
15527    }
15528
15529    /**
15530     * <p>Calling this method is equivalent to calling <code>buildDrawingCache(false)</code>.</p>
15531     *
15532     * @see #buildDrawingCache(boolean)
15533     */
15534    public void buildDrawingCache() {
15535        buildDrawingCache(false);
15536    }
15537
15538    /**
15539     * <p>Forces the drawing cache to be built if the drawing cache is invalid.</p>
15540     *
15541     * <p>If you call {@link #buildDrawingCache()} manually without calling
15542     * {@link #setDrawingCacheEnabled(boolean) setDrawingCacheEnabled(true)}, you
15543     * should cleanup the cache by calling {@link #destroyDrawingCache()} afterwards.</p>
15544     *
15545     * <p>Note about auto scaling in compatibility mode: When auto scaling is not enabled,
15546     * this method will create a bitmap of the same size as this view. Because this bitmap
15547     * will be drawn scaled by the parent ViewGroup, the result on screen might show
15548     * scaling artifacts. To avoid such artifacts, you should call this method by setting
15549     * the auto scaling to true. Doing so, however, will generate a bitmap of a different
15550     * size than the view. This implies that your application must be able to handle this
15551     * size.</p>
15552     *
15553     * <p>You should avoid calling this method when hardware acceleration is enabled. If
15554     * you do not need the drawing cache bitmap, calling this method will increase memory
15555     * usage and cause the view to be rendered in software once, thus negatively impacting
15556     * performance.</p>
15557     *
15558     * @see #getDrawingCache()
15559     * @see #destroyDrawingCache()
15560     */
15561    public void buildDrawingCache(boolean autoScale) {
15562        if ((mPrivateFlags & PFLAG_DRAWING_CACHE_VALID) == 0 || (autoScale ?
15563                mDrawingCache == null : mUnscaledDrawingCache == null)) {
15564            if (Trace.isTagEnabled(Trace.TRACE_TAG_VIEW)) {
15565                Trace.traceBegin(Trace.TRACE_TAG_VIEW,
15566                        "buildDrawingCache/SW Layer for " + getClass().getSimpleName());
15567            }
15568            try {
15569                buildDrawingCacheImpl(autoScale);
15570            } finally {
15571                Trace.traceEnd(Trace.TRACE_TAG_VIEW);
15572            }
15573        }
15574    }
15575
15576    /**
15577     * private, internal implementation of buildDrawingCache, used to enable tracing
15578     */
15579    private void buildDrawingCacheImpl(boolean autoScale) {
15580        mCachingFailed = false;
15581
15582        int width = mRight - mLeft;
15583        int height = mBottom - mTop;
15584
15585        final AttachInfo attachInfo = mAttachInfo;
15586        final boolean scalingRequired = attachInfo != null && attachInfo.mScalingRequired;
15587
15588        if (autoScale && scalingRequired) {
15589            width = (int) ((width * attachInfo.mApplicationScale) + 0.5f);
15590            height = (int) ((height * attachInfo.mApplicationScale) + 0.5f);
15591        }
15592
15593        final int drawingCacheBackgroundColor = mDrawingCacheBackgroundColor;
15594        final boolean opaque = drawingCacheBackgroundColor != 0 || isOpaque();
15595        final boolean use32BitCache = attachInfo != null && attachInfo.mUse32BitDrawingCache;
15596
15597        final long projectedBitmapSize = width * height * (opaque && !use32BitCache ? 2 : 4);
15598        final long drawingCacheSize =
15599                ViewConfiguration.get(mContext).getScaledMaximumDrawingCacheSize();
15600        if (width <= 0 || height <= 0 || projectedBitmapSize > drawingCacheSize) {
15601            if (width > 0 && height > 0) {
15602                Log.w(VIEW_LOG_TAG, getClass().getSimpleName() + " not displayed because it is"
15603                        + " too large to fit into a software layer (or drawing cache), needs "
15604                        + projectedBitmapSize + " bytes, only "
15605                        + drawingCacheSize + " available");
15606            }
15607            destroyDrawingCache();
15608            mCachingFailed = true;
15609            return;
15610        }
15611
15612        boolean clear = true;
15613        Bitmap bitmap = autoScale ? mDrawingCache : mUnscaledDrawingCache;
15614
15615        if (bitmap == null || bitmap.getWidth() != width || bitmap.getHeight() != height) {
15616            Bitmap.Config quality;
15617            if (!opaque) {
15618                // Never pick ARGB_4444 because it looks awful
15619                // Keep the DRAWING_CACHE_QUALITY_LOW flag just in case
15620                switch (mViewFlags & DRAWING_CACHE_QUALITY_MASK) {
15621                    case DRAWING_CACHE_QUALITY_AUTO:
15622                    case DRAWING_CACHE_QUALITY_LOW:
15623                    case DRAWING_CACHE_QUALITY_HIGH:
15624                    default:
15625                        quality = Bitmap.Config.ARGB_8888;
15626                        break;
15627                }
15628            } else {
15629                // Optimization for translucent windows
15630                // If the window is translucent, use a 32 bits bitmap to benefit from memcpy()
15631                quality = use32BitCache ? Bitmap.Config.ARGB_8888 : Bitmap.Config.RGB_565;
15632            }
15633
15634            // Try to cleanup memory
15635            if (bitmap != null) bitmap.recycle();
15636
15637            try {
15638                bitmap = Bitmap.createBitmap(mResources.getDisplayMetrics(),
15639                        width, height, quality);
15640                bitmap.setDensity(getResources().getDisplayMetrics().densityDpi);
15641                if (autoScale) {
15642                    mDrawingCache = bitmap;
15643                } else {
15644                    mUnscaledDrawingCache = bitmap;
15645                }
15646                if (opaque && use32BitCache) bitmap.setHasAlpha(false);
15647            } catch (OutOfMemoryError e) {
15648                // If there is not enough memory to create the bitmap cache, just
15649                // ignore the issue as bitmap caches are not required to draw the
15650                // view hierarchy
15651                if (autoScale) {
15652                    mDrawingCache = null;
15653                } else {
15654                    mUnscaledDrawingCache = null;
15655                }
15656                mCachingFailed = true;
15657                return;
15658            }
15659
15660            clear = drawingCacheBackgroundColor != 0;
15661        }
15662
15663        Canvas canvas;
15664        if (attachInfo != null) {
15665            canvas = attachInfo.mCanvas;
15666            if (canvas == null) {
15667                canvas = new Canvas();
15668            }
15669            canvas.setBitmap(bitmap);
15670            // Temporarily clobber the cached Canvas in case one of our children
15671            // is also using a drawing cache. Without this, the children would
15672            // steal the canvas by attaching their own bitmap to it and bad, bad
15673            // thing would happen (invisible views, corrupted drawings, etc.)
15674            attachInfo.mCanvas = null;
15675        } else {
15676            // This case should hopefully never or seldom happen
15677            canvas = new Canvas(bitmap);
15678        }
15679
15680        if (clear) {
15681            bitmap.eraseColor(drawingCacheBackgroundColor);
15682        }
15683
15684        computeScroll();
15685        final int restoreCount = canvas.save();
15686
15687        if (autoScale && scalingRequired) {
15688            final float scale = attachInfo.mApplicationScale;
15689            canvas.scale(scale, scale);
15690        }
15691
15692        canvas.translate(-mScrollX, -mScrollY);
15693
15694        mPrivateFlags |= PFLAG_DRAWN;
15695        if (mAttachInfo == null || !mAttachInfo.mHardwareAccelerated ||
15696                mLayerType != LAYER_TYPE_NONE) {
15697            mPrivateFlags |= PFLAG_DRAWING_CACHE_VALID;
15698        }
15699
15700        // Fast path for layouts with no backgrounds
15701        if ((mPrivateFlags & PFLAG_SKIP_DRAW) == PFLAG_SKIP_DRAW) {
15702            mPrivateFlags &= ~PFLAG_DIRTY_MASK;
15703            dispatchDraw(canvas);
15704            if (mOverlay != null && !mOverlay.isEmpty()) {
15705                mOverlay.getOverlayView().draw(canvas);
15706            }
15707        } else {
15708            draw(canvas);
15709        }
15710
15711        canvas.restoreToCount(restoreCount);
15712        canvas.setBitmap(null);
15713
15714        if (attachInfo != null) {
15715            // Restore the cached Canvas for our siblings
15716            attachInfo.mCanvas = canvas;
15717        }
15718    }
15719
15720    /**
15721     * Create a snapshot of the view into a bitmap.  We should probably make
15722     * some form of this public, but should think about the API.
15723     */
15724    Bitmap createSnapshot(Bitmap.Config quality, int backgroundColor, boolean skipChildren) {
15725        int width = mRight - mLeft;
15726        int height = mBottom - mTop;
15727
15728        final AttachInfo attachInfo = mAttachInfo;
15729        final float scale = attachInfo != null ? attachInfo.mApplicationScale : 1.0f;
15730        width = (int) ((width * scale) + 0.5f);
15731        height = (int) ((height * scale) + 0.5f);
15732
15733        Bitmap bitmap = Bitmap.createBitmap(mResources.getDisplayMetrics(),
15734                width > 0 ? width : 1, height > 0 ? height : 1, quality);
15735        if (bitmap == null) {
15736            throw new OutOfMemoryError();
15737        }
15738
15739        Resources resources = getResources();
15740        if (resources != null) {
15741            bitmap.setDensity(resources.getDisplayMetrics().densityDpi);
15742        }
15743
15744        Canvas canvas;
15745        if (attachInfo != null) {
15746            canvas = attachInfo.mCanvas;
15747            if (canvas == null) {
15748                canvas = new Canvas();
15749            }
15750            canvas.setBitmap(bitmap);
15751            // Temporarily clobber the cached Canvas in case one of our children
15752            // is also using a drawing cache. Without this, the children would
15753            // steal the canvas by attaching their own bitmap to it and bad, bad
15754            // things would happen (invisible views, corrupted drawings, etc.)
15755            attachInfo.mCanvas = null;
15756        } else {
15757            // This case should hopefully never or seldom happen
15758            canvas = new Canvas(bitmap);
15759        }
15760
15761        if ((backgroundColor & 0xff000000) != 0) {
15762            bitmap.eraseColor(backgroundColor);
15763        }
15764
15765        computeScroll();
15766        final int restoreCount = canvas.save();
15767        canvas.scale(scale, scale);
15768        canvas.translate(-mScrollX, -mScrollY);
15769
15770        // Temporarily remove the dirty mask
15771        int flags = mPrivateFlags;
15772        mPrivateFlags &= ~PFLAG_DIRTY_MASK;
15773
15774        // Fast path for layouts with no backgrounds
15775        if ((mPrivateFlags & PFLAG_SKIP_DRAW) == PFLAG_SKIP_DRAW) {
15776            dispatchDraw(canvas);
15777            if (mOverlay != null && !mOverlay.isEmpty()) {
15778                mOverlay.getOverlayView().draw(canvas);
15779            }
15780        } else {
15781            draw(canvas);
15782        }
15783
15784        mPrivateFlags = flags;
15785
15786        canvas.restoreToCount(restoreCount);
15787        canvas.setBitmap(null);
15788
15789        if (attachInfo != null) {
15790            // Restore the cached Canvas for our siblings
15791            attachInfo.mCanvas = canvas;
15792        }
15793
15794        return bitmap;
15795    }
15796
15797    /**
15798     * Indicates whether this View is currently in edit mode. A View is usually
15799     * in edit mode when displayed within a developer tool. For instance, if
15800     * this View is being drawn by a visual user interface builder, this method
15801     * should return true.
15802     *
15803     * Subclasses should check the return value of this method to provide
15804     * different behaviors if their normal behavior might interfere with the
15805     * host environment. For instance: the class spawns a thread in its
15806     * constructor, the drawing code relies on device-specific features, etc.
15807     *
15808     * This method is usually checked in the drawing code of custom widgets.
15809     *
15810     * @return True if this View is in edit mode, false otherwise.
15811     */
15812    public boolean isInEditMode() {
15813        return false;
15814    }
15815
15816    /**
15817     * If the View draws content inside its padding and enables fading edges,
15818     * it needs to support padding offsets. Padding offsets are added to the
15819     * fading edges to extend the length of the fade so that it covers pixels
15820     * drawn inside the padding.
15821     *
15822     * Subclasses of this class should override this method if they need
15823     * to draw content inside the padding.
15824     *
15825     * @return True if padding offset must be applied, false otherwise.
15826     *
15827     * @see #getLeftPaddingOffset()
15828     * @see #getRightPaddingOffset()
15829     * @see #getTopPaddingOffset()
15830     * @see #getBottomPaddingOffset()
15831     *
15832     * @since CURRENT
15833     */
15834    protected boolean isPaddingOffsetRequired() {
15835        return false;
15836    }
15837
15838    /**
15839     * Amount by which to extend the left fading region. Called only when
15840     * {@link #isPaddingOffsetRequired()} returns true.
15841     *
15842     * @return The left padding offset in pixels.
15843     *
15844     * @see #isPaddingOffsetRequired()
15845     *
15846     * @since CURRENT
15847     */
15848    protected int getLeftPaddingOffset() {
15849        return 0;
15850    }
15851
15852    /**
15853     * Amount by which to extend the right fading region. Called only when
15854     * {@link #isPaddingOffsetRequired()} returns true.
15855     *
15856     * @return The right padding offset in pixels.
15857     *
15858     * @see #isPaddingOffsetRequired()
15859     *
15860     * @since CURRENT
15861     */
15862    protected int getRightPaddingOffset() {
15863        return 0;
15864    }
15865
15866    /**
15867     * Amount by which to extend the top fading region. Called only when
15868     * {@link #isPaddingOffsetRequired()} returns true.
15869     *
15870     * @return The top padding offset in pixels.
15871     *
15872     * @see #isPaddingOffsetRequired()
15873     *
15874     * @since CURRENT
15875     */
15876    protected int getTopPaddingOffset() {
15877        return 0;
15878    }
15879
15880    /**
15881     * Amount by which to extend the bottom fading region. Called only when
15882     * {@link #isPaddingOffsetRequired()} returns true.
15883     *
15884     * @return The bottom padding offset in pixels.
15885     *
15886     * @see #isPaddingOffsetRequired()
15887     *
15888     * @since CURRENT
15889     */
15890    protected int getBottomPaddingOffset() {
15891        return 0;
15892    }
15893
15894    /**
15895     * @hide
15896     * @param offsetRequired
15897     */
15898    protected int getFadeTop(boolean offsetRequired) {
15899        int top = mPaddingTop;
15900        if (offsetRequired) top += getTopPaddingOffset();
15901        return top;
15902    }
15903
15904    /**
15905     * @hide
15906     * @param offsetRequired
15907     */
15908    protected int getFadeHeight(boolean offsetRequired) {
15909        int padding = mPaddingTop;
15910        if (offsetRequired) padding += getTopPaddingOffset();
15911        return mBottom - mTop - mPaddingBottom - padding;
15912    }
15913
15914    /**
15915     * <p>Indicates whether this view is attached to a hardware accelerated
15916     * window or not.</p>
15917     *
15918     * <p>Even if this method returns true, it does not mean that every call
15919     * to {@link #draw(android.graphics.Canvas)} will be made with an hardware
15920     * accelerated {@link android.graphics.Canvas}. For instance, if this view
15921     * is drawn onto an offscreen {@link android.graphics.Bitmap} and its
15922     * window is hardware accelerated,
15923     * {@link android.graphics.Canvas#isHardwareAccelerated()} will likely
15924     * return false, and this method will return true.</p>
15925     *
15926     * @return True if the view is attached to a window and the window is
15927     *         hardware accelerated; false in any other case.
15928     */
15929    @ViewDebug.ExportedProperty(category = "drawing")
15930    public boolean isHardwareAccelerated() {
15931        return mAttachInfo != null && mAttachInfo.mHardwareAccelerated;
15932    }
15933
15934    /**
15935     * Sets a rectangular area on this view to which the view will be clipped
15936     * when it is drawn. Setting the value to null will remove the clip bounds
15937     * and the view will draw normally, using its full bounds.
15938     *
15939     * @param clipBounds The rectangular area, in the local coordinates of
15940     * this view, to which future drawing operations will be clipped.
15941     */
15942    public void setClipBounds(Rect clipBounds) {
15943        if (clipBounds == mClipBounds
15944                || (clipBounds != null && clipBounds.equals(mClipBounds))) {
15945            return;
15946        }
15947        if (clipBounds != null) {
15948            if (mClipBounds == null) {
15949                mClipBounds = new Rect(clipBounds);
15950            } else {
15951                mClipBounds.set(clipBounds);
15952            }
15953        } else {
15954            mClipBounds = null;
15955        }
15956        mRenderNode.setClipBounds(mClipBounds);
15957        invalidateViewProperty(false, false);
15958    }
15959
15960    /**
15961     * Returns a copy of the current {@link #setClipBounds(Rect) clipBounds}.
15962     *
15963     * @return A copy of the current clip bounds if clip bounds are set,
15964     * otherwise null.
15965     */
15966    public Rect getClipBounds() {
15967        return (mClipBounds != null) ? new Rect(mClipBounds) : null;
15968    }
15969
15970
15971    /**
15972     * Populates an output rectangle with the clip bounds of the view,
15973     * returning {@code true} if successful or {@code false} if the view's
15974     * clip bounds are {@code null}.
15975     *
15976     * @param outRect rectangle in which to place the clip bounds of the view
15977     * @return {@code true} if successful or {@code false} if the view's
15978     *         clip bounds are {@code null}
15979     */
15980    public boolean getClipBounds(Rect outRect) {
15981        if (mClipBounds != null) {
15982            outRect.set(mClipBounds);
15983            return true;
15984        }
15985        return false;
15986    }
15987
15988    /**
15989     * Utility function, called by draw(canvas, parent, drawingTime) to handle the less common
15990     * case of an active Animation being run on the view.
15991     */
15992    private boolean applyLegacyAnimation(ViewGroup parent, long drawingTime,
15993            Animation a, boolean scalingRequired) {
15994        Transformation invalidationTransform;
15995        final int flags = parent.mGroupFlags;
15996        final boolean initialized = a.isInitialized();
15997        if (!initialized) {
15998            a.initialize(mRight - mLeft, mBottom - mTop, parent.getWidth(), parent.getHeight());
15999            a.initializeInvalidateRegion(0, 0, mRight - mLeft, mBottom - mTop);
16000            if (mAttachInfo != null) a.setListenerHandler(mAttachInfo.mHandler);
16001            onAnimationStart();
16002        }
16003
16004        final Transformation t = parent.getChildTransformation();
16005        boolean more = a.getTransformation(drawingTime, t, 1f);
16006        if (scalingRequired && mAttachInfo.mApplicationScale != 1f) {
16007            if (parent.mInvalidationTransformation == null) {
16008                parent.mInvalidationTransformation = new Transformation();
16009            }
16010            invalidationTransform = parent.mInvalidationTransformation;
16011            a.getTransformation(drawingTime, invalidationTransform, 1f);
16012        } else {
16013            invalidationTransform = t;
16014        }
16015
16016        if (more) {
16017            if (!a.willChangeBounds()) {
16018                if ((flags & (ViewGroup.FLAG_OPTIMIZE_INVALIDATE | ViewGroup.FLAG_ANIMATION_DONE)) ==
16019                        ViewGroup.FLAG_OPTIMIZE_INVALIDATE) {
16020                    parent.mGroupFlags |= ViewGroup.FLAG_INVALIDATE_REQUIRED;
16021                } else if ((flags & ViewGroup.FLAG_INVALIDATE_REQUIRED) == 0) {
16022                    // The child need to draw an animation, potentially offscreen, so
16023                    // make sure we do not cancel invalidate requests
16024                    parent.mPrivateFlags |= PFLAG_DRAW_ANIMATION;
16025                    parent.invalidate(mLeft, mTop, mRight, mBottom);
16026                }
16027            } else {
16028                if (parent.mInvalidateRegion == null) {
16029                    parent.mInvalidateRegion = new RectF();
16030                }
16031                final RectF region = parent.mInvalidateRegion;
16032                a.getInvalidateRegion(0, 0, mRight - mLeft, mBottom - mTop, region,
16033                        invalidationTransform);
16034
16035                // The child need to draw an animation, potentially offscreen, so
16036                // make sure we do not cancel invalidate requests
16037                parent.mPrivateFlags |= PFLAG_DRAW_ANIMATION;
16038
16039                final int left = mLeft + (int) region.left;
16040                final int top = mTop + (int) region.top;
16041                parent.invalidate(left, top, left + (int) (region.width() + .5f),
16042                        top + (int) (region.height() + .5f));
16043            }
16044        }
16045        return more;
16046    }
16047
16048    /**
16049     * This method is called by getDisplayList() when a display list is recorded for a View.
16050     * It pushes any properties to the RenderNode that aren't managed by the RenderNode.
16051     */
16052    void setDisplayListProperties(RenderNode renderNode) {
16053        if (renderNode != null) {
16054            renderNode.setHasOverlappingRendering(hasOverlappingRendering());
16055            renderNode.setClipToBounds(mParent instanceof ViewGroup
16056                    && ((ViewGroup) mParent).getClipChildren());
16057
16058            float alpha = 1;
16059            if (mParent instanceof ViewGroup && (((ViewGroup) mParent).mGroupFlags &
16060                    ViewGroup.FLAG_SUPPORT_STATIC_TRANSFORMATIONS) != 0) {
16061                ViewGroup parentVG = (ViewGroup) mParent;
16062                final Transformation t = parentVG.getChildTransformation();
16063                if (parentVG.getChildStaticTransformation(this, t)) {
16064                    final int transformType = t.getTransformationType();
16065                    if (transformType != Transformation.TYPE_IDENTITY) {
16066                        if ((transformType & Transformation.TYPE_ALPHA) != 0) {
16067                            alpha = t.getAlpha();
16068                        }
16069                        if ((transformType & Transformation.TYPE_MATRIX) != 0) {
16070                            renderNode.setStaticMatrix(t.getMatrix());
16071                        }
16072                    }
16073                }
16074            }
16075            if (mTransformationInfo != null) {
16076                alpha *= getFinalAlpha();
16077                if (alpha < 1) {
16078                    final int multipliedAlpha = (int) (255 * alpha);
16079                    if (onSetAlpha(multipliedAlpha)) {
16080                        alpha = 1;
16081                    }
16082                }
16083                renderNode.setAlpha(alpha);
16084            } else if (alpha < 1) {
16085                renderNode.setAlpha(alpha);
16086            }
16087        }
16088    }
16089
16090    /**
16091     * This method is called by ViewGroup.drawChild() to have each child view draw itself.
16092     *
16093     * This is where the View specializes rendering behavior based on layer type,
16094     * and hardware acceleration.
16095     */
16096    boolean draw(Canvas canvas, ViewGroup parent, long drawingTime) {
16097        final boolean hardwareAcceleratedCanvas = canvas.isHardwareAccelerated();
16098        /* If an attached view draws to a HW canvas, it may use its RenderNode + DisplayList.
16099         *
16100         * If a view is dettached, its DisplayList shouldn't exist. If the canvas isn't
16101         * HW accelerated, it can't handle drawing RenderNodes.
16102         */
16103        boolean drawingWithRenderNode = mAttachInfo != null
16104                && mAttachInfo.mHardwareAccelerated
16105                && hardwareAcceleratedCanvas;
16106
16107        boolean more = false;
16108        final boolean childHasIdentityMatrix = hasIdentityMatrix();
16109        final int parentFlags = parent.mGroupFlags;
16110
16111        if ((parentFlags & ViewGroup.FLAG_CLEAR_TRANSFORMATION) != 0) {
16112            parent.getChildTransformation().clear();
16113            parent.mGroupFlags &= ~ViewGroup.FLAG_CLEAR_TRANSFORMATION;
16114        }
16115
16116        Transformation transformToApply = null;
16117        boolean concatMatrix = false;
16118        final boolean scalingRequired = mAttachInfo != null && mAttachInfo.mScalingRequired;
16119        final Animation a = getAnimation();
16120        if (a != null) {
16121            more = applyLegacyAnimation(parent, drawingTime, a, scalingRequired);
16122            concatMatrix = a.willChangeTransformationMatrix();
16123            if (concatMatrix) {
16124                mPrivateFlags3 |= PFLAG3_VIEW_IS_ANIMATING_TRANSFORM;
16125            }
16126            transformToApply = parent.getChildTransformation();
16127        } else {
16128            if ((mPrivateFlags3 & PFLAG3_VIEW_IS_ANIMATING_TRANSFORM) != 0) {
16129                // No longer animating: clear out old animation matrix
16130                mRenderNode.setAnimationMatrix(null);
16131                mPrivateFlags3 &= ~PFLAG3_VIEW_IS_ANIMATING_TRANSFORM;
16132            }
16133            if (!drawingWithRenderNode
16134                    && (parentFlags & ViewGroup.FLAG_SUPPORT_STATIC_TRANSFORMATIONS) != 0) {
16135                final Transformation t = parent.getChildTransformation();
16136                final boolean hasTransform = parent.getChildStaticTransformation(this, t);
16137                if (hasTransform) {
16138                    final int transformType = t.getTransformationType();
16139                    transformToApply = transformType != Transformation.TYPE_IDENTITY ? t : null;
16140                    concatMatrix = (transformType & Transformation.TYPE_MATRIX) != 0;
16141                }
16142            }
16143        }
16144
16145        concatMatrix |= !childHasIdentityMatrix;
16146
16147        // Sets the flag as early as possible to allow draw() implementations
16148        // to call invalidate() successfully when doing animations
16149        mPrivateFlags |= PFLAG_DRAWN;
16150
16151        if (!concatMatrix &&
16152                (parentFlags & (ViewGroup.FLAG_SUPPORT_STATIC_TRANSFORMATIONS |
16153                        ViewGroup.FLAG_CLIP_CHILDREN)) == ViewGroup.FLAG_CLIP_CHILDREN &&
16154                canvas.quickReject(mLeft, mTop, mRight, mBottom, Canvas.EdgeType.BW) &&
16155                (mPrivateFlags & PFLAG_DRAW_ANIMATION) == 0) {
16156            mPrivateFlags2 |= PFLAG2_VIEW_QUICK_REJECTED;
16157            return more;
16158        }
16159        mPrivateFlags2 &= ~PFLAG2_VIEW_QUICK_REJECTED;
16160
16161        if (hardwareAcceleratedCanvas) {
16162            // Clear INVALIDATED flag to allow invalidation to occur during rendering, but
16163            // retain the flag's value temporarily in the mRecreateDisplayList flag
16164            mRecreateDisplayList = (mPrivateFlags & PFLAG_INVALIDATED) != 0;
16165            mPrivateFlags &= ~PFLAG_INVALIDATED;
16166        }
16167
16168        RenderNode renderNode = null;
16169        Bitmap cache = null;
16170        int layerType = getLayerType(); // TODO: signify cache state with just 'cache' local
16171        if (layerType == LAYER_TYPE_SOFTWARE
16172                || (!drawingWithRenderNode && layerType != LAYER_TYPE_NONE)) {
16173            // If not drawing with RenderNode, treat HW layers as SW
16174            layerType = LAYER_TYPE_SOFTWARE;
16175            buildDrawingCache(true);
16176            cache = getDrawingCache(true);
16177        }
16178
16179        if (drawingWithRenderNode) {
16180            // Delay getting the display list until animation-driven alpha values are
16181            // set up and possibly passed on to the view
16182            renderNode = updateDisplayListIfDirty();
16183            if (!renderNode.isValid()) {
16184                // Uncommon, but possible. If a view is removed from the hierarchy during the call
16185                // to getDisplayList(), the display list will be marked invalid and we should not
16186                // try to use it again.
16187                renderNode = null;
16188                drawingWithRenderNode = false;
16189            }
16190        }
16191
16192        int sx = 0;
16193        int sy = 0;
16194        if (!drawingWithRenderNode) {
16195            computeScroll();
16196            sx = mScrollX;
16197            sy = mScrollY;
16198        }
16199
16200        final boolean drawingWithDrawingCache = cache != null && !drawingWithRenderNode;
16201        final boolean offsetForScroll = cache == null && !drawingWithRenderNode;
16202
16203        int restoreTo = -1;
16204        if (!drawingWithRenderNode || transformToApply != null) {
16205            restoreTo = canvas.save();
16206        }
16207        if (offsetForScroll) {
16208            canvas.translate(mLeft - sx, mTop - sy);
16209        } else {
16210            if (!drawingWithRenderNode) {
16211                canvas.translate(mLeft, mTop);
16212            }
16213            if (scalingRequired) {
16214                if (drawingWithRenderNode) {
16215                    // TODO: Might not need this if we put everything inside the DL
16216                    restoreTo = canvas.save();
16217                }
16218                // mAttachInfo cannot be null, otherwise scalingRequired == false
16219                final float scale = 1.0f / mAttachInfo.mApplicationScale;
16220                canvas.scale(scale, scale);
16221            }
16222        }
16223
16224        float alpha = drawingWithRenderNode ? 1 : (getAlpha() * getTransitionAlpha());
16225        if (transformToApply != null
16226                || alpha < 1
16227                || !hasIdentityMatrix()
16228                || (mPrivateFlags3 & PFLAG3_VIEW_IS_ANIMATING_ALPHA) != 0) {
16229            if (transformToApply != null || !childHasIdentityMatrix) {
16230                int transX = 0;
16231                int transY = 0;
16232
16233                if (offsetForScroll) {
16234                    transX = -sx;
16235                    transY = -sy;
16236                }
16237
16238                if (transformToApply != null) {
16239                    if (concatMatrix) {
16240                        if (drawingWithRenderNode) {
16241                            renderNode.setAnimationMatrix(transformToApply.getMatrix());
16242                        } else {
16243                            // Undo the scroll translation, apply the transformation matrix,
16244                            // then redo the scroll translate to get the correct result.
16245                            canvas.translate(-transX, -transY);
16246                            canvas.concat(transformToApply.getMatrix());
16247                            canvas.translate(transX, transY);
16248                        }
16249                        parent.mGroupFlags |= ViewGroup.FLAG_CLEAR_TRANSFORMATION;
16250                    }
16251
16252                    float transformAlpha = transformToApply.getAlpha();
16253                    if (transformAlpha < 1) {
16254                        alpha *= transformAlpha;
16255                        parent.mGroupFlags |= ViewGroup.FLAG_CLEAR_TRANSFORMATION;
16256                    }
16257                }
16258
16259                if (!childHasIdentityMatrix && !drawingWithRenderNode) {
16260                    canvas.translate(-transX, -transY);
16261                    canvas.concat(getMatrix());
16262                    canvas.translate(transX, transY);
16263                }
16264            }
16265
16266            // Deal with alpha if it is or used to be <1
16267            if (alpha < 1 || (mPrivateFlags3 & PFLAG3_VIEW_IS_ANIMATING_ALPHA) != 0) {
16268                if (alpha < 1) {
16269                    mPrivateFlags3 |= PFLAG3_VIEW_IS_ANIMATING_ALPHA;
16270                } else {
16271                    mPrivateFlags3 &= ~PFLAG3_VIEW_IS_ANIMATING_ALPHA;
16272                }
16273                parent.mGroupFlags |= ViewGroup.FLAG_CLEAR_TRANSFORMATION;
16274                if (!drawingWithDrawingCache) {
16275                    final int multipliedAlpha = (int) (255 * alpha);
16276                    if (!onSetAlpha(multipliedAlpha)) {
16277                        if (drawingWithRenderNode) {
16278                            renderNode.setAlpha(alpha * getAlpha() * getTransitionAlpha());
16279                        } else if (layerType == LAYER_TYPE_NONE) {
16280                            canvas.saveLayerAlpha(sx, sy, sx + getWidth(), sy + getHeight(),
16281                                    multipliedAlpha);
16282                        }
16283                    } else {
16284                        // Alpha is handled by the child directly, clobber the layer's alpha
16285                        mPrivateFlags |= PFLAG_ALPHA_SET;
16286                    }
16287                }
16288            }
16289        } else if ((mPrivateFlags & PFLAG_ALPHA_SET) == PFLAG_ALPHA_SET) {
16290            onSetAlpha(255);
16291            mPrivateFlags &= ~PFLAG_ALPHA_SET;
16292        }
16293
16294        if (!drawingWithRenderNode) {
16295            // apply clips directly, since RenderNode won't do it for this draw
16296            if ((parentFlags & ViewGroup.FLAG_CLIP_CHILDREN) != 0 && cache == null) {
16297                if (offsetForScroll) {
16298                    canvas.clipRect(sx, sy, sx + getWidth(), sy + getHeight());
16299                } else {
16300                    if (!scalingRequired || cache == null) {
16301                        canvas.clipRect(0, 0, getWidth(), getHeight());
16302                    } else {
16303                        canvas.clipRect(0, 0, cache.getWidth(), cache.getHeight());
16304                    }
16305                }
16306            }
16307
16308            if (mClipBounds != null) {
16309                // clip bounds ignore scroll
16310                canvas.clipRect(mClipBounds);
16311            }
16312        }
16313
16314        if (!drawingWithDrawingCache) {
16315            if (drawingWithRenderNode) {
16316                mPrivateFlags &= ~PFLAG_DIRTY_MASK;
16317                ((DisplayListCanvas) canvas).drawRenderNode(renderNode);
16318            } else {
16319                // Fast path for layouts with no backgrounds
16320                if ((mPrivateFlags & PFLAG_SKIP_DRAW) == PFLAG_SKIP_DRAW) {
16321                    mPrivateFlags &= ~PFLAG_DIRTY_MASK;
16322                    dispatchDraw(canvas);
16323                } else {
16324                    draw(canvas);
16325                }
16326            }
16327        } else if (cache != null) {
16328            mPrivateFlags &= ~PFLAG_DIRTY_MASK;
16329            if (layerType == LAYER_TYPE_NONE) {
16330                // no layer paint, use temporary paint to draw bitmap
16331                Paint cachePaint = parent.mCachePaint;
16332                if (cachePaint == null) {
16333                    cachePaint = new Paint();
16334                    cachePaint.setDither(false);
16335                    parent.mCachePaint = cachePaint;
16336                }
16337                cachePaint.setAlpha((int) (alpha * 255));
16338                canvas.drawBitmap(cache, 0.0f, 0.0f, cachePaint);
16339            } else {
16340                // use layer paint to draw the bitmap, merging the two alphas, but also restore
16341                int layerPaintAlpha = mLayerPaint.getAlpha();
16342                mLayerPaint.setAlpha((int) (alpha * layerPaintAlpha));
16343                canvas.drawBitmap(cache, 0.0f, 0.0f, mLayerPaint);
16344                mLayerPaint.setAlpha(layerPaintAlpha);
16345            }
16346        }
16347
16348        if (restoreTo >= 0) {
16349            canvas.restoreToCount(restoreTo);
16350        }
16351
16352        if (a != null && !more) {
16353            if (!hardwareAcceleratedCanvas && !a.getFillAfter()) {
16354                onSetAlpha(255);
16355            }
16356            parent.finishAnimatingView(this, a);
16357        }
16358
16359        if (more && hardwareAcceleratedCanvas) {
16360            if (a.hasAlpha() && (mPrivateFlags & PFLAG_ALPHA_SET) == PFLAG_ALPHA_SET) {
16361                // alpha animations should cause the child to recreate its display list
16362                invalidate(true);
16363            }
16364        }
16365
16366        mRecreateDisplayList = false;
16367
16368        return more;
16369    }
16370
16371    /**
16372     * Manually render this view (and all of its children) to the given Canvas.
16373     * The view must have already done a full layout before this function is
16374     * called.  When implementing a view, implement
16375     * {@link #onDraw(android.graphics.Canvas)} instead of overriding this method.
16376     * If you do need to override this method, call the superclass version.
16377     *
16378     * @param canvas The Canvas to which the View is rendered.
16379     */
16380    @CallSuper
16381    public void draw(Canvas canvas) {
16382        final int privateFlags = mPrivateFlags;
16383        final boolean dirtyOpaque = (privateFlags & PFLAG_DIRTY_MASK) == PFLAG_DIRTY_OPAQUE &&
16384                (mAttachInfo == null || !mAttachInfo.mIgnoreDirtyState);
16385        mPrivateFlags = (privateFlags & ~PFLAG_DIRTY_MASK) | PFLAG_DRAWN;
16386
16387        /*
16388         * Draw traversal performs several drawing steps which must be executed
16389         * in the appropriate order:
16390         *
16391         *      1. Draw the background
16392         *      2. If necessary, save the canvas' layers to prepare for fading
16393         *      3. Draw view's content
16394         *      4. Draw children
16395         *      5. If necessary, draw the fading edges and restore layers
16396         *      6. Draw decorations (scrollbars for instance)
16397         */
16398
16399        // Step 1, draw the background, if needed
16400        int saveCount;
16401
16402        if (!dirtyOpaque) {
16403            drawBackground(canvas);
16404        }
16405
16406        // skip step 2 & 5 if possible (common case)
16407        final int viewFlags = mViewFlags;
16408        boolean horizontalEdges = (viewFlags & FADING_EDGE_HORIZONTAL) != 0;
16409        boolean verticalEdges = (viewFlags & FADING_EDGE_VERTICAL) != 0;
16410        if (!verticalEdges && !horizontalEdges) {
16411            // Step 3, draw the content
16412            if (!dirtyOpaque) onDraw(canvas);
16413
16414            // Step 4, draw the children
16415            dispatchDraw(canvas);
16416
16417            // Overlay is part of the content and draws beneath Foreground
16418            if (mOverlay != null && !mOverlay.isEmpty()) {
16419                mOverlay.getOverlayView().dispatchDraw(canvas);
16420            }
16421
16422            // Step 6, draw decorations (foreground, scrollbars)
16423            onDrawForeground(canvas);
16424
16425            // we're done...
16426            return;
16427        }
16428
16429        /*
16430         * Here we do the full fledged routine...
16431         * (this is an uncommon case where speed matters less,
16432         * this is why we repeat some of the tests that have been
16433         * done above)
16434         */
16435
16436        boolean drawTop = false;
16437        boolean drawBottom = false;
16438        boolean drawLeft = false;
16439        boolean drawRight = false;
16440
16441        float topFadeStrength = 0.0f;
16442        float bottomFadeStrength = 0.0f;
16443        float leftFadeStrength = 0.0f;
16444        float rightFadeStrength = 0.0f;
16445
16446        // Step 2, save the canvas' layers
16447        int paddingLeft = mPaddingLeft;
16448
16449        final boolean offsetRequired = isPaddingOffsetRequired();
16450        if (offsetRequired) {
16451            paddingLeft += getLeftPaddingOffset();
16452        }
16453
16454        int left = mScrollX + paddingLeft;
16455        int right = left + mRight - mLeft - mPaddingRight - paddingLeft;
16456        int top = mScrollY + getFadeTop(offsetRequired);
16457        int bottom = top + getFadeHeight(offsetRequired);
16458
16459        if (offsetRequired) {
16460            right += getRightPaddingOffset();
16461            bottom += getBottomPaddingOffset();
16462        }
16463
16464        final ScrollabilityCache scrollabilityCache = mScrollCache;
16465        final float fadeHeight = scrollabilityCache.fadingEdgeLength;
16466        int length = (int) fadeHeight;
16467
16468        // clip the fade length if top and bottom fades overlap
16469        // overlapping fades produce odd-looking artifacts
16470        if (verticalEdges && (top + length > bottom - length)) {
16471            length = (bottom - top) / 2;
16472        }
16473
16474        // also clip horizontal fades if necessary
16475        if (horizontalEdges && (left + length > right - length)) {
16476            length = (right - left) / 2;
16477        }
16478
16479        if (verticalEdges) {
16480            topFadeStrength = Math.max(0.0f, Math.min(1.0f, getTopFadingEdgeStrength()));
16481            drawTop = topFadeStrength * fadeHeight > 1.0f;
16482            bottomFadeStrength = Math.max(0.0f, Math.min(1.0f, getBottomFadingEdgeStrength()));
16483            drawBottom = bottomFadeStrength * fadeHeight > 1.0f;
16484        }
16485
16486        if (horizontalEdges) {
16487            leftFadeStrength = Math.max(0.0f, Math.min(1.0f, getLeftFadingEdgeStrength()));
16488            drawLeft = leftFadeStrength * fadeHeight > 1.0f;
16489            rightFadeStrength = Math.max(0.0f, Math.min(1.0f, getRightFadingEdgeStrength()));
16490            drawRight = rightFadeStrength * fadeHeight > 1.0f;
16491        }
16492
16493        saveCount = canvas.getSaveCount();
16494
16495        int solidColor = getSolidColor();
16496        if (solidColor == 0) {
16497            final int flags = Canvas.HAS_ALPHA_LAYER_SAVE_FLAG;
16498
16499            if (drawTop) {
16500                canvas.saveLayer(left, top, right, top + length, null, flags);
16501            }
16502
16503            if (drawBottom) {
16504                canvas.saveLayer(left, bottom - length, right, bottom, null, flags);
16505            }
16506
16507            if (drawLeft) {
16508                canvas.saveLayer(left, top, left + length, bottom, null, flags);
16509            }
16510
16511            if (drawRight) {
16512                canvas.saveLayer(right - length, top, right, bottom, null, flags);
16513            }
16514        } else {
16515            scrollabilityCache.setFadeColor(solidColor);
16516        }
16517
16518        // Step 3, draw the content
16519        if (!dirtyOpaque) onDraw(canvas);
16520
16521        // Step 4, draw the children
16522        dispatchDraw(canvas);
16523
16524        // Step 5, draw the fade effect and restore layers
16525        final Paint p = scrollabilityCache.paint;
16526        final Matrix matrix = scrollabilityCache.matrix;
16527        final Shader fade = scrollabilityCache.shader;
16528
16529        if (drawTop) {
16530            matrix.setScale(1, fadeHeight * topFadeStrength);
16531            matrix.postTranslate(left, top);
16532            fade.setLocalMatrix(matrix);
16533            p.setShader(fade);
16534            canvas.drawRect(left, top, right, top + length, p);
16535        }
16536
16537        if (drawBottom) {
16538            matrix.setScale(1, fadeHeight * bottomFadeStrength);
16539            matrix.postRotate(180);
16540            matrix.postTranslate(left, bottom);
16541            fade.setLocalMatrix(matrix);
16542            p.setShader(fade);
16543            canvas.drawRect(left, bottom - length, right, bottom, p);
16544        }
16545
16546        if (drawLeft) {
16547            matrix.setScale(1, fadeHeight * leftFadeStrength);
16548            matrix.postRotate(-90);
16549            matrix.postTranslate(left, top);
16550            fade.setLocalMatrix(matrix);
16551            p.setShader(fade);
16552            canvas.drawRect(left, top, left + length, bottom, p);
16553        }
16554
16555        if (drawRight) {
16556            matrix.setScale(1, fadeHeight * rightFadeStrength);
16557            matrix.postRotate(90);
16558            matrix.postTranslate(right, top);
16559            fade.setLocalMatrix(matrix);
16560            p.setShader(fade);
16561            canvas.drawRect(right - length, top, right, bottom, p);
16562        }
16563
16564        canvas.restoreToCount(saveCount);
16565
16566        // Overlay is part of the content and draws beneath Foreground
16567        if (mOverlay != null && !mOverlay.isEmpty()) {
16568            mOverlay.getOverlayView().dispatchDraw(canvas);
16569        }
16570
16571        // Step 6, draw decorations (foreground, scrollbars)
16572        onDrawForeground(canvas);
16573    }
16574
16575    /**
16576     * Draws the background onto the specified canvas.
16577     *
16578     * @param canvas Canvas on which to draw the background
16579     */
16580    private void drawBackground(Canvas canvas) {
16581        final Drawable background = mBackground;
16582        if (background == null) {
16583            return;
16584        }
16585
16586        setBackgroundBounds();
16587
16588        // Attempt to use a display list if requested.
16589        if (canvas.isHardwareAccelerated() && mAttachInfo != null
16590                && mAttachInfo.mHardwareRenderer != null) {
16591            mBackgroundRenderNode = getDrawableRenderNode(background, mBackgroundRenderNode);
16592
16593            final RenderNode renderNode = mBackgroundRenderNode;
16594            if (renderNode != null && renderNode.isValid()) {
16595                setBackgroundRenderNodeProperties(renderNode);
16596                ((DisplayListCanvas) canvas).drawRenderNode(renderNode);
16597                return;
16598            }
16599        }
16600
16601        final int scrollX = mScrollX;
16602        final int scrollY = mScrollY;
16603        if ((scrollX | scrollY) == 0) {
16604            background.draw(canvas);
16605        } else {
16606            canvas.translate(scrollX, scrollY);
16607            background.draw(canvas);
16608            canvas.translate(-scrollX, -scrollY);
16609        }
16610    }
16611
16612    /**
16613     * Sets the correct background bounds and rebuilds the outline, if needed.
16614     * <p/>
16615     * This is called by LayoutLib.
16616     */
16617    void setBackgroundBounds() {
16618        if (mBackgroundSizeChanged && mBackground != null) {
16619            mBackground.setBounds(0, 0, mRight - mLeft, mBottom - mTop);
16620            mBackgroundSizeChanged = false;
16621            rebuildOutline();
16622        }
16623    }
16624
16625    private void setBackgroundRenderNodeProperties(RenderNode renderNode) {
16626        renderNode.setTranslationX(mScrollX);
16627        renderNode.setTranslationY(mScrollY);
16628    }
16629
16630    /**
16631     * Creates a new display list or updates the existing display list for the
16632     * specified Drawable.
16633     *
16634     * @param drawable Drawable for which to create a display list
16635     * @param renderNode Existing RenderNode, or {@code null}
16636     * @return A valid display list for the specified drawable
16637     */
16638    private RenderNode getDrawableRenderNode(Drawable drawable, RenderNode renderNode) {
16639        if (renderNode == null) {
16640            renderNode = RenderNode.create(drawable.getClass().getName(), this);
16641        }
16642
16643        final Rect bounds = drawable.getBounds();
16644        final int width = bounds.width();
16645        final int height = bounds.height();
16646        final DisplayListCanvas canvas = renderNode.start(width, height);
16647
16648        // Reverse left/top translation done by drawable canvas, which will
16649        // instead be applied by rendernode's LTRB bounds below. This way, the
16650        // drawable's bounds match with its rendernode bounds and its content
16651        // will lie within those bounds in the rendernode tree.
16652        canvas.translate(-bounds.left, -bounds.top);
16653
16654        try {
16655            drawable.draw(canvas);
16656        } finally {
16657            renderNode.end(canvas);
16658        }
16659
16660        // Set up drawable properties that are view-independent.
16661        renderNode.setLeftTopRightBottom(bounds.left, bounds.top, bounds.right, bounds.bottom);
16662        renderNode.setProjectBackwards(drawable.isProjected());
16663        renderNode.setProjectionReceiver(true);
16664        renderNode.setClipToBounds(false);
16665        return renderNode;
16666    }
16667
16668    /**
16669     * Returns the overlay for this view, creating it if it does not yet exist.
16670     * Adding drawables to the overlay will cause them to be displayed whenever
16671     * the view itself is redrawn. Objects in the overlay should be actively
16672     * managed: remove them when they should not be displayed anymore. The
16673     * overlay will always have the same size as its host view.
16674     *
16675     * <p>Note: Overlays do not currently work correctly with {@link
16676     * SurfaceView} or {@link TextureView}; contents in overlays for these
16677     * types of views may not display correctly.</p>
16678     *
16679     * @return The ViewOverlay object for this view.
16680     * @see ViewOverlay
16681     */
16682    public ViewOverlay getOverlay() {
16683        if (mOverlay == null) {
16684            mOverlay = new ViewOverlay(mContext, this);
16685        }
16686        return mOverlay;
16687    }
16688
16689    /**
16690     * Override this if your view is known to always be drawn on top of a solid color background,
16691     * and needs to draw fading edges. Returning a non-zero color enables the view system to
16692     * optimize the drawing of the fading edges. If you do return a non-zero color, the alpha
16693     * should be set to 0xFF.
16694     *
16695     * @see #setVerticalFadingEdgeEnabled(boolean)
16696     * @see #setHorizontalFadingEdgeEnabled(boolean)
16697     *
16698     * @return The known solid color background for this view, or 0 if the color may vary
16699     */
16700    @ViewDebug.ExportedProperty(category = "drawing")
16701    @ColorInt
16702    public int getSolidColor() {
16703        return 0;
16704    }
16705
16706    /**
16707     * Build a human readable string representation of the specified view flags.
16708     *
16709     * @param flags the view flags to convert to a string
16710     * @return a String representing the supplied flags
16711     */
16712    private static String printFlags(int flags) {
16713        String output = "";
16714        int numFlags = 0;
16715        if ((flags & FOCUSABLE_MASK) == FOCUSABLE) {
16716            output += "TAKES_FOCUS";
16717            numFlags++;
16718        }
16719
16720        switch (flags & VISIBILITY_MASK) {
16721        case INVISIBLE:
16722            if (numFlags > 0) {
16723                output += " ";
16724            }
16725            output += "INVISIBLE";
16726            // USELESS HERE numFlags++;
16727            break;
16728        case GONE:
16729            if (numFlags > 0) {
16730                output += " ";
16731            }
16732            output += "GONE";
16733            // USELESS HERE numFlags++;
16734            break;
16735        default:
16736            break;
16737        }
16738        return output;
16739    }
16740
16741    /**
16742     * Build a human readable string representation of the specified private
16743     * view flags.
16744     *
16745     * @param privateFlags the private view flags to convert to a string
16746     * @return a String representing the supplied flags
16747     */
16748    private static String printPrivateFlags(int privateFlags) {
16749        String output = "";
16750        int numFlags = 0;
16751
16752        if ((privateFlags & PFLAG_WANTS_FOCUS) == PFLAG_WANTS_FOCUS) {
16753            output += "WANTS_FOCUS";
16754            numFlags++;
16755        }
16756
16757        if ((privateFlags & PFLAG_FOCUSED) == PFLAG_FOCUSED) {
16758            if (numFlags > 0) {
16759                output += " ";
16760            }
16761            output += "FOCUSED";
16762            numFlags++;
16763        }
16764
16765        if ((privateFlags & PFLAG_SELECTED) == PFLAG_SELECTED) {
16766            if (numFlags > 0) {
16767                output += " ";
16768            }
16769            output += "SELECTED";
16770            numFlags++;
16771        }
16772
16773        if ((privateFlags & PFLAG_IS_ROOT_NAMESPACE) == PFLAG_IS_ROOT_NAMESPACE) {
16774            if (numFlags > 0) {
16775                output += " ";
16776            }
16777            output += "IS_ROOT_NAMESPACE";
16778            numFlags++;
16779        }
16780
16781        if ((privateFlags & PFLAG_HAS_BOUNDS) == PFLAG_HAS_BOUNDS) {
16782            if (numFlags > 0) {
16783                output += " ";
16784            }
16785            output += "HAS_BOUNDS";
16786            numFlags++;
16787        }
16788
16789        if ((privateFlags & PFLAG_DRAWN) == PFLAG_DRAWN) {
16790            if (numFlags > 0) {
16791                output += " ";
16792            }
16793            output += "DRAWN";
16794            // USELESS HERE numFlags++;
16795        }
16796        return output;
16797    }
16798
16799    /**
16800     * <p>Indicates whether or not this view's layout will be requested during
16801     * the next hierarchy layout pass.</p>
16802     *
16803     * @return true if the layout will be forced during next layout pass
16804     */
16805    public boolean isLayoutRequested() {
16806        return (mPrivateFlags & PFLAG_FORCE_LAYOUT) == PFLAG_FORCE_LAYOUT;
16807    }
16808
16809    /**
16810     * Return true if o is a ViewGroup that is laying out using optical bounds.
16811     * @hide
16812     */
16813    public static boolean isLayoutModeOptical(Object o) {
16814        return o instanceof ViewGroup && ((ViewGroup) o).isLayoutModeOptical();
16815    }
16816
16817    private boolean setOpticalFrame(int left, int top, int right, int bottom) {
16818        Insets parentInsets = mParent instanceof View ?
16819                ((View) mParent).getOpticalInsets() : Insets.NONE;
16820        Insets childInsets = getOpticalInsets();
16821        return setFrame(
16822                left   + parentInsets.left - childInsets.left,
16823                top    + parentInsets.top  - childInsets.top,
16824                right  + parentInsets.left + childInsets.right,
16825                bottom + parentInsets.top  + childInsets.bottom);
16826    }
16827
16828    /**
16829     * Assign a size and position to a view and all of its
16830     * descendants
16831     *
16832     * <p>This is the second phase of the layout mechanism.
16833     * (The first is measuring). In this phase, each parent calls
16834     * layout on all of its children to position them.
16835     * This is typically done using the child measurements
16836     * that were stored in the measure pass().</p>
16837     *
16838     * <p>Derived classes should not override this method.
16839     * Derived classes with children should override
16840     * onLayout. In that method, they should
16841     * call layout on each of their children.</p>
16842     *
16843     * @param l Left position, relative to parent
16844     * @param t Top position, relative to parent
16845     * @param r Right position, relative to parent
16846     * @param b Bottom position, relative to parent
16847     */
16848    @SuppressWarnings({"unchecked"})
16849    public void layout(int l, int t, int r, int b) {
16850        if ((mPrivateFlags3 & PFLAG3_MEASURE_NEEDED_BEFORE_LAYOUT) != 0) {
16851            onMeasure(mOldWidthMeasureSpec, mOldHeightMeasureSpec);
16852            mPrivateFlags3 &= ~PFLAG3_MEASURE_NEEDED_BEFORE_LAYOUT;
16853        }
16854
16855        int oldL = mLeft;
16856        int oldT = mTop;
16857        int oldB = mBottom;
16858        int oldR = mRight;
16859
16860        boolean changed = isLayoutModeOptical(mParent) ?
16861                setOpticalFrame(l, t, r, b) : setFrame(l, t, r, b);
16862
16863        if (changed || (mPrivateFlags & PFLAG_LAYOUT_REQUIRED) == PFLAG_LAYOUT_REQUIRED) {
16864            onLayout(changed, l, t, r, b);
16865            mPrivateFlags &= ~PFLAG_LAYOUT_REQUIRED;
16866
16867            ListenerInfo li = mListenerInfo;
16868            if (li != null && li.mOnLayoutChangeListeners != null) {
16869                ArrayList<OnLayoutChangeListener> listenersCopy =
16870                        (ArrayList<OnLayoutChangeListener>)li.mOnLayoutChangeListeners.clone();
16871                int numListeners = listenersCopy.size();
16872                for (int i = 0; i < numListeners; ++i) {
16873                    listenersCopy.get(i).onLayoutChange(this, l, t, r, b, oldL, oldT, oldR, oldB);
16874                }
16875            }
16876        }
16877
16878        mPrivateFlags &= ~PFLAG_FORCE_LAYOUT;
16879        mPrivateFlags3 |= PFLAG3_IS_LAID_OUT;
16880    }
16881
16882    /**
16883     * Called from layout when this view should
16884     * assign a size and position to each of its children.
16885     *
16886     * Derived classes with children should override
16887     * this method and call layout on each of
16888     * their children.
16889     * @param changed This is a new size or position for this view
16890     * @param left Left position, relative to parent
16891     * @param top Top position, relative to parent
16892     * @param right Right position, relative to parent
16893     * @param bottom Bottom position, relative to parent
16894     */
16895    protected void onLayout(boolean changed, int left, int top, int right, int bottom) {
16896    }
16897
16898    /**
16899     * Assign a size and position to this view.
16900     *
16901     * This is called from layout.
16902     *
16903     * @param left Left position, relative to parent
16904     * @param top Top position, relative to parent
16905     * @param right Right position, relative to parent
16906     * @param bottom Bottom position, relative to parent
16907     * @return true if the new size and position are different than the
16908     *         previous ones
16909     * {@hide}
16910     */
16911    protected boolean setFrame(int left, int top, int right, int bottom) {
16912        boolean changed = false;
16913
16914        if (DBG) {
16915            Log.d("View", this + " View.setFrame(" + left + "," + top + ","
16916                    + right + "," + bottom + ")");
16917        }
16918
16919        if (mLeft != left || mRight != right || mTop != top || mBottom != bottom) {
16920            changed = true;
16921
16922            // Remember our drawn bit
16923            int drawn = mPrivateFlags & PFLAG_DRAWN;
16924
16925            int oldWidth = mRight - mLeft;
16926            int oldHeight = mBottom - mTop;
16927            int newWidth = right - left;
16928            int newHeight = bottom - top;
16929            boolean sizeChanged = (newWidth != oldWidth) || (newHeight != oldHeight);
16930
16931            // Invalidate our old position
16932            invalidate(sizeChanged);
16933
16934            mLeft = left;
16935            mTop = top;
16936            mRight = right;
16937            mBottom = bottom;
16938            mRenderNode.setLeftTopRightBottom(mLeft, mTop, mRight, mBottom);
16939
16940            mPrivateFlags |= PFLAG_HAS_BOUNDS;
16941
16942
16943            if (sizeChanged) {
16944                sizeChange(newWidth, newHeight, oldWidth, oldHeight);
16945            }
16946
16947            if ((mViewFlags & VISIBILITY_MASK) == VISIBLE || mGhostView != null) {
16948                // If we are visible, force the DRAWN bit to on so that
16949                // this invalidate will go through (at least to our parent).
16950                // This is because someone may have invalidated this view
16951                // before this call to setFrame came in, thereby clearing
16952                // the DRAWN bit.
16953                mPrivateFlags |= PFLAG_DRAWN;
16954                invalidate(sizeChanged);
16955                // parent display list may need to be recreated based on a change in the bounds
16956                // of any child
16957                invalidateParentCaches();
16958            }
16959
16960            // Reset drawn bit to original value (invalidate turns it off)
16961            mPrivateFlags |= drawn;
16962
16963            mBackgroundSizeChanged = true;
16964            if (mForegroundInfo != null) {
16965                mForegroundInfo.mBoundsChanged = true;
16966            }
16967
16968            notifySubtreeAccessibilityStateChangedIfNeeded();
16969        }
16970        return changed;
16971    }
16972
16973    /**
16974     * Same as setFrame, but public and hidden. For use in {@link android.transition.ChangeBounds}.
16975     * @hide
16976     */
16977    public void setLeftTopRightBottom(int left, int top, int right, int bottom) {
16978        setFrame(left, top, right, bottom);
16979    }
16980
16981    private void sizeChange(int newWidth, int newHeight, int oldWidth, int oldHeight) {
16982        onSizeChanged(newWidth, newHeight, oldWidth, oldHeight);
16983        if (mOverlay != null) {
16984            mOverlay.getOverlayView().setRight(newWidth);
16985            mOverlay.getOverlayView().setBottom(newHeight);
16986        }
16987        rebuildOutline();
16988    }
16989
16990    /**
16991     * Finalize inflating a view from XML.  This is called as the last phase
16992     * of inflation, after all child views have been added.
16993     *
16994     * <p>Even if the subclass overrides onFinishInflate, they should always be
16995     * sure to call the super method, so that we get called.
16996     */
16997    @CallSuper
16998    protected void onFinishInflate() {
16999    }
17000
17001    /**
17002     * Returns the resources associated with this view.
17003     *
17004     * @return Resources object.
17005     */
17006    public Resources getResources() {
17007        return mResources;
17008    }
17009
17010    /**
17011     * Invalidates the specified Drawable.
17012     *
17013     * @param drawable the drawable to invalidate
17014     */
17015    @Override
17016    public void invalidateDrawable(@NonNull Drawable drawable) {
17017        if (verifyDrawable(drawable)) {
17018            final Rect dirty = drawable.getDirtyBounds();
17019            final int scrollX = mScrollX;
17020            final int scrollY = mScrollY;
17021
17022            invalidate(dirty.left + scrollX, dirty.top + scrollY,
17023                    dirty.right + scrollX, dirty.bottom + scrollY);
17024            rebuildOutline();
17025        }
17026    }
17027
17028    /**
17029     * Schedules an action on a drawable to occur at a specified time.
17030     *
17031     * @param who the recipient of the action
17032     * @param what the action to run on the drawable
17033     * @param when the time at which the action must occur. Uses the
17034     *        {@link SystemClock#uptimeMillis} timebase.
17035     */
17036    @Override
17037    public void scheduleDrawable(Drawable who, Runnable what, long when) {
17038        if (verifyDrawable(who) && what != null) {
17039            final long delay = when - SystemClock.uptimeMillis();
17040            if (mAttachInfo != null) {
17041                mAttachInfo.mViewRootImpl.mChoreographer.postCallbackDelayed(
17042                        Choreographer.CALLBACK_ANIMATION, what, who,
17043                        Choreographer.subtractFrameDelay(delay));
17044            } else {
17045                // Postpone the runnable until we know
17046                // on which thread it needs to run.
17047                getRunQueue().postDelayed(what, delay);
17048            }
17049        }
17050    }
17051
17052    /**
17053     * Cancels a scheduled action on a drawable.
17054     *
17055     * @param who the recipient of the action
17056     * @param what the action to cancel
17057     */
17058    @Override
17059    public void unscheduleDrawable(Drawable who, Runnable what) {
17060        if (verifyDrawable(who) && what != null) {
17061            if (mAttachInfo != null) {
17062                mAttachInfo.mViewRootImpl.mChoreographer.removeCallbacks(
17063                        Choreographer.CALLBACK_ANIMATION, what, who);
17064            }
17065            getRunQueue().removeCallbacks(what);
17066        }
17067    }
17068
17069    /**
17070     * Unschedule any events associated with the given Drawable.  This can be
17071     * used when selecting a new Drawable into a view, so that the previous
17072     * one is completely unscheduled.
17073     *
17074     * @param who The Drawable to unschedule.
17075     *
17076     * @see #drawableStateChanged
17077     */
17078    public void unscheduleDrawable(Drawable who) {
17079        if (mAttachInfo != null && who != null) {
17080            mAttachInfo.mViewRootImpl.mChoreographer.removeCallbacks(
17081                    Choreographer.CALLBACK_ANIMATION, null, who);
17082        }
17083    }
17084
17085    /**
17086     * Resolve the Drawables depending on the layout direction. This is implicitly supposing
17087     * that the View directionality can and will be resolved before its Drawables.
17088     *
17089     * Will call {@link View#onResolveDrawables} when resolution is done.
17090     *
17091     * @hide
17092     */
17093    protected void resolveDrawables() {
17094        // Drawables resolution may need to happen before resolving the layout direction (which is
17095        // done only during the measure() call).
17096        // If the layout direction is not resolved yet, we cannot resolve the Drawables except in
17097        // one case: when the raw layout direction has not been defined as LAYOUT_DIRECTION_INHERIT.
17098        // So, if the raw layout direction is LAYOUT_DIRECTION_LTR or LAYOUT_DIRECTION_RTL or
17099        // LAYOUT_DIRECTION_LOCALE, we can "cheat" and we don't need to wait for the layout
17100        // direction to be resolved as its resolved value will be the same as its raw value.
17101        if (!isLayoutDirectionResolved() &&
17102                getRawLayoutDirection() == View.LAYOUT_DIRECTION_INHERIT) {
17103            return;
17104        }
17105
17106        final int layoutDirection = isLayoutDirectionResolved() ?
17107                getLayoutDirection() : getRawLayoutDirection();
17108
17109        if (mBackground != null) {
17110            mBackground.setLayoutDirection(layoutDirection);
17111        }
17112        if (mForegroundInfo != null && mForegroundInfo.mDrawable != null) {
17113            mForegroundInfo.mDrawable.setLayoutDirection(layoutDirection);
17114        }
17115        mPrivateFlags2 |= PFLAG2_DRAWABLE_RESOLVED;
17116        onResolveDrawables(layoutDirection);
17117    }
17118
17119    boolean areDrawablesResolved() {
17120        return (mPrivateFlags2 & PFLAG2_DRAWABLE_RESOLVED) == PFLAG2_DRAWABLE_RESOLVED;
17121    }
17122
17123    /**
17124     * Called when layout direction has been resolved.
17125     *
17126     * The default implementation does nothing.
17127     *
17128     * @param layoutDirection The resolved layout direction.
17129     *
17130     * @see #LAYOUT_DIRECTION_LTR
17131     * @see #LAYOUT_DIRECTION_RTL
17132     *
17133     * @hide
17134     */
17135    public void onResolveDrawables(@ResolvedLayoutDir int layoutDirection) {
17136    }
17137
17138    /**
17139     * @hide
17140     */
17141    protected void resetResolvedDrawables() {
17142        resetResolvedDrawablesInternal();
17143    }
17144
17145    void resetResolvedDrawablesInternal() {
17146        mPrivateFlags2 &= ~PFLAG2_DRAWABLE_RESOLVED;
17147    }
17148
17149    /**
17150     * If your view subclass is displaying its own Drawable objects, it should
17151     * override this function and return true for any Drawable it is
17152     * displaying.  This allows animations for those drawables to be
17153     * scheduled.
17154     *
17155     * <p>Be sure to call through to the super class when overriding this
17156     * function.
17157     *
17158     * @param who The Drawable to verify.  Return true if it is one you are
17159     *            displaying, else return the result of calling through to the
17160     *            super class.
17161     *
17162     * @return boolean If true than the Drawable is being displayed in the
17163     *         view; else false and it is not allowed to animate.
17164     *
17165     * @see #unscheduleDrawable(android.graphics.drawable.Drawable)
17166     * @see #drawableStateChanged()
17167     */
17168    @CallSuper
17169    protected boolean verifyDrawable(Drawable who) {
17170        return who == mBackground || (mScrollCache != null && mScrollCache.scrollBar == who)
17171                || (mForegroundInfo != null && mForegroundInfo.mDrawable == who);
17172    }
17173
17174    /**
17175     * This function is called whenever the state of the view changes in such
17176     * a way that it impacts the state of drawables being shown.
17177     * <p>
17178     * If the View has a StateListAnimator, it will also be called to run necessary state
17179     * change animations.
17180     * <p>
17181     * Be sure to call through to the superclass when overriding this function.
17182     *
17183     * @see Drawable#setState(int[])
17184     */
17185    @CallSuper
17186    protected void drawableStateChanged() {
17187        final int[] state = getDrawableState();
17188        boolean changed = false;
17189
17190        final Drawable bg = mBackground;
17191        if (bg != null && bg.isStateful()) {
17192            changed |= bg.setState(state);
17193        }
17194
17195        final Drawable fg = mForegroundInfo != null ? mForegroundInfo.mDrawable : null;
17196        if (fg != null && fg.isStateful()) {
17197            changed |= fg.setState(state);
17198        }
17199
17200        if (mScrollCache != null) {
17201            final Drawable scrollBar = mScrollCache.scrollBar;
17202            if (scrollBar != null && scrollBar.isStateful()) {
17203                changed |= scrollBar.setState(state)
17204                        && mScrollCache.state != ScrollabilityCache.OFF;
17205            }
17206        }
17207
17208        if (mStateListAnimator != null) {
17209            mStateListAnimator.setState(state);
17210        }
17211
17212        if (changed) {
17213            invalidate();
17214        }
17215    }
17216
17217    /**
17218     * This function is called whenever the view hotspot changes and needs to
17219     * be propagated to drawables or child views managed by the view.
17220     * <p>
17221     * Dispatching to child views is handled by
17222     * {@link #dispatchDrawableHotspotChanged(float, float)}.
17223     * <p>
17224     * Be sure to call through to the superclass when overriding this function.
17225     *
17226     * @param x hotspot x coordinate
17227     * @param y hotspot y coordinate
17228     */
17229    @CallSuper
17230    public void drawableHotspotChanged(float x, float y) {
17231        if (mBackground != null) {
17232            mBackground.setHotspot(x, y);
17233        }
17234        if (mForegroundInfo != null && mForegroundInfo.mDrawable != null) {
17235            mForegroundInfo.mDrawable.setHotspot(x, y);
17236        }
17237
17238        dispatchDrawableHotspotChanged(x, y);
17239    }
17240
17241    /**
17242     * Dispatches drawableHotspotChanged to all of this View's children.
17243     *
17244     * @param x hotspot x coordinate
17245     * @param y hotspot y coordinate
17246     * @see #drawableHotspotChanged(float, float)
17247     */
17248    public void dispatchDrawableHotspotChanged(float x, float y) {
17249    }
17250
17251    /**
17252     * Call this to force a view to update its drawable state. This will cause
17253     * drawableStateChanged to be called on this view. Views that are interested
17254     * in the new state should call getDrawableState.
17255     *
17256     * @see #drawableStateChanged
17257     * @see #getDrawableState
17258     */
17259    public void refreshDrawableState() {
17260        mPrivateFlags |= PFLAG_DRAWABLE_STATE_DIRTY;
17261        drawableStateChanged();
17262
17263        ViewParent parent = mParent;
17264        if (parent != null) {
17265            parent.childDrawableStateChanged(this);
17266        }
17267    }
17268
17269    /**
17270     * Return an array of resource IDs of the drawable states representing the
17271     * current state of the view.
17272     *
17273     * @return The current drawable state
17274     *
17275     * @see Drawable#setState(int[])
17276     * @see #drawableStateChanged()
17277     * @see #onCreateDrawableState(int)
17278     */
17279    public final int[] getDrawableState() {
17280        if ((mDrawableState != null) && ((mPrivateFlags & PFLAG_DRAWABLE_STATE_DIRTY) == 0)) {
17281            return mDrawableState;
17282        } else {
17283            mDrawableState = onCreateDrawableState(0);
17284            mPrivateFlags &= ~PFLAG_DRAWABLE_STATE_DIRTY;
17285            return mDrawableState;
17286        }
17287    }
17288
17289    /**
17290     * Generate the new {@link android.graphics.drawable.Drawable} state for
17291     * this view. This is called by the view
17292     * system when the cached Drawable state is determined to be invalid.  To
17293     * retrieve the current state, you should use {@link #getDrawableState}.
17294     *
17295     * @param extraSpace if non-zero, this is the number of extra entries you
17296     * would like in the returned array in which you can place your own
17297     * states.
17298     *
17299     * @return Returns an array holding the current {@link Drawable} state of
17300     * the view.
17301     *
17302     * @see #mergeDrawableStates(int[], int[])
17303     */
17304    protected int[] onCreateDrawableState(int extraSpace) {
17305        if ((mViewFlags & DUPLICATE_PARENT_STATE) == DUPLICATE_PARENT_STATE &&
17306                mParent instanceof View) {
17307            return ((View) mParent).onCreateDrawableState(extraSpace);
17308        }
17309
17310        int[] drawableState;
17311
17312        int privateFlags = mPrivateFlags;
17313
17314        int viewStateIndex = 0;
17315        if ((privateFlags & PFLAG_PRESSED) != 0) viewStateIndex |= StateSet.VIEW_STATE_PRESSED;
17316        if ((mViewFlags & ENABLED_MASK) == ENABLED) viewStateIndex |= StateSet.VIEW_STATE_ENABLED;
17317        if (isFocused()) viewStateIndex |= StateSet.VIEW_STATE_FOCUSED;
17318        if ((privateFlags & PFLAG_SELECTED) != 0) viewStateIndex |= StateSet.VIEW_STATE_SELECTED;
17319        if (hasWindowFocus()) viewStateIndex |= StateSet.VIEW_STATE_WINDOW_FOCUSED;
17320        if ((privateFlags & PFLAG_ACTIVATED) != 0) viewStateIndex |= StateSet.VIEW_STATE_ACTIVATED;
17321        if (mAttachInfo != null && mAttachInfo.mHardwareAccelerationRequested &&
17322                HardwareRenderer.isAvailable()) {
17323            // This is set if HW acceleration is requested, even if the current
17324            // process doesn't allow it.  This is just to allow app preview
17325            // windows to better match their app.
17326            viewStateIndex |= StateSet.VIEW_STATE_ACCELERATED;
17327        }
17328        if ((privateFlags & PFLAG_HOVERED) != 0) viewStateIndex |= StateSet.VIEW_STATE_HOVERED;
17329
17330        final int privateFlags2 = mPrivateFlags2;
17331        if ((privateFlags2 & PFLAG2_DRAG_CAN_ACCEPT) != 0) {
17332            viewStateIndex |= StateSet.VIEW_STATE_DRAG_CAN_ACCEPT;
17333        }
17334        if ((privateFlags2 & PFLAG2_DRAG_HOVERED) != 0) {
17335            viewStateIndex |= StateSet.VIEW_STATE_DRAG_HOVERED;
17336        }
17337
17338        drawableState = StateSet.get(viewStateIndex);
17339
17340        //noinspection ConstantIfStatement
17341        if (false) {
17342            Log.i("View", "drawableStateIndex=" + viewStateIndex);
17343            Log.i("View", toString()
17344                    + " pressed=" + ((privateFlags & PFLAG_PRESSED) != 0)
17345                    + " en=" + ((mViewFlags & ENABLED_MASK) == ENABLED)
17346                    + " fo=" + hasFocus()
17347                    + " sl=" + ((privateFlags & PFLAG_SELECTED) != 0)
17348                    + " wf=" + hasWindowFocus()
17349                    + ": " + Arrays.toString(drawableState));
17350        }
17351
17352        if (extraSpace == 0) {
17353            return drawableState;
17354        }
17355
17356        final int[] fullState;
17357        if (drawableState != null) {
17358            fullState = new int[drawableState.length + extraSpace];
17359            System.arraycopy(drawableState, 0, fullState, 0, drawableState.length);
17360        } else {
17361            fullState = new int[extraSpace];
17362        }
17363
17364        return fullState;
17365    }
17366
17367    /**
17368     * Merge your own state values in <var>additionalState</var> into the base
17369     * state values <var>baseState</var> that were returned by
17370     * {@link #onCreateDrawableState(int)}.
17371     *
17372     * @param baseState The base state values returned by
17373     * {@link #onCreateDrawableState(int)}, which will be modified to also hold your
17374     * own additional state values.
17375     *
17376     * @param additionalState The additional state values you would like
17377     * added to <var>baseState</var>; this array is not modified.
17378     *
17379     * @return As a convenience, the <var>baseState</var> array you originally
17380     * passed into the function is returned.
17381     *
17382     * @see #onCreateDrawableState(int)
17383     */
17384    protected static int[] mergeDrawableStates(int[] baseState, int[] additionalState) {
17385        final int N = baseState.length;
17386        int i = N - 1;
17387        while (i >= 0 && baseState[i] == 0) {
17388            i--;
17389        }
17390        System.arraycopy(additionalState, 0, baseState, i + 1, additionalState.length);
17391        return baseState;
17392    }
17393
17394    /**
17395     * Call {@link Drawable#jumpToCurrentState() Drawable.jumpToCurrentState()}
17396     * on all Drawable objects associated with this view.
17397     * <p>
17398     * Also calls {@link StateListAnimator#jumpToCurrentState()} if there is a StateListAnimator
17399     * attached to this view.
17400     */
17401    @CallSuper
17402    public void jumpDrawablesToCurrentState() {
17403        if (mBackground != null) {
17404            mBackground.jumpToCurrentState();
17405        }
17406        if (mStateListAnimator != null) {
17407            mStateListAnimator.jumpToCurrentState();
17408        }
17409        if (mForegroundInfo != null && mForegroundInfo.mDrawable != null) {
17410            mForegroundInfo.mDrawable.jumpToCurrentState();
17411        }
17412    }
17413
17414    /**
17415     * Sets the background color for this view.
17416     * @param color the color of the background
17417     */
17418    @RemotableViewMethod
17419    public void setBackgroundColor(@ColorInt int color) {
17420        if (mBackground instanceof ColorDrawable) {
17421            ((ColorDrawable) mBackground.mutate()).setColor(color);
17422            computeOpaqueFlags();
17423            mBackgroundResource = 0;
17424        } else {
17425            setBackground(new ColorDrawable(color));
17426        }
17427    }
17428
17429    /**
17430     * Set the background to a given resource. The resource should refer to
17431     * a Drawable object or 0 to remove the background.
17432     * @param resid The identifier of the resource.
17433     *
17434     * @attr ref android.R.styleable#View_background
17435     */
17436    @RemotableViewMethod
17437    public void setBackgroundResource(@DrawableRes int resid) {
17438        if (resid != 0 && resid == mBackgroundResource) {
17439            return;
17440        }
17441
17442        Drawable d = null;
17443        if (resid != 0) {
17444            d = mContext.getDrawable(resid);
17445        }
17446        setBackground(d);
17447
17448        mBackgroundResource = resid;
17449    }
17450
17451    /**
17452     * Set the background to a given Drawable, or remove the background. If the
17453     * background has padding, this View's padding is set to the background's
17454     * padding. However, when a background is removed, this View's padding isn't
17455     * touched. If setting the padding is desired, please use
17456     * {@link #setPadding(int, int, int, int)}.
17457     *
17458     * @param background The Drawable to use as the background, or null to remove the
17459     *        background
17460     */
17461    public void setBackground(Drawable background) {
17462        //noinspection deprecation
17463        setBackgroundDrawable(background);
17464    }
17465
17466    /**
17467     * @deprecated use {@link #setBackground(Drawable)} instead
17468     */
17469    @Deprecated
17470    public void setBackgroundDrawable(Drawable background) {
17471        computeOpaqueFlags();
17472
17473        if (background == mBackground) {
17474            return;
17475        }
17476
17477        boolean requestLayout = false;
17478
17479        mBackgroundResource = 0;
17480
17481        /*
17482         * Regardless of whether we're setting a new background or not, we want
17483         * to clear the previous drawable.
17484         */
17485        if (mBackground != null) {
17486            mBackground.setCallback(null);
17487            unscheduleDrawable(mBackground);
17488        }
17489
17490        if (background != null) {
17491            Rect padding = sThreadLocal.get();
17492            if (padding == null) {
17493                padding = new Rect();
17494                sThreadLocal.set(padding);
17495            }
17496            resetResolvedDrawablesInternal();
17497            background.setLayoutDirection(getLayoutDirection());
17498            if (background.getPadding(padding)) {
17499                resetResolvedPaddingInternal();
17500                switch (background.getLayoutDirection()) {
17501                    case LAYOUT_DIRECTION_RTL:
17502                        mUserPaddingLeftInitial = padding.right;
17503                        mUserPaddingRightInitial = padding.left;
17504                        internalSetPadding(padding.right, padding.top, padding.left, padding.bottom);
17505                        break;
17506                    case LAYOUT_DIRECTION_LTR:
17507                    default:
17508                        mUserPaddingLeftInitial = padding.left;
17509                        mUserPaddingRightInitial = padding.right;
17510                        internalSetPadding(padding.left, padding.top, padding.right, padding.bottom);
17511                }
17512                mLeftPaddingDefined = false;
17513                mRightPaddingDefined = false;
17514            }
17515
17516            // Compare the minimum sizes of the old Drawable and the new.  If there isn't an old or
17517            // if it has a different minimum size, we should layout again
17518            if (mBackground == null
17519                    || mBackground.getMinimumHeight() != background.getMinimumHeight()
17520                    || mBackground.getMinimumWidth() != background.getMinimumWidth()) {
17521                requestLayout = true;
17522            }
17523
17524            background.setCallback(this);
17525            if (background.isStateful()) {
17526                background.setState(getDrawableState());
17527            }
17528            background.setVisible(getVisibility() == VISIBLE, false);
17529            mBackground = background;
17530
17531            applyBackgroundTint();
17532
17533            if ((mPrivateFlags & PFLAG_SKIP_DRAW) != 0) {
17534                mPrivateFlags &= ~PFLAG_SKIP_DRAW;
17535                requestLayout = true;
17536            }
17537        } else {
17538            /* Remove the background */
17539            mBackground = null;
17540            if ((mViewFlags & WILL_NOT_DRAW) != 0
17541                    && (mForegroundInfo == null || mForegroundInfo.mDrawable == null)) {
17542                mPrivateFlags |= PFLAG_SKIP_DRAW;
17543            }
17544
17545            /*
17546             * When the background is set, we try to apply its padding to this
17547             * View. When the background is removed, we don't touch this View's
17548             * padding. This is noted in the Javadocs. Hence, we don't need to
17549             * requestLayout(), the invalidate() below is sufficient.
17550             */
17551
17552            // The old background's minimum size could have affected this
17553            // View's layout, so let's requestLayout
17554            requestLayout = true;
17555        }
17556
17557        computeOpaqueFlags();
17558
17559        if (requestLayout) {
17560            requestLayout();
17561        }
17562
17563        mBackgroundSizeChanged = true;
17564        invalidate(true);
17565    }
17566
17567    /**
17568     * Gets the background drawable
17569     *
17570     * @return The drawable used as the background for this view, if any.
17571     *
17572     * @see #setBackground(Drawable)
17573     *
17574     * @attr ref android.R.styleable#View_background
17575     */
17576    public Drawable getBackground() {
17577        return mBackground;
17578    }
17579
17580    /**
17581     * Applies a tint to the background drawable. Does not modify the current tint
17582     * mode, which is {@link PorterDuff.Mode#SRC_IN} by default.
17583     * <p>
17584     * Subsequent calls to {@link #setBackground(Drawable)} will automatically
17585     * mutate the drawable and apply the specified tint and tint mode using
17586     * {@link Drawable#setTintList(ColorStateList)}.
17587     *
17588     * @param tint the tint to apply, may be {@code null} to clear tint
17589     *
17590     * @attr ref android.R.styleable#View_backgroundTint
17591     * @see #getBackgroundTintList()
17592     * @see Drawable#setTintList(ColorStateList)
17593     */
17594    public void setBackgroundTintList(@Nullable ColorStateList tint) {
17595        if (mBackgroundTint == null) {
17596            mBackgroundTint = new TintInfo();
17597        }
17598        mBackgroundTint.mTintList = tint;
17599        mBackgroundTint.mHasTintList = true;
17600
17601        applyBackgroundTint();
17602    }
17603
17604    /**
17605     * Return the tint applied to the background drawable, if specified.
17606     *
17607     * @return the tint applied to the background drawable
17608     * @attr ref android.R.styleable#View_backgroundTint
17609     * @see #setBackgroundTintList(ColorStateList)
17610     */
17611    @Nullable
17612    public ColorStateList getBackgroundTintList() {
17613        return mBackgroundTint != null ? mBackgroundTint.mTintList : null;
17614    }
17615
17616    /**
17617     * Specifies the blending mode used to apply the tint specified by
17618     * {@link #setBackgroundTintList(ColorStateList)}} to the background
17619     * drawable. The default mode is {@link PorterDuff.Mode#SRC_IN}.
17620     *
17621     * @param tintMode the blending mode used to apply the tint, may be
17622     *                 {@code null} to clear tint
17623     * @attr ref android.R.styleable#View_backgroundTintMode
17624     * @see #getBackgroundTintMode()
17625     * @see Drawable#setTintMode(PorterDuff.Mode)
17626     */
17627    public void setBackgroundTintMode(@Nullable PorterDuff.Mode tintMode) {
17628        if (mBackgroundTint == null) {
17629            mBackgroundTint = new TintInfo();
17630        }
17631        mBackgroundTint.mTintMode = tintMode;
17632        mBackgroundTint.mHasTintMode = true;
17633
17634        applyBackgroundTint();
17635    }
17636
17637    /**
17638     * Return the blending mode used to apply the tint to the background
17639     * drawable, if specified.
17640     *
17641     * @return the blending mode used to apply the tint to the background
17642     *         drawable
17643     * @attr ref android.R.styleable#View_backgroundTintMode
17644     * @see #setBackgroundTintMode(PorterDuff.Mode)
17645     */
17646    @Nullable
17647    public PorterDuff.Mode getBackgroundTintMode() {
17648        return mBackgroundTint != null ? mBackgroundTint.mTintMode : null;
17649    }
17650
17651    private void applyBackgroundTint() {
17652        if (mBackground != null && mBackgroundTint != null) {
17653            final TintInfo tintInfo = mBackgroundTint;
17654            if (tintInfo.mHasTintList || tintInfo.mHasTintMode) {
17655                mBackground = mBackground.mutate();
17656
17657                if (tintInfo.mHasTintList) {
17658                    mBackground.setTintList(tintInfo.mTintList);
17659                }
17660
17661                if (tintInfo.mHasTintMode) {
17662                    mBackground.setTintMode(tintInfo.mTintMode);
17663                }
17664
17665                // The drawable (or one of its children) may not have been
17666                // stateful before applying the tint, so let's try again.
17667                if (mBackground.isStateful()) {
17668                    mBackground.setState(getDrawableState());
17669                }
17670            }
17671        }
17672    }
17673
17674    /**
17675     * Returns the drawable used as the foreground of this View. The
17676     * foreground drawable, if non-null, is always drawn on top of the view's content.
17677     *
17678     * @return a Drawable or null if no foreground was set
17679     *
17680     * @see #onDrawForeground(Canvas)
17681     */
17682    public Drawable getForeground() {
17683        return mForegroundInfo != null ? mForegroundInfo.mDrawable : null;
17684    }
17685
17686    /**
17687     * Supply a Drawable that is to be rendered on top of all of the content in the view.
17688     *
17689     * @param foreground the Drawable to be drawn on top of the children
17690     *
17691     * @attr ref android.R.styleable#View_foreground
17692     */
17693    public void setForeground(Drawable foreground) {
17694        if (mForegroundInfo == null) {
17695            if (foreground == null) {
17696                // Nothing to do.
17697                return;
17698            }
17699            mForegroundInfo = new ForegroundInfo();
17700        }
17701
17702        if (foreground == mForegroundInfo.mDrawable) {
17703            // Nothing to do
17704            return;
17705        }
17706
17707        if (mForegroundInfo.mDrawable != null) {
17708            mForegroundInfo.mDrawable.setCallback(null);
17709            unscheduleDrawable(mForegroundInfo.mDrawable);
17710        }
17711
17712        mForegroundInfo.mDrawable = foreground;
17713        mForegroundInfo.mBoundsChanged = true;
17714        if (foreground != null) {
17715            if ((mPrivateFlags & PFLAG_SKIP_DRAW) != 0) {
17716                mPrivateFlags &= ~PFLAG_SKIP_DRAW;
17717            }
17718            foreground.setCallback(this);
17719            foreground.setLayoutDirection(getLayoutDirection());
17720            if (foreground.isStateful()) {
17721                foreground.setState(getDrawableState());
17722            }
17723            applyForegroundTint();
17724        } else if ((mViewFlags & WILL_NOT_DRAW) != 0 && mBackground == null) {
17725            mPrivateFlags |= PFLAG_SKIP_DRAW;
17726        }
17727        requestLayout();
17728        invalidate();
17729    }
17730
17731    /**
17732     * Magic bit used to support features of framework-internal window decor implementation details.
17733     * This used to live exclusively in FrameLayout.
17734     *
17735     * @return true if the foreground should draw inside the padding region or false
17736     *         if it should draw inset by the view's padding
17737     * @hide internal use only; only used by FrameLayout and internal screen layouts.
17738     */
17739    public boolean isForegroundInsidePadding() {
17740        return mForegroundInfo != null ? mForegroundInfo.mInsidePadding : true;
17741    }
17742
17743    /**
17744     * Describes how the foreground is positioned.
17745     *
17746     * @return foreground gravity.
17747     *
17748     * @see #setForegroundGravity(int)
17749     *
17750     * @attr ref android.R.styleable#View_foregroundGravity
17751     */
17752    public int getForegroundGravity() {
17753        return mForegroundInfo != null ? mForegroundInfo.mGravity
17754                : Gravity.START | Gravity.TOP;
17755    }
17756
17757    /**
17758     * Describes how the foreground is positioned. Defaults to START and TOP.
17759     *
17760     * @param gravity see {@link android.view.Gravity}
17761     *
17762     * @see #getForegroundGravity()
17763     *
17764     * @attr ref android.R.styleable#View_foregroundGravity
17765     */
17766    public void setForegroundGravity(int gravity) {
17767        if (mForegroundInfo == null) {
17768            mForegroundInfo = new ForegroundInfo();
17769        }
17770
17771        if (mForegroundInfo.mGravity != gravity) {
17772            if ((gravity & Gravity.RELATIVE_HORIZONTAL_GRAVITY_MASK) == 0) {
17773                gravity |= Gravity.START;
17774            }
17775
17776            if ((gravity & Gravity.VERTICAL_GRAVITY_MASK) == 0) {
17777                gravity |= Gravity.TOP;
17778            }
17779
17780            mForegroundInfo.mGravity = gravity;
17781            requestLayout();
17782        }
17783    }
17784
17785    /**
17786     * Applies a tint to the foreground drawable. Does not modify the current tint
17787     * mode, which is {@link PorterDuff.Mode#SRC_IN} by default.
17788     * <p>
17789     * Subsequent calls to {@link #setForeground(Drawable)} will automatically
17790     * mutate the drawable and apply the specified tint and tint mode using
17791     * {@link Drawable#setTintList(ColorStateList)}.
17792     *
17793     * @param tint the tint to apply, may be {@code null} to clear tint
17794     *
17795     * @attr ref android.R.styleable#View_foregroundTint
17796     * @see #getForegroundTintList()
17797     * @see Drawable#setTintList(ColorStateList)
17798     */
17799    public void setForegroundTintList(@Nullable ColorStateList tint) {
17800        if (mForegroundInfo == null) {
17801            mForegroundInfo = new ForegroundInfo();
17802        }
17803        if (mForegroundInfo.mTintInfo == null) {
17804            mForegroundInfo.mTintInfo = new TintInfo();
17805        }
17806        mForegroundInfo.mTintInfo.mTintList = tint;
17807        mForegroundInfo.mTintInfo.mHasTintList = true;
17808
17809        applyForegroundTint();
17810    }
17811
17812    /**
17813     * Return the tint applied to the foreground drawable, if specified.
17814     *
17815     * @return the tint applied to the foreground drawable
17816     * @attr ref android.R.styleable#View_foregroundTint
17817     * @see #setForegroundTintList(ColorStateList)
17818     */
17819    @Nullable
17820    public ColorStateList getForegroundTintList() {
17821        return mForegroundInfo != null && mForegroundInfo.mTintInfo != null
17822                ? mForegroundInfo.mTintInfo.mTintList : null;
17823    }
17824
17825    /**
17826     * Specifies the blending mode used to apply the tint specified by
17827     * {@link #setForegroundTintList(ColorStateList)}} to the background
17828     * drawable. The default mode is {@link PorterDuff.Mode#SRC_IN}.
17829     *
17830     * @param tintMode the blending mode used to apply the tint, may be
17831     *                 {@code null} to clear tint
17832     * @attr ref android.R.styleable#View_foregroundTintMode
17833     * @see #getForegroundTintMode()
17834     * @see Drawable#setTintMode(PorterDuff.Mode)
17835     */
17836    public void setForegroundTintMode(@Nullable PorterDuff.Mode tintMode) {
17837        if (mForegroundInfo == null) {
17838            mForegroundInfo = new ForegroundInfo();
17839        }
17840        if (mForegroundInfo.mTintInfo == null) {
17841            mForegroundInfo.mTintInfo = new TintInfo();
17842        }
17843        mForegroundInfo.mTintInfo.mTintMode = tintMode;
17844        mForegroundInfo.mTintInfo.mHasTintMode = true;
17845
17846        applyForegroundTint();
17847    }
17848
17849    /**
17850     * Return the blending mode used to apply the tint to the foreground
17851     * drawable, if specified.
17852     *
17853     * @return the blending mode used to apply the tint to the foreground
17854     *         drawable
17855     * @attr ref android.R.styleable#View_foregroundTintMode
17856     * @see #setForegroundTintMode(PorterDuff.Mode)
17857     */
17858    @Nullable
17859    public PorterDuff.Mode getForegroundTintMode() {
17860        return mForegroundInfo != null && mForegroundInfo.mTintInfo != null
17861                ? mForegroundInfo.mTintInfo.mTintMode : null;
17862    }
17863
17864    private void applyForegroundTint() {
17865        if (mForegroundInfo != null && mForegroundInfo.mDrawable != null
17866                && mForegroundInfo.mTintInfo != null) {
17867            final TintInfo tintInfo = mForegroundInfo.mTintInfo;
17868            if (tintInfo.mHasTintList || tintInfo.mHasTintMode) {
17869                mForegroundInfo.mDrawable = mForegroundInfo.mDrawable.mutate();
17870
17871                if (tintInfo.mHasTintList) {
17872                    mForegroundInfo.mDrawable.setTintList(tintInfo.mTintList);
17873                }
17874
17875                if (tintInfo.mHasTintMode) {
17876                    mForegroundInfo.mDrawable.setTintMode(tintInfo.mTintMode);
17877                }
17878
17879                // The drawable (or one of its children) may not have been
17880                // stateful before applying the tint, so let's try again.
17881                if (mForegroundInfo.mDrawable.isStateful()) {
17882                    mForegroundInfo.mDrawable.setState(getDrawableState());
17883                }
17884            }
17885        }
17886    }
17887
17888    /**
17889     * Draw any foreground content for this view.
17890     *
17891     * <p>Foreground content may consist of scroll bars, a {@link #setForeground foreground}
17892     * drawable or other view-specific decorations. The foreground is drawn on top of the
17893     * primary view content.</p>
17894     *
17895     * @param canvas canvas to draw into
17896     */
17897    public void onDrawForeground(Canvas canvas) {
17898        onDrawScrollIndicators(canvas);
17899        onDrawScrollBars(canvas);
17900
17901        final Drawable foreground = mForegroundInfo != null ? mForegroundInfo.mDrawable : null;
17902        if (foreground != null) {
17903            if (mForegroundInfo.mBoundsChanged) {
17904                mForegroundInfo.mBoundsChanged = false;
17905                final Rect selfBounds = mForegroundInfo.mSelfBounds;
17906                final Rect overlayBounds = mForegroundInfo.mOverlayBounds;
17907
17908                if (mForegroundInfo.mInsidePadding) {
17909                    selfBounds.set(0, 0, getWidth(), getHeight());
17910                } else {
17911                    selfBounds.set(getPaddingLeft(), getPaddingTop(),
17912                            getWidth() - getPaddingRight(), getHeight() - getPaddingBottom());
17913                }
17914
17915                final int ld = getLayoutDirection();
17916                Gravity.apply(mForegroundInfo.mGravity, foreground.getIntrinsicWidth(),
17917                        foreground.getIntrinsicHeight(), selfBounds, overlayBounds, ld);
17918                foreground.setBounds(overlayBounds);
17919            }
17920
17921            foreground.draw(canvas);
17922        }
17923    }
17924
17925    /**
17926     * Sets the padding. The view may add on the space required to display
17927     * the scrollbars, depending on the style and visibility of the scrollbars.
17928     * So the values returned from {@link #getPaddingLeft}, {@link #getPaddingTop},
17929     * {@link #getPaddingRight} and {@link #getPaddingBottom} may be different
17930     * from the values set in this call.
17931     *
17932     * @attr ref android.R.styleable#View_padding
17933     * @attr ref android.R.styleable#View_paddingBottom
17934     * @attr ref android.R.styleable#View_paddingLeft
17935     * @attr ref android.R.styleable#View_paddingRight
17936     * @attr ref android.R.styleable#View_paddingTop
17937     * @param left the left padding in pixels
17938     * @param top the top padding in pixels
17939     * @param right the right padding in pixels
17940     * @param bottom the bottom padding in pixels
17941     */
17942    public void setPadding(int left, int top, int right, int bottom) {
17943        resetResolvedPaddingInternal();
17944
17945        mUserPaddingStart = UNDEFINED_PADDING;
17946        mUserPaddingEnd = UNDEFINED_PADDING;
17947
17948        mUserPaddingLeftInitial = left;
17949        mUserPaddingRightInitial = right;
17950
17951        mLeftPaddingDefined = true;
17952        mRightPaddingDefined = true;
17953
17954        internalSetPadding(left, top, right, bottom);
17955    }
17956
17957    /**
17958     * @hide
17959     */
17960    protected void internalSetPadding(int left, int top, int right, int bottom) {
17961        mUserPaddingLeft = left;
17962        mUserPaddingRight = right;
17963        mUserPaddingBottom = bottom;
17964
17965        final int viewFlags = mViewFlags;
17966        boolean changed = false;
17967
17968        // Common case is there are no scroll bars.
17969        if ((viewFlags & (SCROLLBARS_VERTICAL|SCROLLBARS_HORIZONTAL)) != 0) {
17970            if ((viewFlags & SCROLLBARS_VERTICAL) != 0) {
17971                final int offset = (viewFlags & SCROLLBARS_INSET_MASK) == 0
17972                        ? 0 : getVerticalScrollbarWidth();
17973                switch (mVerticalScrollbarPosition) {
17974                    case SCROLLBAR_POSITION_DEFAULT:
17975                        if (isLayoutRtl()) {
17976                            left += offset;
17977                        } else {
17978                            right += offset;
17979                        }
17980                        break;
17981                    case SCROLLBAR_POSITION_RIGHT:
17982                        right += offset;
17983                        break;
17984                    case SCROLLBAR_POSITION_LEFT:
17985                        left += offset;
17986                        break;
17987                }
17988            }
17989            if ((viewFlags & SCROLLBARS_HORIZONTAL) != 0) {
17990                bottom += (viewFlags & SCROLLBARS_INSET_MASK) == 0
17991                        ? 0 : getHorizontalScrollbarHeight();
17992            }
17993        }
17994
17995        if (mPaddingLeft != left) {
17996            changed = true;
17997            mPaddingLeft = left;
17998        }
17999        if (mPaddingTop != top) {
18000            changed = true;
18001            mPaddingTop = top;
18002        }
18003        if (mPaddingRight != right) {
18004            changed = true;
18005            mPaddingRight = right;
18006        }
18007        if (mPaddingBottom != bottom) {
18008            changed = true;
18009            mPaddingBottom = bottom;
18010        }
18011
18012        if (changed) {
18013            requestLayout();
18014            invalidateOutline();
18015        }
18016    }
18017
18018    /**
18019     * Sets the relative padding. The view may add on the space required to display
18020     * the scrollbars, depending on the style and visibility of the scrollbars.
18021     * So the values returned from {@link #getPaddingStart}, {@link #getPaddingTop},
18022     * {@link #getPaddingEnd} and {@link #getPaddingBottom} may be different
18023     * from the values set in this call.
18024     *
18025     * @attr ref android.R.styleable#View_padding
18026     * @attr ref android.R.styleable#View_paddingBottom
18027     * @attr ref android.R.styleable#View_paddingStart
18028     * @attr ref android.R.styleable#View_paddingEnd
18029     * @attr ref android.R.styleable#View_paddingTop
18030     * @param start the start padding in pixels
18031     * @param top the top padding in pixels
18032     * @param end the end padding in pixels
18033     * @param bottom the bottom padding in pixels
18034     */
18035    public void setPaddingRelative(int start, int top, int end, int bottom) {
18036        resetResolvedPaddingInternal();
18037
18038        mUserPaddingStart = start;
18039        mUserPaddingEnd = end;
18040        mLeftPaddingDefined = true;
18041        mRightPaddingDefined = true;
18042
18043        switch(getLayoutDirection()) {
18044            case LAYOUT_DIRECTION_RTL:
18045                mUserPaddingLeftInitial = end;
18046                mUserPaddingRightInitial = start;
18047                internalSetPadding(end, top, start, bottom);
18048                break;
18049            case LAYOUT_DIRECTION_LTR:
18050            default:
18051                mUserPaddingLeftInitial = start;
18052                mUserPaddingRightInitial = end;
18053                internalSetPadding(start, top, end, bottom);
18054        }
18055    }
18056
18057    /**
18058     * Returns the top padding of this view.
18059     *
18060     * @return the top padding in pixels
18061     */
18062    public int getPaddingTop() {
18063        return mPaddingTop;
18064    }
18065
18066    /**
18067     * Returns the bottom padding of this view. If there are inset and enabled
18068     * scrollbars, this value may include the space required to display the
18069     * scrollbars as well.
18070     *
18071     * @return the bottom padding in pixels
18072     */
18073    public int getPaddingBottom() {
18074        return mPaddingBottom;
18075    }
18076
18077    /**
18078     * Returns the left padding of this view. If there are inset and enabled
18079     * scrollbars, this value may include the space required to display the
18080     * scrollbars as well.
18081     *
18082     * @return the left padding in pixels
18083     */
18084    public int getPaddingLeft() {
18085        if (!isPaddingResolved()) {
18086            resolvePadding();
18087        }
18088        return mPaddingLeft;
18089    }
18090
18091    /**
18092     * Returns the start padding of this view depending on its resolved layout direction.
18093     * If there are inset and enabled scrollbars, this value may include the space
18094     * required to display the scrollbars as well.
18095     *
18096     * @return the start padding in pixels
18097     */
18098    public int getPaddingStart() {
18099        if (!isPaddingResolved()) {
18100            resolvePadding();
18101        }
18102        return (getLayoutDirection() == LAYOUT_DIRECTION_RTL) ?
18103                mPaddingRight : mPaddingLeft;
18104    }
18105
18106    /**
18107     * Returns the right padding of this view. If there are inset and enabled
18108     * scrollbars, this value may include the space required to display the
18109     * scrollbars as well.
18110     *
18111     * @return the right padding in pixels
18112     */
18113    public int getPaddingRight() {
18114        if (!isPaddingResolved()) {
18115            resolvePadding();
18116        }
18117        return mPaddingRight;
18118    }
18119
18120    /**
18121     * Returns the end padding of this view depending on its resolved layout direction.
18122     * If there are inset and enabled scrollbars, this value may include the space
18123     * required to display the scrollbars as well.
18124     *
18125     * @return the end padding in pixels
18126     */
18127    public int getPaddingEnd() {
18128        if (!isPaddingResolved()) {
18129            resolvePadding();
18130        }
18131        return (getLayoutDirection() == LAYOUT_DIRECTION_RTL) ?
18132                mPaddingLeft : mPaddingRight;
18133    }
18134
18135    /**
18136     * Return if the padding has been set through relative values
18137     * {@link #setPaddingRelative(int, int, int, int)} or through
18138     * @attr ref android.R.styleable#View_paddingStart or
18139     * @attr ref android.R.styleable#View_paddingEnd
18140     *
18141     * @return true if the padding is relative or false if it is not.
18142     */
18143    public boolean isPaddingRelative() {
18144        return (mUserPaddingStart != UNDEFINED_PADDING || mUserPaddingEnd != UNDEFINED_PADDING);
18145    }
18146
18147    Insets computeOpticalInsets() {
18148        return (mBackground == null) ? Insets.NONE : mBackground.getOpticalInsets();
18149    }
18150
18151    /**
18152     * @hide
18153     */
18154    public void resetPaddingToInitialValues() {
18155        if (isRtlCompatibilityMode()) {
18156            mPaddingLeft = mUserPaddingLeftInitial;
18157            mPaddingRight = mUserPaddingRightInitial;
18158            return;
18159        }
18160        if (isLayoutRtl()) {
18161            mPaddingLeft = (mUserPaddingEnd >= 0) ? mUserPaddingEnd : mUserPaddingLeftInitial;
18162            mPaddingRight = (mUserPaddingStart >= 0) ? mUserPaddingStart : mUserPaddingRightInitial;
18163        } else {
18164            mPaddingLeft = (mUserPaddingStart >= 0) ? mUserPaddingStart : mUserPaddingLeftInitial;
18165            mPaddingRight = (mUserPaddingEnd >= 0) ? mUserPaddingEnd : mUserPaddingRightInitial;
18166        }
18167    }
18168
18169    /**
18170     * @hide
18171     */
18172    public Insets getOpticalInsets() {
18173        if (mLayoutInsets == null) {
18174            mLayoutInsets = computeOpticalInsets();
18175        }
18176        return mLayoutInsets;
18177    }
18178
18179    /**
18180     * Set this view's optical insets.
18181     *
18182     * <p>This method should be treated similarly to setMeasuredDimension and not as a general
18183     * property. Views that compute their own optical insets should call it as part of measurement.
18184     * This method does not request layout. If you are setting optical insets outside of
18185     * measure/layout itself you will want to call requestLayout() yourself.
18186     * </p>
18187     * @hide
18188     */
18189    public void setOpticalInsets(Insets insets) {
18190        mLayoutInsets = insets;
18191    }
18192
18193    /**
18194     * Changes the selection state of this view. A view can be selected or not.
18195     * Note that selection is not the same as focus. Views are typically
18196     * selected in the context of an AdapterView like ListView or GridView;
18197     * the selected view is the view that is highlighted.
18198     *
18199     * @param selected true if the view must be selected, false otherwise
18200     */
18201    public void setSelected(boolean selected) {
18202        //noinspection DoubleNegation
18203        if (((mPrivateFlags & PFLAG_SELECTED) != 0) != selected) {
18204            mPrivateFlags = (mPrivateFlags & ~PFLAG_SELECTED) | (selected ? PFLAG_SELECTED : 0);
18205            if (!selected) resetPressedState();
18206            invalidate(true);
18207            refreshDrawableState();
18208            dispatchSetSelected(selected);
18209            if (selected) {
18210                sendAccessibilityEvent(AccessibilityEvent.TYPE_VIEW_SELECTED);
18211            } else {
18212                notifyViewAccessibilityStateChangedIfNeeded(
18213                        AccessibilityEvent.CONTENT_CHANGE_TYPE_UNDEFINED);
18214            }
18215        }
18216    }
18217
18218    /**
18219     * Dispatch setSelected to all of this View's children.
18220     *
18221     * @see #setSelected(boolean)
18222     *
18223     * @param selected The new selected state
18224     */
18225    protected void dispatchSetSelected(boolean selected) {
18226    }
18227
18228    /**
18229     * Indicates the selection state of this view.
18230     *
18231     * @return true if the view is selected, false otherwise
18232     */
18233    @ViewDebug.ExportedProperty
18234    public boolean isSelected() {
18235        return (mPrivateFlags & PFLAG_SELECTED) != 0;
18236    }
18237
18238    /**
18239     * Changes the activated state of this view. A view can be activated or not.
18240     * Note that activation is not the same as selection.  Selection is
18241     * a transient property, representing the view (hierarchy) the user is
18242     * currently interacting with.  Activation is a longer-term state that the
18243     * user can move views in and out of.  For example, in a list view with
18244     * single or multiple selection enabled, the views in the current selection
18245     * set are activated.  (Um, yeah, we are deeply sorry about the terminology
18246     * here.)  The activated state is propagated down to children of the view it
18247     * is set on.
18248     *
18249     * @param activated true if the view must be activated, false otherwise
18250     */
18251    public void setActivated(boolean activated) {
18252        //noinspection DoubleNegation
18253        if (((mPrivateFlags & PFLAG_ACTIVATED) != 0) != activated) {
18254            mPrivateFlags = (mPrivateFlags & ~PFLAG_ACTIVATED) | (activated ? PFLAG_ACTIVATED : 0);
18255            invalidate(true);
18256            refreshDrawableState();
18257            dispatchSetActivated(activated);
18258        }
18259    }
18260
18261    /**
18262     * Dispatch setActivated to all of this View's children.
18263     *
18264     * @see #setActivated(boolean)
18265     *
18266     * @param activated The new activated state
18267     */
18268    protected void dispatchSetActivated(boolean activated) {
18269    }
18270
18271    /**
18272     * Indicates the activation state of this view.
18273     *
18274     * @return true if the view is activated, false otherwise
18275     */
18276    @ViewDebug.ExportedProperty
18277    public boolean isActivated() {
18278        return (mPrivateFlags & PFLAG_ACTIVATED) != 0;
18279    }
18280
18281    /**
18282     * Returns the ViewTreeObserver for this view's hierarchy. The view tree
18283     * observer can be used to get notifications when global events, like
18284     * layout, happen.
18285     *
18286     * The returned ViewTreeObserver observer is not guaranteed to remain
18287     * valid for the lifetime of this View. If the caller of this method keeps
18288     * a long-lived reference to ViewTreeObserver, it should always check for
18289     * the return value of {@link ViewTreeObserver#isAlive()}.
18290     *
18291     * @return The ViewTreeObserver for this view's hierarchy.
18292     */
18293    public ViewTreeObserver getViewTreeObserver() {
18294        if (mAttachInfo != null) {
18295            return mAttachInfo.mTreeObserver;
18296        }
18297        if (mFloatingTreeObserver == null) {
18298            mFloatingTreeObserver = new ViewTreeObserver();
18299        }
18300        return mFloatingTreeObserver;
18301    }
18302
18303    /**
18304     * <p>Finds the topmost view in the current view hierarchy.</p>
18305     *
18306     * @return the topmost view containing this view
18307     */
18308    public View getRootView() {
18309        if (mAttachInfo != null) {
18310            final View v = mAttachInfo.mRootView;
18311            if (v != null) {
18312                return v;
18313            }
18314        }
18315
18316        View parent = this;
18317
18318        while (parent.mParent != null && parent.mParent instanceof View) {
18319            parent = (View) parent.mParent;
18320        }
18321
18322        return parent;
18323    }
18324
18325    /**
18326     * Transforms a motion event from view-local coordinates to on-screen
18327     * coordinates.
18328     *
18329     * @param ev the view-local motion event
18330     * @return false if the transformation could not be applied
18331     * @hide
18332     */
18333    public boolean toGlobalMotionEvent(MotionEvent ev) {
18334        final AttachInfo info = mAttachInfo;
18335        if (info == null) {
18336            return false;
18337        }
18338
18339        final Matrix m = info.mTmpMatrix;
18340        m.set(Matrix.IDENTITY_MATRIX);
18341        transformMatrixToGlobal(m);
18342        ev.transform(m);
18343        return true;
18344    }
18345
18346    /**
18347     * Transforms a motion event from on-screen coordinates to view-local
18348     * coordinates.
18349     *
18350     * @param ev the on-screen motion event
18351     * @return false if the transformation could not be applied
18352     * @hide
18353     */
18354    public boolean toLocalMotionEvent(MotionEvent ev) {
18355        final AttachInfo info = mAttachInfo;
18356        if (info == null) {
18357            return false;
18358        }
18359
18360        final Matrix m = info.mTmpMatrix;
18361        m.set(Matrix.IDENTITY_MATRIX);
18362        transformMatrixToLocal(m);
18363        ev.transform(m);
18364        return true;
18365    }
18366
18367    /**
18368     * Modifies the input matrix such that it maps view-local coordinates to
18369     * on-screen coordinates.
18370     *
18371     * @param m input matrix to modify
18372     * @hide
18373     */
18374    public void transformMatrixToGlobal(Matrix m) {
18375        final ViewParent parent = mParent;
18376        if (parent instanceof View) {
18377            final View vp = (View) parent;
18378            vp.transformMatrixToGlobal(m);
18379            m.preTranslate(-vp.mScrollX, -vp.mScrollY);
18380        } else if (parent instanceof ViewRootImpl) {
18381            final ViewRootImpl vr = (ViewRootImpl) parent;
18382            vr.transformMatrixToGlobal(m);
18383            m.preTranslate(0, -vr.mCurScrollY);
18384        }
18385
18386        m.preTranslate(mLeft, mTop);
18387
18388        if (!hasIdentityMatrix()) {
18389            m.preConcat(getMatrix());
18390        }
18391    }
18392
18393    /**
18394     * Modifies the input matrix such that it maps on-screen coordinates to
18395     * view-local coordinates.
18396     *
18397     * @param m input matrix to modify
18398     * @hide
18399     */
18400    public void transformMatrixToLocal(Matrix m) {
18401        final ViewParent parent = mParent;
18402        if (parent instanceof View) {
18403            final View vp = (View) parent;
18404            vp.transformMatrixToLocal(m);
18405            m.postTranslate(vp.mScrollX, vp.mScrollY);
18406        } else if (parent instanceof ViewRootImpl) {
18407            final ViewRootImpl vr = (ViewRootImpl) parent;
18408            vr.transformMatrixToLocal(m);
18409            m.postTranslate(0, vr.mCurScrollY);
18410        }
18411
18412        m.postTranslate(-mLeft, -mTop);
18413
18414        if (!hasIdentityMatrix()) {
18415            m.postConcat(getInverseMatrix());
18416        }
18417    }
18418
18419    /**
18420     * @hide
18421     */
18422    @ViewDebug.ExportedProperty(category = "layout", indexMapping = {
18423            @ViewDebug.IntToString(from = 0, to = "x"),
18424            @ViewDebug.IntToString(from = 1, to = "y")
18425    })
18426    public int[] getLocationOnScreen() {
18427        int[] location = new int[2];
18428        getLocationOnScreen(location);
18429        return location;
18430    }
18431
18432    /**
18433     * <p>Computes the coordinates of this view on the screen. The argument
18434     * must be an array of two integers. After the method returns, the array
18435     * contains the x and y location in that order.</p>
18436     *
18437     * @param location an array of two integers in which to hold the coordinates
18438     */
18439    public void getLocationOnScreen(@Size(2) int[] location) {
18440        getLocationInWindow(location);
18441
18442        final AttachInfo info = mAttachInfo;
18443        if (info != null) {
18444            location[0] += info.mWindowLeft;
18445            location[1] += info.mWindowTop;
18446        }
18447    }
18448
18449    /**
18450     * <p>Computes the coordinates of this view in its window. The argument
18451     * must be an array of two integers. After the method returns, the array
18452     * contains the x and y location in that order.</p>
18453     *
18454     * @param location an array of two integers in which to hold the coordinates
18455     */
18456    public void getLocationInWindow(@Size(2) int[] location) {
18457        if (location == null || location.length < 2) {
18458            throw new IllegalArgumentException("location must be an array of two integers");
18459        }
18460
18461        if (mAttachInfo == null) {
18462            // When the view is not attached to a window, this method does not make sense
18463            location[0] = location[1] = 0;
18464            return;
18465        }
18466
18467        float[] position = mAttachInfo.mTmpTransformLocation;
18468        position[0] = position[1] = 0.0f;
18469
18470        if (!hasIdentityMatrix()) {
18471            getMatrix().mapPoints(position);
18472        }
18473
18474        position[0] += mLeft;
18475        position[1] += mTop;
18476
18477        ViewParent viewParent = mParent;
18478        while (viewParent instanceof View) {
18479            final View view = (View) viewParent;
18480
18481            position[0] -= view.mScrollX;
18482            position[1] -= view.mScrollY;
18483
18484            if (!view.hasIdentityMatrix()) {
18485                view.getMatrix().mapPoints(position);
18486            }
18487
18488            position[0] += view.mLeft;
18489            position[1] += view.mTop;
18490
18491            viewParent = view.mParent;
18492         }
18493
18494        if (viewParent instanceof ViewRootImpl) {
18495            // *cough*
18496            final ViewRootImpl vr = (ViewRootImpl) viewParent;
18497            position[1] -= vr.mCurScrollY;
18498        }
18499
18500        location[0] = (int) (position[0] + 0.5f);
18501        location[1] = (int) (position[1] + 0.5f);
18502    }
18503
18504    /**
18505     * {@hide}
18506     * @param id the id of the view to be found
18507     * @return the view of the specified id, null if cannot be found
18508     */
18509    protected View findViewTraversal(@IdRes int id) {
18510        if (id == mID) {
18511            return this;
18512        }
18513        return null;
18514    }
18515
18516    /**
18517     * {@hide}
18518     * @param tag the tag of the view to be found
18519     * @return the view of specified tag, null if cannot be found
18520     */
18521    protected View findViewWithTagTraversal(Object tag) {
18522        if (tag != null && tag.equals(mTag)) {
18523            return this;
18524        }
18525        return null;
18526    }
18527
18528    /**
18529     * {@hide}
18530     * @param predicate The predicate to evaluate.
18531     * @param childToSkip If not null, ignores this child during the recursive traversal.
18532     * @return The first view that matches the predicate or null.
18533     */
18534    protected View findViewByPredicateTraversal(Predicate<View> predicate, View childToSkip) {
18535        if (predicate.apply(this)) {
18536            return this;
18537        }
18538        return null;
18539    }
18540
18541    /**
18542     * Look for a child view with the given id.  If this view has the given
18543     * id, return this view.
18544     *
18545     * @param id The id to search for.
18546     * @return The view that has the given id in the hierarchy or null
18547     */
18548    @Nullable
18549    public final View findViewById(@IdRes int id) {
18550        if (id < 0) {
18551            return null;
18552        }
18553        return findViewTraversal(id);
18554    }
18555
18556    /**
18557     * Finds a view by its unuque and stable accessibility id.
18558     *
18559     * @param accessibilityId The searched accessibility id.
18560     * @return The found view.
18561     */
18562    final View findViewByAccessibilityId(int accessibilityId) {
18563        if (accessibilityId < 0) {
18564            return null;
18565        }
18566        View view = findViewByAccessibilityIdTraversal(accessibilityId);
18567        if (view != null) {
18568            return view.includeForAccessibility() ? view : null;
18569        }
18570        return null;
18571    }
18572
18573    /**
18574     * Performs the traversal to find a view by its unuque and stable accessibility id.
18575     *
18576     * <strong>Note:</strong>This method does not stop at the root namespace
18577     * boundary since the user can touch the screen at an arbitrary location
18578     * potentially crossing the root namespace bounday which will send an
18579     * accessibility event to accessibility services and they should be able
18580     * to obtain the event source. Also accessibility ids are guaranteed to be
18581     * unique in the window.
18582     *
18583     * @param accessibilityId The accessibility id.
18584     * @return The found view.
18585     *
18586     * @hide
18587     */
18588    public View findViewByAccessibilityIdTraversal(int accessibilityId) {
18589        if (getAccessibilityViewId() == accessibilityId) {
18590            return this;
18591        }
18592        return null;
18593    }
18594
18595    /**
18596     * Look for a child view with the given tag.  If this view has the given
18597     * tag, return this view.
18598     *
18599     * @param tag The tag to search for, using "tag.equals(getTag())".
18600     * @return The View that has the given tag in the hierarchy or null
18601     */
18602    public final View findViewWithTag(Object tag) {
18603        if (tag == null) {
18604            return null;
18605        }
18606        return findViewWithTagTraversal(tag);
18607    }
18608
18609    /**
18610     * {@hide}
18611     * Look for a child view that matches the specified predicate.
18612     * If this view matches the predicate, return this view.
18613     *
18614     * @param predicate The predicate to evaluate.
18615     * @return The first view that matches the predicate or null.
18616     */
18617    public final View findViewByPredicate(Predicate<View> predicate) {
18618        return findViewByPredicateTraversal(predicate, null);
18619    }
18620
18621    /**
18622     * {@hide}
18623     * Look for a child view that matches the specified predicate,
18624     * starting with the specified view and its descendents and then
18625     * recusively searching the ancestors and siblings of that view
18626     * until this view is reached.
18627     *
18628     * This method is useful in cases where the predicate does not match
18629     * a single unique view (perhaps multiple views use the same id)
18630     * and we are trying to find the view that is "closest" in scope to the
18631     * starting view.
18632     *
18633     * @param start The view to start from.
18634     * @param predicate The predicate to evaluate.
18635     * @return The first view that matches the predicate or null.
18636     */
18637    public final View findViewByPredicateInsideOut(View start, Predicate<View> predicate) {
18638        View childToSkip = null;
18639        for (;;) {
18640            View view = start.findViewByPredicateTraversal(predicate, childToSkip);
18641            if (view != null || start == this) {
18642                return view;
18643            }
18644
18645            ViewParent parent = start.getParent();
18646            if (parent == null || !(parent instanceof View)) {
18647                return null;
18648            }
18649
18650            childToSkip = start;
18651            start = (View) parent;
18652        }
18653    }
18654
18655    /**
18656     * Sets the identifier for this view. The identifier does not have to be
18657     * unique in this view's hierarchy. The identifier should be a positive
18658     * number.
18659     *
18660     * @see #NO_ID
18661     * @see #getId()
18662     * @see #findViewById(int)
18663     *
18664     * @param id a number used to identify the view
18665     *
18666     * @attr ref android.R.styleable#View_id
18667     */
18668    public void setId(@IdRes int id) {
18669        mID = id;
18670        if (mID == View.NO_ID && mLabelForId != View.NO_ID) {
18671            mID = generateViewId();
18672        }
18673    }
18674
18675    /**
18676     * {@hide}
18677     *
18678     * @param isRoot true if the view belongs to the root namespace, false
18679     *        otherwise
18680     */
18681    public void setIsRootNamespace(boolean isRoot) {
18682        if (isRoot) {
18683            mPrivateFlags |= PFLAG_IS_ROOT_NAMESPACE;
18684        } else {
18685            mPrivateFlags &= ~PFLAG_IS_ROOT_NAMESPACE;
18686        }
18687    }
18688
18689    /**
18690     * {@hide}
18691     *
18692     * @return true if the view belongs to the root namespace, false otherwise
18693     */
18694    public boolean isRootNamespace() {
18695        return (mPrivateFlags&PFLAG_IS_ROOT_NAMESPACE) != 0;
18696    }
18697
18698    /**
18699     * Returns this view's identifier.
18700     *
18701     * @return a positive integer used to identify the view or {@link #NO_ID}
18702     *         if the view has no ID
18703     *
18704     * @see #setId(int)
18705     * @see #findViewById(int)
18706     * @attr ref android.R.styleable#View_id
18707     */
18708    @IdRes
18709    @ViewDebug.CapturedViewProperty
18710    public int getId() {
18711        return mID;
18712    }
18713
18714    /**
18715     * Returns this view's tag.
18716     *
18717     * @return the Object stored in this view as a tag, or {@code null} if not
18718     *         set
18719     *
18720     * @see #setTag(Object)
18721     * @see #getTag(int)
18722     */
18723    @ViewDebug.ExportedProperty
18724    public Object getTag() {
18725        return mTag;
18726    }
18727
18728    /**
18729     * Sets the tag associated with this view. A tag can be used to mark
18730     * a view in its hierarchy and does not have to be unique within the
18731     * hierarchy. Tags can also be used to store data within a view without
18732     * resorting to another data structure.
18733     *
18734     * @param tag an Object to tag the view with
18735     *
18736     * @see #getTag()
18737     * @see #setTag(int, Object)
18738     */
18739    public void setTag(final Object tag) {
18740        mTag = tag;
18741    }
18742
18743    /**
18744     * Returns the tag associated with this view and the specified key.
18745     *
18746     * @param key The key identifying the tag
18747     *
18748     * @return the Object stored in this view as a tag, or {@code null} if not
18749     *         set
18750     *
18751     * @see #setTag(int, Object)
18752     * @see #getTag()
18753     */
18754    public Object getTag(int key) {
18755        if (mKeyedTags != null) return mKeyedTags.get(key);
18756        return null;
18757    }
18758
18759    /**
18760     * Sets a tag associated with this view and a key. A tag can be used
18761     * to mark a view in its hierarchy and does not have to be unique within
18762     * the hierarchy. Tags can also be used to store data within a view
18763     * without resorting to another data structure.
18764     *
18765     * The specified key should be an id declared in the resources of the
18766     * application to ensure it is unique (see the <a
18767     * href="{@docRoot}guide/topics/resources/more-resources.html#Id">ID resource type</a>).
18768     * Keys identified as belonging to
18769     * the Android framework or not associated with any package will cause
18770     * an {@link IllegalArgumentException} to be thrown.
18771     *
18772     * @param key The key identifying the tag
18773     * @param tag An Object to tag the view with
18774     *
18775     * @throws IllegalArgumentException If they specified key is not valid
18776     *
18777     * @see #setTag(Object)
18778     * @see #getTag(int)
18779     */
18780    public void setTag(int key, final Object tag) {
18781        // If the package id is 0x00 or 0x01, it's either an undefined package
18782        // or a framework id
18783        if ((key >>> 24) < 2) {
18784            throw new IllegalArgumentException("The key must be an application-specific "
18785                    + "resource id.");
18786        }
18787
18788        setKeyedTag(key, tag);
18789    }
18790
18791    /**
18792     * Variation of {@link #setTag(int, Object)} that enforces the key to be a
18793     * framework id.
18794     *
18795     * @hide
18796     */
18797    public void setTagInternal(int key, Object tag) {
18798        if ((key >>> 24) != 0x1) {
18799            throw new IllegalArgumentException("The key must be a framework-specific "
18800                    + "resource id.");
18801        }
18802
18803        setKeyedTag(key, tag);
18804    }
18805
18806    private void setKeyedTag(int key, Object tag) {
18807        if (mKeyedTags == null) {
18808            mKeyedTags = new SparseArray<Object>(2);
18809        }
18810
18811        mKeyedTags.put(key, tag);
18812    }
18813
18814    /**
18815     * Prints information about this view in the log output, with the tag
18816     * {@link #VIEW_LOG_TAG}.
18817     *
18818     * @hide
18819     */
18820    public void debug() {
18821        debug(0);
18822    }
18823
18824    /**
18825     * Prints information about this view in the log output, with the tag
18826     * {@link #VIEW_LOG_TAG}. Each line in the output is preceded with an
18827     * indentation defined by the <code>depth</code>.
18828     *
18829     * @param depth the indentation level
18830     *
18831     * @hide
18832     */
18833    protected void debug(int depth) {
18834        String output = debugIndent(depth - 1);
18835
18836        output += "+ " + this;
18837        int id = getId();
18838        if (id != -1) {
18839            output += " (id=" + id + ")";
18840        }
18841        Object tag = getTag();
18842        if (tag != null) {
18843            output += " (tag=" + tag + ")";
18844        }
18845        Log.d(VIEW_LOG_TAG, output);
18846
18847        if ((mPrivateFlags & PFLAG_FOCUSED) != 0) {
18848            output = debugIndent(depth) + " FOCUSED";
18849            Log.d(VIEW_LOG_TAG, output);
18850        }
18851
18852        output = debugIndent(depth);
18853        output += "frame={" + mLeft + ", " + mTop + ", " + mRight
18854                + ", " + mBottom + "} scroll={" + mScrollX + ", " + mScrollY
18855                + "} ";
18856        Log.d(VIEW_LOG_TAG, output);
18857
18858        if (mPaddingLeft != 0 || mPaddingTop != 0 || mPaddingRight != 0
18859                || mPaddingBottom != 0) {
18860            output = debugIndent(depth);
18861            output += "padding={" + mPaddingLeft + ", " + mPaddingTop
18862                    + ", " + mPaddingRight + ", " + mPaddingBottom + "}";
18863            Log.d(VIEW_LOG_TAG, output);
18864        }
18865
18866        output = debugIndent(depth);
18867        output += "mMeasureWidth=" + mMeasuredWidth +
18868                " mMeasureHeight=" + mMeasuredHeight;
18869        Log.d(VIEW_LOG_TAG, output);
18870
18871        output = debugIndent(depth);
18872        if (mLayoutParams == null) {
18873            output += "BAD! no layout params";
18874        } else {
18875            output = mLayoutParams.debug(output);
18876        }
18877        Log.d(VIEW_LOG_TAG, output);
18878
18879        output = debugIndent(depth);
18880        output += "flags={";
18881        output += View.printFlags(mViewFlags);
18882        output += "}";
18883        Log.d(VIEW_LOG_TAG, output);
18884
18885        output = debugIndent(depth);
18886        output += "privateFlags={";
18887        output += View.printPrivateFlags(mPrivateFlags);
18888        output += "}";
18889        Log.d(VIEW_LOG_TAG, output);
18890    }
18891
18892    /**
18893     * Creates a string of whitespaces used for indentation.
18894     *
18895     * @param depth the indentation level
18896     * @return a String containing (depth * 2 + 3) * 2 white spaces
18897     *
18898     * @hide
18899     */
18900    protected static String debugIndent(int depth) {
18901        StringBuilder spaces = new StringBuilder((depth * 2 + 3) * 2);
18902        for (int i = 0; i < (depth * 2) + 3; i++) {
18903            spaces.append(' ').append(' ');
18904        }
18905        return spaces.toString();
18906    }
18907
18908    /**
18909     * <p>Return the offset of the widget's text baseline from the widget's top
18910     * boundary. If this widget does not support baseline alignment, this
18911     * method returns -1. </p>
18912     *
18913     * @return the offset of the baseline within the widget's bounds or -1
18914     *         if baseline alignment is not supported
18915     */
18916    @ViewDebug.ExportedProperty(category = "layout")
18917    public int getBaseline() {
18918        return -1;
18919    }
18920
18921    /**
18922     * Returns whether the view hierarchy is currently undergoing a layout pass. This
18923     * information is useful to avoid situations such as calling {@link #requestLayout()} during
18924     * a layout pass.
18925     *
18926     * @return whether the view hierarchy is currently undergoing a layout pass
18927     */
18928    public boolean isInLayout() {
18929        ViewRootImpl viewRoot = getViewRootImpl();
18930        return (viewRoot != null && viewRoot.isInLayout());
18931    }
18932
18933    /**
18934     * Call this when something has changed which has invalidated the
18935     * layout of this view. This will schedule a layout pass of the view
18936     * tree. This should not be called while the view hierarchy is currently in a layout
18937     * pass ({@link #isInLayout()}. If layout is happening, the request may be honored at the
18938     * end of the current layout pass (and then layout will run again) or after the current
18939     * frame is drawn and the next layout occurs.
18940     *
18941     * <p>Subclasses which override this method should call the superclass method to
18942     * handle possible request-during-layout errors correctly.</p>
18943     */
18944    @CallSuper
18945    public void requestLayout() {
18946        if (mMeasureCache != null) mMeasureCache.clear();
18947
18948        if (mAttachInfo != null && mAttachInfo.mViewRequestingLayout == null) {
18949            // Only trigger request-during-layout logic if this is the view requesting it,
18950            // not the views in its parent hierarchy
18951            ViewRootImpl viewRoot = getViewRootImpl();
18952            if (viewRoot != null && viewRoot.isInLayout()) {
18953                if (!viewRoot.requestLayoutDuringLayout(this)) {
18954                    return;
18955                }
18956            }
18957            mAttachInfo.mViewRequestingLayout = this;
18958        }
18959
18960        mPrivateFlags |= PFLAG_FORCE_LAYOUT;
18961        mPrivateFlags |= PFLAG_INVALIDATED;
18962
18963        if (mParent != null && !mParent.isLayoutRequested()) {
18964            mParent.requestLayout();
18965        }
18966        if (mAttachInfo != null && mAttachInfo.mViewRequestingLayout == this) {
18967            mAttachInfo.mViewRequestingLayout = null;
18968        }
18969    }
18970
18971    /**
18972     * Forces this view to be laid out during the next layout pass.
18973     * This method does not call requestLayout() or forceLayout()
18974     * on the parent.
18975     */
18976    public void forceLayout() {
18977        if (mMeasureCache != null) mMeasureCache.clear();
18978
18979        mPrivateFlags |= PFLAG_FORCE_LAYOUT;
18980        mPrivateFlags |= PFLAG_INVALIDATED;
18981    }
18982
18983    /**
18984     * <p>
18985     * This is called to find out how big a view should be. The parent
18986     * supplies constraint information in the width and height parameters.
18987     * </p>
18988     *
18989     * <p>
18990     * The actual measurement work of a view is performed in
18991     * {@link #onMeasure(int, int)}, called by this method. Therefore, only
18992     * {@link #onMeasure(int, int)} can and must be overridden by subclasses.
18993     * </p>
18994     *
18995     *
18996     * @param widthMeasureSpec Horizontal space requirements as imposed by the
18997     *        parent
18998     * @param heightMeasureSpec Vertical space requirements as imposed by the
18999     *        parent
19000     *
19001     * @see #onMeasure(int, int)
19002     */
19003    public final void measure(int widthMeasureSpec, int heightMeasureSpec) {
19004        boolean optical = isLayoutModeOptical(this);
19005        if (optical != isLayoutModeOptical(mParent)) {
19006            Insets insets = getOpticalInsets();
19007            int oWidth  = insets.left + insets.right;
19008            int oHeight = insets.top  + insets.bottom;
19009            widthMeasureSpec  = MeasureSpec.adjust(widthMeasureSpec,  optical ? -oWidth  : oWidth);
19010            heightMeasureSpec = MeasureSpec.adjust(heightMeasureSpec, optical ? -oHeight : oHeight);
19011        }
19012
19013        // Suppress sign extension for the low bytes
19014        long key = (long) widthMeasureSpec << 32 | (long) heightMeasureSpec & 0xffffffffL;
19015        if (mMeasureCache == null) mMeasureCache = new LongSparseLongArray(2);
19016
19017        final boolean forceLayout = (mPrivateFlags & PFLAG_FORCE_LAYOUT) == PFLAG_FORCE_LAYOUT;
19018
19019        // Optimize layout by avoiding an extra EXACTLY pass when the view is
19020        // already measured as the correct size. In API 23 and below, this
19021        // extra pass is required to make LinearLayout re-distribute weight.
19022        final boolean specChanged = widthMeasureSpec != mOldWidthMeasureSpec
19023                || heightMeasureSpec != mOldHeightMeasureSpec;
19024        final boolean isSpecExactly = MeasureSpec.getMode(widthMeasureSpec) == MeasureSpec.EXACTLY
19025                && MeasureSpec.getMode(heightMeasureSpec) == MeasureSpec.EXACTLY;
19026        final boolean matchesSpecSize = getMeasuredWidth() == MeasureSpec.getSize(widthMeasureSpec)
19027                && getMeasuredHeight() == MeasureSpec.getSize(heightMeasureSpec);
19028        final boolean needsLayout = specChanged
19029                && (sAlwaysRemeasureExactly || !isSpecExactly || !matchesSpecSize);
19030
19031        if (forceLayout || needsLayout) {
19032            // first clears the measured dimension flag
19033            mPrivateFlags &= ~PFLAG_MEASURED_DIMENSION_SET;
19034
19035            resolveRtlPropertiesIfNeeded();
19036
19037            int cacheIndex = forceLayout ? -1 : mMeasureCache.indexOfKey(key);
19038            if (cacheIndex < 0 || sIgnoreMeasureCache) {
19039                // measure ourselves, this should set the measured dimension flag back
19040                onMeasure(widthMeasureSpec, heightMeasureSpec);
19041                mPrivateFlags3 &= ~PFLAG3_MEASURE_NEEDED_BEFORE_LAYOUT;
19042            } else {
19043                long value = mMeasureCache.valueAt(cacheIndex);
19044                // Casting a long to int drops the high 32 bits, no mask needed
19045                setMeasuredDimensionRaw((int) (value >> 32), (int) value);
19046                mPrivateFlags3 |= PFLAG3_MEASURE_NEEDED_BEFORE_LAYOUT;
19047            }
19048
19049            // flag not set, setMeasuredDimension() was not invoked, we raise
19050            // an exception to warn the developer
19051            if ((mPrivateFlags & PFLAG_MEASURED_DIMENSION_SET) != PFLAG_MEASURED_DIMENSION_SET) {
19052                throw new IllegalStateException("View with id " + getId() + ": "
19053                        + getClass().getName() + "#onMeasure() did not set the"
19054                        + " measured dimension by calling"
19055                        + " setMeasuredDimension()");
19056            }
19057
19058            mPrivateFlags |= PFLAG_LAYOUT_REQUIRED;
19059        }
19060
19061        mOldWidthMeasureSpec = widthMeasureSpec;
19062        mOldHeightMeasureSpec = heightMeasureSpec;
19063
19064        mMeasureCache.put(key, ((long) mMeasuredWidth) << 32 |
19065                (long) mMeasuredHeight & 0xffffffffL); // suppress sign extension
19066    }
19067
19068    /**
19069     * <p>
19070     * Measure the view and its content to determine the measured width and the
19071     * measured height. This method is invoked by {@link #measure(int, int)} and
19072     * should be overridden by subclasses to provide accurate and efficient
19073     * measurement of their contents.
19074     * </p>
19075     *
19076     * <p>
19077     * <strong>CONTRACT:</strong> When overriding this method, you
19078     * <em>must</em> call {@link #setMeasuredDimension(int, int)} to store the
19079     * measured width and height of this view. Failure to do so will trigger an
19080     * <code>IllegalStateException</code>, thrown by
19081     * {@link #measure(int, int)}. Calling the superclass'
19082     * {@link #onMeasure(int, int)} is a valid use.
19083     * </p>
19084     *
19085     * <p>
19086     * The base class implementation of measure defaults to the background size,
19087     * unless a larger size is allowed by the MeasureSpec. Subclasses should
19088     * override {@link #onMeasure(int, int)} to provide better measurements of
19089     * their content.
19090     * </p>
19091     *
19092     * <p>
19093     * If this method is overridden, it is the subclass's responsibility to make
19094     * sure the measured height and width are at least the view's minimum height
19095     * and width ({@link #getSuggestedMinimumHeight()} and
19096     * {@link #getSuggestedMinimumWidth()}).
19097     * </p>
19098     *
19099     * @param widthMeasureSpec horizontal space requirements as imposed by the parent.
19100     *                         The requirements are encoded with
19101     *                         {@link android.view.View.MeasureSpec}.
19102     * @param heightMeasureSpec vertical space requirements as imposed by the parent.
19103     *                         The requirements are encoded with
19104     *                         {@link android.view.View.MeasureSpec}.
19105     *
19106     * @see #getMeasuredWidth()
19107     * @see #getMeasuredHeight()
19108     * @see #setMeasuredDimension(int, int)
19109     * @see #getSuggestedMinimumHeight()
19110     * @see #getSuggestedMinimumWidth()
19111     * @see android.view.View.MeasureSpec#getMode(int)
19112     * @see android.view.View.MeasureSpec#getSize(int)
19113     */
19114    protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
19115        setMeasuredDimension(getDefaultSize(getSuggestedMinimumWidth(), widthMeasureSpec),
19116                getDefaultSize(getSuggestedMinimumHeight(), heightMeasureSpec));
19117    }
19118
19119    /**
19120     * <p>This method must be called by {@link #onMeasure(int, int)} to store the
19121     * measured width and measured height. Failing to do so will trigger an
19122     * exception at measurement time.</p>
19123     *
19124     * @param measuredWidth The measured width of this view.  May be a complex
19125     * bit mask as defined by {@link #MEASURED_SIZE_MASK} and
19126     * {@link #MEASURED_STATE_TOO_SMALL}.
19127     * @param measuredHeight The measured height of this view.  May be a complex
19128     * bit mask as defined by {@link #MEASURED_SIZE_MASK} and
19129     * {@link #MEASURED_STATE_TOO_SMALL}.
19130     */
19131    protected final void setMeasuredDimension(int measuredWidth, int measuredHeight) {
19132        boolean optical = isLayoutModeOptical(this);
19133        if (optical != isLayoutModeOptical(mParent)) {
19134            Insets insets = getOpticalInsets();
19135            int opticalWidth  = insets.left + insets.right;
19136            int opticalHeight = insets.top  + insets.bottom;
19137
19138            measuredWidth  += optical ? opticalWidth  : -opticalWidth;
19139            measuredHeight += optical ? opticalHeight : -opticalHeight;
19140        }
19141        setMeasuredDimensionRaw(measuredWidth, measuredHeight);
19142    }
19143
19144    /**
19145     * Sets the measured dimension without extra processing for things like optical bounds.
19146     * Useful for reapplying consistent values that have already been cooked with adjustments
19147     * for optical bounds, etc. such as those from the measurement cache.
19148     *
19149     * @param measuredWidth The measured width of this view.  May be a complex
19150     * bit mask as defined by {@link #MEASURED_SIZE_MASK} and
19151     * {@link #MEASURED_STATE_TOO_SMALL}.
19152     * @param measuredHeight The measured height of this view.  May be a complex
19153     * bit mask as defined by {@link #MEASURED_SIZE_MASK} and
19154     * {@link #MEASURED_STATE_TOO_SMALL}.
19155     */
19156    private void setMeasuredDimensionRaw(int measuredWidth, int measuredHeight) {
19157        mMeasuredWidth = measuredWidth;
19158        mMeasuredHeight = measuredHeight;
19159
19160        mPrivateFlags |= PFLAG_MEASURED_DIMENSION_SET;
19161    }
19162
19163    /**
19164     * Merge two states as returned by {@link #getMeasuredState()}.
19165     * @param curState The current state as returned from a view or the result
19166     * of combining multiple views.
19167     * @param newState The new view state to combine.
19168     * @return Returns a new integer reflecting the combination of the two
19169     * states.
19170     */
19171    public static int combineMeasuredStates(int curState, int newState) {
19172        return curState | newState;
19173    }
19174
19175    /**
19176     * Version of {@link #resolveSizeAndState(int, int, int)}
19177     * returning only the {@link #MEASURED_SIZE_MASK} bits of the result.
19178     */
19179    public static int resolveSize(int size, int measureSpec) {
19180        return resolveSizeAndState(size, measureSpec, 0) & MEASURED_SIZE_MASK;
19181    }
19182
19183    /**
19184     * Utility to reconcile a desired size and state, with constraints imposed
19185     * by a MeasureSpec. Will take the desired size, unless a different size
19186     * is imposed by the constraints. The returned value is a compound integer,
19187     * with the resolved size in the {@link #MEASURED_SIZE_MASK} bits and
19188     * optionally the bit {@link #MEASURED_STATE_TOO_SMALL} set if the
19189     * resulting size is smaller than the size the view wants to be.
19190     *
19191     * @param size How big the view wants to be.
19192     * @param measureSpec Constraints imposed by the parent.
19193     * @param childMeasuredState Size information bit mask for the view's
19194     *                           children.
19195     * @return Size information bit mask as defined by
19196     *         {@link #MEASURED_SIZE_MASK} and
19197     *         {@link #MEASURED_STATE_TOO_SMALL}.
19198     */
19199    public static int resolveSizeAndState(int size, int measureSpec, int childMeasuredState) {
19200        final int specMode = MeasureSpec.getMode(measureSpec);
19201        final int specSize = MeasureSpec.getSize(measureSpec);
19202        final int result;
19203        switch (specMode) {
19204            case MeasureSpec.AT_MOST:
19205                if (specSize < size) {
19206                    result = specSize | MEASURED_STATE_TOO_SMALL;
19207                } else {
19208                    result = size;
19209                }
19210                break;
19211            case MeasureSpec.EXACTLY:
19212                result = specSize;
19213                break;
19214            case MeasureSpec.UNSPECIFIED:
19215            default:
19216                result = size;
19217        }
19218        return result | (childMeasuredState & MEASURED_STATE_MASK);
19219    }
19220
19221    /**
19222     * Utility to return a default size. Uses the supplied size if the
19223     * MeasureSpec imposed no constraints. Will get larger if allowed
19224     * by the MeasureSpec.
19225     *
19226     * @param size Default size for this view
19227     * @param measureSpec Constraints imposed by the parent
19228     * @return The size this view should be.
19229     */
19230    public static int getDefaultSize(int size, int measureSpec) {
19231        int result = size;
19232        int specMode = MeasureSpec.getMode(measureSpec);
19233        int specSize = MeasureSpec.getSize(measureSpec);
19234
19235        switch (specMode) {
19236        case MeasureSpec.UNSPECIFIED:
19237            result = size;
19238            break;
19239        case MeasureSpec.AT_MOST:
19240        case MeasureSpec.EXACTLY:
19241            result = specSize;
19242            break;
19243        }
19244        return result;
19245    }
19246
19247    /**
19248     * Returns the suggested minimum height that the view should use. This
19249     * returns the maximum of the view's minimum height
19250     * and the background's minimum height
19251     * ({@link android.graphics.drawable.Drawable#getMinimumHeight()}).
19252     * <p>
19253     * When being used in {@link #onMeasure(int, int)}, the caller should still
19254     * ensure the returned height is within the requirements of the parent.
19255     *
19256     * @return The suggested minimum height of the view.
19257     */
19258    protected int getSuggestedMinimumHeight() {
19259        return (mBackground == null) ? mMinHeight : max(mMinHeight, mBackground.getMinimumHeight());
19260
19261    }
19262
19263    /**
19264     * Returns the suggested minimum width that the view should use. This
19265     * returns the maximum of the view's minimum width
19266     * and the background's minimum width
19267     *  ({@link android.graphics.drawable.Drawable#getMinimumWidth()}).
19268     * <p>
19269     * When being used in {@link #onMeasure(int, int)}, the caller should still
19270     * ensure the returned width is within the requirements of the parent.
19271     *
19272     * @return The suggested minimum width of the view.
19273     */
19274    protected int getSuggestedMinimumWidth() {
19275        return (mBackground == null) ? mMinWidth : max(mMinWidth, mBackground.getMinimumWidth());
19276    }
19277
19278    /**
19279     * Returns the minimum height of the view.
19280     *
19281     * @return the minimum height the view will try to be.
19282     *
19283     * @see #setMinimumHeight(int)
19284     *
19285     * @attr ref android.R.styleable#View_minHeight
19286     */
19287    public int getMinimumHeight() {
19288        return mMinHeight;
19289    }
19290
19291    /**
19292     * Sets the minimum height of the view. It is not guaranteed the view will
19293     * be able to achieve this minimum height (for example, if its parent layout
19294     * constrains it with less available height).
19295     *
19296     * @param minHeight The minimum height the view will try to be.
19297     *
19298     * @see #getMinimumHeight()
19299     *
19300     * @attr ref android.R.styleable#View_minHeight
19301     */
19302    public void setMinimumHeight(int minHeight) {
19303        mMinHeight = minHeight;
19304        requestLayout();
19305    }
19306
19307    /**
19308     * Returns the minimum width of the view.
19309     *
19310     * @return the minimum width the view will try to be.
19311     *
19312     * @see #setMinimumWidth(int)
19313     *
19314     * @attr ref android.R.styleable#View_minWidth
19315     */
19316    public int getMinimumWidth() {
19317        return mMinWidth;
19318    }
19319
19320    /**
19321     * Sets the minimum width of the view. It is not guaranteed the view will
19322     * be able to achieve this minimum width (for example, if its parent layout
19323     * constrains it with less available width).
19324     *
19325     * @param minWidth The minimum width the view will try to be.
19326     *
19327     * @see #getMinimumWidth()
19328     *
19329     * @attr ref android.R.styleable#View_minWidth
19330     */
19331    public void setMinimumWidth(int minWidth) {
19332        mMinWidth = minWidth;
19333        requestLayout();
19334
19335    }
19336
19337    /**
19338     * Get the animation currently associated with this view.
19339     *
19340     * @return The animation that is currently playing or
19341     *         scheduled to play for this view.
19342     */
19343    public Animation getAnimation() {
19344        return mCurrentAnimation;
19345    }
19346
19347    /**
19348     * Start the specified animation now.
19349     *
19350     * @param animation the animation to start now
19351     */
19352    public void startAnimation(Animation animation) {
19353        animation.setStartTime(Animation.START_ON_FIRST_FRAME);
19354        setAnimation(animation);
19355        invalidateParentCaches();
19356        invalidate(true);
19357    }
19358
19359    /**
19360     * Cancels any animations for this view.
19361     */
19362    public void clearAnimation() {
19363        if (mCurrentAnimation != null) {
19364            mCurrentAnimation.detach();
19365        }
19366        mCurrentAnimation = null;
19367        invalidateParentIfNeeded();
19368    }
19369
19370    /**
19371     * Sets the next animation to play for this view.
19372     * If you want the animation to play immediately, use
19373     * {@link #startAnimation(android.view.animation.Animation)} instead.
19374     * This method provides allows fine-grained
19375     * control over the start time and invalidation, but you
19376     * must make sure that 1) the animation has a start time set, and
19377     * 2) the view's parent (which controls animations on its children)
19378     * will be invalidated when the animation is supposed to
19379     * start.
19380     *
19381     * @param animation The next animation, or null.
19382     */
19383    public void setAnimation(Animation animation) {
19384        mCurrentAnimation = animation;
19385
19386        if (animation != null) {
19387            // If the screen is off assume the animation start time is now instead of
19388            // the next frame we draw. Keeping the START_ON_FIRST_FRAME start time
19389            // would cause the animation to start when the screen turns back on
19390            if (mAttachInfo != null && mAttachInfo.mDisplayState == Display.STATE_OFF
19391                    && animation.getStartTime() == Animation.START_ON_FIRST_FRAME) {
19392                animation.setStartTime(AnimationUtils.currentAnimationTimeMillis());
19393            }
19394            animation.reset();
19395        }
19396    }
19397
19398    /**
19399     * Invoked by a parent ViewGroup to notify the start of the animation
19400     * currently associated with this view. If you override this method,
19401     * always call super.onAnimationStart();
19402     *
19403     * @see #setAnimation(android.view.animation.Animation)
19404     * @see #getAnimation()
19405     */
19406    @CallSuper
19407    protected void onAnimationStart() {
19408        mPrivateFlags |= PFLAG_ANIMATION_STARTED;
19409    }
19410
19411    /**
19412     * Invoked by a parent ViewGroup to notify the end of the animation
19413     * currently associated with this view. If you override this method,
19414     * always call super.onAnimationEnd();
19415     *
19416     * @see #setAnimation(android.view.animation.Animation)
19417     * @see #getAnimation()
19418     */
19419    @CallSuper
19420    protected void onAnimationEnd() {
19421        mPrivateFlags &= ~PFLAG_ANIMATION_STARTED;
19422    }
19423
19424    /**
19425     * Invoked if there is a Transform that involves alpha. Subclass that can
19426     * draw themselves with the specified alpha should return true, and then
19427     * respect that alpha when their onDraw() is called. If this returns false
19428     * then the view may be redirected to draw into an offscreen buffer to
19429     * fulfill the request, which will look fine, but may be slower than if the
19430     * subclass handles it internally. The default implementation returns false.
19431     *
19432     * @param alpha The alpha (0..255) to apply to the view's drawing
19433     * @return true if the view can draw with the specified alpha.
19434     */
19435    protected boolean onSetAlpha(int alpha) {
19436        return false;
19437    }
19438
19439    /**
19440     * This is used by the RootView to perform an optimization when
19441     * the view hierarchy contains one or several SurfaceView.
19442     * SurfaceView is always considered transparent, but its children are not,
19443     * therefore all View objects remove themselves from the global transparent
19444     * region (passed as a parameter to this function).
19445     *
19446     * @param region The transparent region for this ViewAncestor (window).
19447     *
19448     * @return Returns true if the effective visibility of the view at this
19449     * point is opaque, regardless of the transparent region; returns false
19450     * if it is possible for underlying windows to be seen behind the view.
19451     *
19452     * {@hide}
19453     */
19454    public boolean gatherTransparentRegion(Region region) {
19455        final AttachInfo attachInfo = mAttachInfo;
19456        if (region != null && attachInfo != null) {
19457            final int pflags = mPrivateFlags;
19458            if ((pflags & PFLAG_SKIP_DRAW) == 0) {
19459                // The SKIP_DRAW flag IS NOT set, so this view draws. We need to
19460                // remove it from the transparent region.
19461                final int[] location = attachInfo.mTransparentLocation;
19462                getLocationInWindow(location);
19463                region.op(location[0], location[1], location[0] + mRight - mLeft,
19464                        location[1] + mBottom - mTop, Region.Op.DIFFERENCE);
19465            } else {
19466                if (mBackground != null && mBackground.getOpacity() != PixelFormat.TRANSPARENT) {
19467                    // The SKIP_DRAW flag IS set and the background drawable exists, we remove
19468                    // the background drawable's non-transparent parts from this transparent region.
19469                    applyDrawableToTransparentRegion(mBackground, region);
19470                }
19471                if (mForegroundInfo != null && mForegroundInfo.mDrawable != null
19472                        && mForegroundInfo.mDrawable.getOpacity() != PixelFormat.TRANSPARENT) {
19473                    // Similarly, we remove the foreground drawable's non-transparent parts.
19474                    applyDrawableToTransparentRegion(mForegroundInfo.mDrawable, region);
19475                }
19476            }
19477        }
19478        return true;
19479    }
19480
19481    /**
19482     * Play a sound effect for this view.
19483     *
19484     * <p>The framework will play sound effects for some built in actions, such as
19485     * clicking, but you may wish to play these effects in your widget,
19486     * for instance, for internal navigation.
19487     *
19488     * <p>The sound effect will only be played if sound effects are enabled by the user, and
19489     * {@link #isSoundEffectsEnabled()} is true.
19490     *
19491     * @param soundConstant One of the constants defined in {@link SoundEffectConstants}
19492     */
19493    public void playSoundEffect(int soundConstant) {
19494        if (mAttachInfo == null || mAttachInfo.mRootCallbacks == null || !isSoundEffectsEnabled()) {
19495            return;
19496        }
19497        mAttachInfo.mRootCallbacks.playSoundEffect(soundConstant);
19498    }
19499
19500    /**
19501     * BZZZTT!!1!
19502     *
19503     * <p>Provide haptic feedback to the user for this view.
19504     *
19505     * <p>The framework will provide haptic feedback for some built in actions,
19506     * such as long presses, but you may wish to provide feedback for your
19507     * own widget.
19508     *
19509     * <p>The feedback will only be performed if
19510     * {@link #isHapticFeedbackEnabled()} is true.
19511     *
19512     * @param feedbackConstant One of the constants defined in
19513     * {@link HapticFeedbackConstants}
19514     */
19515    public boolean performHapticFeedback(int feedbackConstant) {
19516        return performHapticFeedback(feedbackConstant, 0);
19517    }
19518
19519    /**
19520     * BZZZTT!!1!
19521     *
19522     * <p>Like {@link #performHapticFeedback(int)}, with additional options.
19523     *
19524     * @param feedbackConstant One of the constants defined in
19525     * {@link HapticFeedbackConstants}
19526     * @param flags Additional flags as per {@link HapticFeedbackConstants}.
19527     */
19528    public boolean performHapticFeedback(int feedbackConstant, int flags) {
19529        if (mAttachInfo == null) {
19530            return false;
19531        }
19532        //noinspection SimplifiableIfStatement
19533        if ((flags & HapticFeedbackConstants.FLAG_IGNORE_VIEW_SETTING) == 0
19534                && !isHapticFeedbackEnabled()) {
19535            return false;
19536        }
19537        return mAttachInfo.mRootCallbacks.performHapticFeedback(feedbackConstant,
19538                (flags & HapticFeedbackConstants.FLAG_IGNORE_GLOBAL_SETTING) != 0);
19539    }
19540
19541    /**
19542     * Request that the visibility of the status bar or other screen/window
19543     * decorations be changed.
19544     *
19545     * <p>This method is used to put the over device UI into temporary modes
19546     * where the user's attention is focused more on the application content,
19547     * by dimming or hiding surrounding system affordances.  This is typically
19548     * used in conjunction with {@link Window#FEATURE_ACTION_BAR_OVERLAY
19549     * Window.FEATURE_ACTION_BAR_OVERLAY}, allowing the applications content
19550     * to be placed behind the action bar (and with these flags other system
19551     * affordances) so that smooth transitions between hiding and showing them
19552     * can be done.
19553     *
19554     * <p>Two representative examples of the use of system UI visibility is
19555     * implementing a content browsing application (like a magazine reader)
19556     * and a video playing application.
19557     *
19558     * <p>The first code shows a typical implementation of a View in a content
19559     * browsing application.  In this implementation, the application goes
19560     * into a content-oriented mode by hiding the status bar and action bar,
19561     * and putting the navigation elements into lights out mode.  The user can
19562     * then interact with content while in this mode.  Such an application should
19563     * provide an easy way for the user to toggle out of the mode (such as to
19564     * check information in the status bar or access notifications).  In the
19565     * implementation here, this is done simply by tapping on the content.
19566     *
19567     * {@sample development/samples/ApiDemos/src/com/example/android/apis/view/ContentBrowserActivity.java
19568     *      content}
19569     *
19570     * <p>This second code sample shows a typical implementation of a View
19571     * in a video playing application.  In this situation, while the video is
19572     * playing the application would like to go into a complete full-screen mode,
19573     * to use as much of the display as possible for the video.  When in this state
19574     * the user can not interact with the application; the system intercepts
19575     * touching on the screen to pop the UI out of full screen mode.  See
19576     * {@link #fitSystemWindows(Rect)} for a sample layout that goes with this code.
19577     *
19578     * {@sample development/samples/ApiDemos/src/com/example/android/apis/view/VideoPlayerActivity.java
19579     *      content}
19580     *
19581     * @param visibility  Bitwise-or of flags {@link #SYSTEM_UI_FLAG_LOW_PROFILE},
19582     * {@link #SYSTEM_UI_FLAG_HIDE_NAVIGATION}, {@link #SYSTEM_UI_FLAG_FULLSCREEN},
19583     * {@link #SYSTEM_UI_FLAG_LAYOUT_STABLE}, {@link #SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION},
19584     * {@link #SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN}, {@link #SYSTEM_UI_FLAG_IMMERSIVE},
19585     * and {@link #SYSTEM_UI_FLAG_IMMERSIVE_STICKY}.
19586     */
19587    public void setSystemUiVisibility(int visibility) {
19588        if (visibility != mSystemUiVisibility) {
19589            mSystemUiVisibility = visibility;
19590            if (mParent != null && mAttachInfo != null && !mAttachInfo.mRecomputeGlobalAttributes) {
19591                mParent.recomputeViewAttributes(this);
19592            }
19593        }
19594    }
19595
19596    /**
19597     * Returns the last {@link #setSystemUiVisibility(int)} that this view has requested.
19598     * @return  Bitwise-or of flags {@link #SYSTEM_UI_FLAG_LOW_PROFILE},
19599     * {@link #SYSTEM_UI_FLAG_HIDE_NAVIGATION}, {@link #SYSTEM_UI_FLAG_FULLSCREEN},
19600     * {@link #SYSTEM_UI_FLAG_LAYOUT_STABLE}, {@link #SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION},
19601     * {@link #SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN}, {@link #SYSTEM_UI_FLAG_IMMERSIVE},
19602     * and {@link #SYSTEM_UI_FLAG_IMMERSIVE_STICKY}.
19603     */
19604    public int getSystemUiVisibility() {
19605        return mSystemUiVisibility;
19606    }
19607
19608    /**
19609     * Returns the current system UI visibility that is currently set for
19610     * the entire window.  This is the combination of the
19611     * {@link #setSystemUiVisibility(int)} values supplied by all of the
19612     * views in the window.
19613     */
19614    public int getWindowSystemUiVisibility() {
19615        return mAttachInfo != null ? mAttachInfo.mSystemUiVisibility : 0;
19616    }
19617
19618    /**
19619     * Override to find out when the window's requested system UI visibility
19620     * has changed, that is the value returned by {@link #getWindowSystemUiVisibility()}.
19621     * This is different from the callbacks received through
19622     * {@link #setOnSystemUiVisibilityChangeListener(OnSystemUiVisibilityChangeListener)}
19623     * in that this is only telling you about the local request of the window,
19624     * not the actual values applied by the system.
19625     */
19626    public void onWindowSystemUiVisibilityChanged(int visible) {
19627    }
19628
19629    /**
19630     * Dispatch callbacks to {@link #onWindowSystemUiVisibilityChanged(int)} down
19631     * the view hierarchy.
19632     */
19633    public void dispatchWindowSystemUiVisiblityChanged(int visible) {
19634        onWindowSystemUiVisibilityChanged(visible);
19635    }
19636
19637    /**
19638     * Set a listener to receive callbacks when the visibility of the system bar changes.
19639     * @param l  The {@link OnSystemUiVisibilityChangeListener} to receive callbacks.
19640     */
19641    public void setOnSystemUiVisibilityChangeListener(OnSystemUiVisibilityChangeListener l) {
19642        getListenerInfo().mOnSystemUiVisibilityChangeListener = l;
19643        if (mParent != null && mAttachInfo != null && !mAttachInfo.mRecomputeGlobalAttributes) {
19644            mParent.recomputeViewAttributes(this);
19645        }
19646    }
19647
19648    /**
19649     * Dispatch callbacks to {@link #setOnSystemUiVisibilityChangeListener} down
19650     * the view hierarchy.
19651     */
19652    public void dispatchSystemUiVisibilityChanged(int visibility) {
19653        ListenerInfo li = mListenerInfo;
19654        if (li != null && li.mOnSystemUiVisibilityChangeListener != null) {
19655            li.mOnSystemUiVisibilityChangeListener.onSystemUiVisibilityChange(
19656                    visibility & PUBLIC_STATUS_BAR_VISIBILITY_MASK);
19657        }
19658    }
19659
19660    boolean updateLocalSystemUiVisibility(int localValue, int localChanges) {
19661        int val = (mSystemUiVisibility&~localChanges) | (localValue&localChanges);
19662        if (val != mSystemUiVisibility) {
19663            setSystemUiVisibility(val);
19664            return true;
19665        }
19666        return false;
19667    }
19668
19669    /** @hide */
19670    public void setDisabledSystemUiVisibility(int flags) {
19671        if (mAttachInfo != null) {
19672            if (mAttachInfo.mDisabledSystemUiVisibility != flags) {
19673                mAttachInfo.mDisabledSystemUiVisibility = flags;
19674                if (mParent != null) {
19675                    mParent.recomputeViewAttributes(this);
19676                }
19677            }
19678        }
19679    }
19680
19681    /**
19682     * Creates an image that the system displays during the drag and drop
19683     * operation. This is called a &quot;drag shadow&quot;. The default implementation
19684     * for a DragShadowBuilder based on a View returns an image that has exactly the same
19685     * appearance as the given View. The default also positions the center of the drag shadow
19686     * directly under the touch point. If no View is provided (the constructor with no parameters
19687     * is used), and {@link #onProvideShadowMetrics(Point,Point) onProvideShadowMetrics()} and
19688     * {@link #onDrawShadow(Canvas) onDrawShadow()} are not overridden, then the
19689     * default is an invisible drag shadow.
19690     * <p>
19691     * You are not required to use the View you provide to the constructor as the basis of the
19692     * drag shadow. The {@link #onDrawShadow(Canvas) onDrawShadow()} method allows you to draw
19693     * anything you want as the drag shadow.
19694     * </p>
19695     * <p>
19696     *  You pass a DragShadowBuilder object to the system when you start the drag. The system
19697     *  calls {@link #onProvideShadowMetrics(Point,Point) onProvideShadowMetrics()} to get the
19698     *  size and position of the drag shadow. It uses this data to construct a
19699     *  {@link android.graphics.Canvas} object, then it calls {@link #onDrawShadow(Canvas) onDrawShadow()}
19700     *  so that your application can draw the shadow image in the Canvas.
19701     * </p>
19702     *
19703     * <div class="special reference">
19704     * <h3>Developer Guides</h3>
19705     * <p>For a guide to implementing drag and drop features, read the
19706     * <a href="{@docRoot}guide/topics/ui/drag-drop.html">Drag and Drop</a> developer guide.</p>
19707     * </div>
19708     */
19709    public static class DragShadowBuilder {
19710        private final WeakReference<View> mView;
19711
19712        /**
19713         * Constructs a shadow image builder based on a View. By default, the resulting drag
19714         * shadow will have the same appearance and dimensions as the View, with the touch point
19715         * over the center of the View.
19716         * @param view A View. Any View in scope can be used.
19717         */
19718        public DragShadowBuilder(View view) {
19719            mView = new WeakReference<View>(view);
19720        }
19721
19722        /**
19723         * Construct a shadow builder object with no associated View.  This
19724         * constructor variant is only useful when the {@link #onProvideShadowMetrics(Point, Point)}
19725         * and {@link #onDrawShadow(Canvas)} methods are also overridden in order
19726         * to supply the drag shadow's dimensions and appearance without
19727         * reference to any View object. If they are not overridden, then the result is an
19728         * invisible drag shadow.
19729         */
19730        public DragShadowBuilder() {
19731            mView = new WeakReference<View>(null);
19732        }
19733
19734        /**
19735         * Returns the View object that had been passed to the
19736         * {@link #View.DragShadowBuilder(View)}
19737         * constructor.  If that View parameter was {@code null} or if the
19738         * {@link #View.DragShadowBuilder()}
19739         * constructor was used to instantiate the builder object, this method will return
19740         * null.
19741         *
19742         * @return The View object associate with this builder object.
19743         */
19744        @SuppressWarnings({"JavadocReference"})
19745        final public View getView() {
19746            return mView.get();
19747        }
19748
19749        /**
19750         * Provides the metrics for the shadow image. These include the dimensions of
19751         * the shadow image, and the point within that shadow that should
19752         * be centered under the touch location while dragging.
19753         * <p>
19754         * The default implementation sets the dimensions of the shadow to be the
19755         * same as the dimensions of the View itself and centers the shadow under
19756         * the touch point.
19757         * </p>
19758         *
19759         * @param shadowSize A {@link android.graphics.Point} containing the width and height
19760         * of the shadow image. Your application must set {@link android.graphics.Point#x} to the
19761         * desired width and must set {@link android.graphics.Point#y} to the desired height of the
19762         * image.
19763         *
19764         * @param shadowTouchPoint A {@link android.graphics.Point} for the position within the
19765         * shadow image that should be underneath the touch point during the drag and drop
19766         * operation. Your application must set {@link android.graphics.Point#x} to the
19767         * X coordinate and {@link android.graphics.Point#y} to the Y coordinate of this position.
19768         */
19769        public void onProvideShadowMetrics(Point shadowSize, Point shadowTouchPoint) {
19770            final View view = mView.get();
19771            if (view != null) {
19772                shadowSize.set(view.getWidth(), view.getHeight());
19773                shadowTouchPoint.set(shadowSize.x / 2, shadowSize.y / 2);
19774            } else {
19775                Log.e(View.VIEW_LOG_TAG, "Asked for drag thumb metrics but no view");
19776            }
19777        }
19778
19779        /**
19780         * Draws the shadow image. The system creates the {@link android.graphics.Canvas} object
19781         * based on the dimensions it received from the
19782         * {@link #onProvideShadowMetrics(Point, Point)} callback.
19783         *
19784         * @param canvas A {@link android.graphics.Canvas} object in which to draw the shadow image.
19785         */
19786        public void onDrawShadow(Canvas canvas) {
19787            final View view = mView.get();
19788            if (view != null) {
19789                view.draw(canvas);
19790            } else {
19791                Log.e(View.VIEW_LOG_TAG, "Asked to draw drag shadow but no view");
19792            }
19793        }
19794    }
19795
19796    /**
19797     * Starts a drag and drop operation. When your application calls this method, it passes a
19798     * {@link android.view.View.DragShadowBuilder} object to the system. The
19799     * system calls this object's {@link DragShadowBuilder#onProvideShadowMetrics(Point, Point)}
19800     * to get metrics for the drag shadow, and then calls the object's
19801     * {@link DragShadowBuilder#onDrawShadow(Canvas)} to draw the drag shadow itself.
19802     * <p>
19803     *  Once the system has the drag shadow, it begins the drag and drop operation by sending
19804     *  drag events to all the View objects in your application that are currently visible. It does
19805     *  this either by calling the View object's drag listener (an implementation of
19806     *  {@link android.view.View.OnDragListener#onDrag(View,DragEvent) onDrag()} or by calling the
19807     *  View object's {@link android.view.View#onDragEvent(DragEvent) onDragEvent()} method.
19808     *  Both are passed a {@link android.view.DragEvent} object that has a
19809     *  {@link android.view.DragEvent#getAction()} value of
19810     *  {@link android.view.DragEvent#ACTION_DRAG_STARTED}.
19811     * </p>
19812     * <p>
19813     * Your application can invoke startDrag() on any attached View object. The View object does not
19814     * need to be the one used in {@link android.view.View.DragShadowBuilder}, nor does it need to
19815     * be related to the View the user selected for dragging.
19816     * </p>
19817     * @param data A {@link android.content.ClipData} object pointing to the data to be
19818     * transferred by the drag and drop operation.
19819     * @param shadowBuilder A {@link android.view.View.DragShadowBuilder} object for building the
19820     * drag shadow.
19821     * @param myLocalState An {@link java.lang.Object} containing local data about the drag and
19822     * drop operation. This Object is put into every DragEvent object sent by the system during the
19823     * current drag.
19824     * <p>
19825     * myLocalState is a lightweight mechanism for the sending information from the dragged View
19826     * to the target Views. For example, it can contain flags that differentiate between a
19827     * a copy operation and a move operation.
19828     * </p>
19829     * @param flags Flags that control the drag and drop operation. No flags are currently defined,
19830     * so the parameter should be set to 0.
19831     * @return {@code true} if the method completes successfully, or
19832     * {@code false} if it fails anywhere. Returning {@code false} means the system was unable to
19833     * do a drag, and so no drag operation is in progress.
19834     */
19835    public final boolean startDrag(ClipData data, DragShadowBuilder shadowBuilder,
19836            Object myLocalState, int flags) {
19837        if (ViewDebug.DEBUG_DRAG) {
19838            Log.d(VIEW_LOG_TAG, "startDrag: data=" + data + " flags=" + flags);
19839        }
19840        boolean okay = false;
19841
19842        Point shadowSize = new Point();
19843        Point shadowTouchPoint = new Point();
19844        shadowBuilder.onProvideShadowMetrics(shadowSize, shadowTouchPoint);
19845
19846        if ((shadowSize.x < 0) || (shadowSize.y < 0) ||
19847                (shadowTouchPoint.x < 0) || (shadowTouchPoint.y < 0)) {
19848            throw new IllegalStateException("Drag shadow dimensions must not be negative");
19849        }
19850
19851        if (ViewDebug.DEBUG_DRAG) {
19852            Log.d(VIEW_LOG_TAG, "drag shadow: width=" + shadowSize.x + " height=" + shadowSize.y
19853                    + " shadowX=" + shadowTouchPoint.x + " shadowY=" + shadowTouchPoint.y);
19854        }
19855        Surface surface = new Surface();
19856        try {
19857            IBinder token = mAttachInfo.mSession.prepareDrag(mAttachInfo.mWindow,
19858                    flags, shadowSize.x, shadowSize.y, surface);
19859            if (ViewDebug.DEBUG_DRAG) Log.d(VIEW_LOG_TAG, "prepareDrag returned token=" + token
19860                    + " surface=" + surface);
19861            if (token != null) {
19862                Canvas canvas = surface.lockCanvas(null);
19863                try {
19864                    canvas.drawColor(0, PorterDuff.Mode.CLEAR);
19865                    shadowBuilder.onDrawShadow(canvas);
19866                } finally {
19867                    surface.unlockCanvasAndPost(canvas);
19868                }
19869
19870                final ViewRootImpl root = getViewRootImpl();
19871
19872                // Cache the local state object for delivery with DragEvents
19873                root.setLocalDragState(myLocalState);
19874
19875                // repurpose 'shadowSize' for the last touch point
19876                root.getLastTouchPoint(shadowSize);
19877
19878                okay = mAttachInfo.mSession.performDrag(mAttachInfo.mWindow, token,
19879                        shadowSize.x, shadowSize.y,
19880                        shadowTouchPoint.x, shadowTouchPoint.y, data);
19881                if (ViewDebug.DEBUG_DRAG) Log.d(VIEW_LOG_TAG, "performDrag returned " + okay);
19882
19883                // Off and running!  Release our local surface instance; the drag
19884                // shadow surface is now managed by the system process.
19885                surface.release();
19886            }
19887        } catch (Exception e) {
19888            Log.e(VIEW_LOG_TAG, "Unable to initiate drag", e);
19889            surface.destroy();
19890        }
19891
19892        return okay;
19893    }
19894
19895    /**
19896     * Starts a move from {startX, startY}, the amount of the movement will be the offset
19897     * between {startX, startY} and the new cursor positon.
19898     * @param startX horizontal coordinate where the move started.
19899     * @param startY vertical coordinate where the move started.
19900     * @return whether moving was started successfully.
19901     * @hide
19902     */
19903    public final boolean startMovingTask(float startX, float startY) {
19904        if (ViewDebug.DEBUG_POSITIONING) {
19905            Log.d(VIEW_LOG_TAG, "startMovingTask: {" + startX + "," + startY + "}");
19906        }
19907        try {
19908            return mAttachInfo.mSession.startMovingTask(mAttachInfo.mWindow, startX, startY);
19909        } catch (RemoteException e) {
19910            Log.e(VIEW_LOG_TAG, "Unable to start moving", e);
19911        }
19912        return false;
19913    }
19914
19915    /**
19916     * Handles drag events sent by the system following a call to
19917     * {@link android.view.View#startDrag(ClipData,DragShadowBuilder,Object,int) startDrag()}.
19918     *<p>
19919     * When the system calls this method, it passes a
19920     * {@link android.view.DragEvent} object. A call to
19921     * {@link android.view.DragEvent#getAction()} returns one of the action type constants defined
19922     * in DragEvent. The method uses these to determine what is happening in the drag and drop
19923     * operation.
19924     * @param event The {@link android.view.DragEvent} sent by the system.
19925     * The {@link android.view.DragEvent#getAction()} method returns an action type constant defined
19926     * in DragEvent, indicating the type of drag event represented by this object.
19927     * @return {@code true} if the method was successful, otherwise {@code false}.
19928     * <p>
19929     *  The method should return {@code true} in response to an action type of
19930     *  {@link android.view.DragEvent#ACTION_DRAG_STARTED} to receive drag events for the current
19931     *  operation.
19932     * </p>
19933     * <p>
19934     *  The method should also return {@code true} in response to an action type of
19935     *  {@link android.view.DragEvent#ACTION_DROP} if it consumed the drop, or
19936     *  {@code false} if it didn't.
19937     * </p>
19938     */
19939    public boolean onDragEvent(DragEvent event) {
19940        return false;
19941    }
19942
19943    /**
19944     * Detects if this View is enabled and has a drag event listener.
19945     * If both are true, then it calls the drag event listener with the
19946     * {@link android.view.DragEvent} it received. If the drag event listener returns
19947     * {@code true}, then dispatchDragEvent() returns {@code true}.
19948     * <p>
19949     * For all other cases, the method calls the
19950     * {@link android.view.View#onDragEvent(DragEvent) onDragEvent()} drag event handler
19951     * method and returns its result.
19952     * </p>
19953     * <p>
19954     * This ensures that a drag event is always consumed, even if the View does not have a drag
19955     * event listener. However, if the View has a listener and the listener returns true, then
19956     * onDragEvent() is not called.
19957     * </p>
19958     */
19959    public boolean dispatchDragEvent(DragEvent event) {
19960        ListenerInfo li = mListenerInfo;
19961        //noinspection SimplifiableIfStatement
19962        if (li != null && li.mOnDragListener != null && (mViewFlags & ENABLED_MASK) == ENABLED
19963                && li.mOnDragListener.onDrag(this, event)) {
19964            return true;
19965        }
19966        return onDragEvent(event);
19967    }
19968
19969    boolean canAcceptDrag() {
19970        return (mPrivateFlags2 & PFLAG2_DRAG_CAN_ACCEPT) != 0;
19971    }
19972
19973    /**
19974     * This needs to be a better API (NOT ON VIEW) before it is exposed.  If
19975     * it is ever exposed at all.
19976     * @hide
19977     */
19978    public void onCloseSystemDialogs(String reason) {
19979    }
19980
19981    /**
19982     * Given a Drawable whose bounds have been set to draw into this view,
19983     * update a Region being computed for
19984     * {@link #gatherTransparentRegion(android.graphics.Region)} so
19985     * that any non-transparent parts of the Drawable are removed from the
19986     * given transparent region.
19987     *
19988     * @param dr The Drawable whose transparency is to be applied to the region.
19989     * @param region A Region holding the current transparency information,
19990     * where any parts of the region that are set are considered to be
19991     * transparent.  On return, this region will be modified to have the
19992     * transparency information reduced by the corresponding parts of the
19993     * Drawable that are not transparent.
19994     * {@hide}
19995     */
19996    public void applyDrawableToTransparentRegion(Drawable dr, Region region) {
19997        if (DBG) {
19998            Log.i("View", "Getting transparent region for: " + this);
19999        }
20000        final Region r = dr.getTransparentRegion();
20001        final Rect db = dr.getBounds();
20002        final AttachInfo attachInfo = mAttachInfo;
20003        if (r != null && attachInfo != null) {
20004            final int w = getRight()-getLeft();
20005            final int h = getBottom()-getTop();
20006            if (db.left > 0) {
20007                //Log.i("VIEW", "Drawable left " + db.left + " > view 0");
20008                r.op(0, 0, db.left, h, Region.Op.UNION);
20009            }
20010            if (db.right < w) {
20011                //Log.i("VIEW", "Drawable right " + db.right + " < view " + w);
20012                r.op(db.right, 0, w, h, Region.Op.UNION);
20013            }
20014            if (db.top > 0) {
20015                //Log.i("VIEW", "Drawable top " + db.top + " > view 0");
20016                r.op(0, 0, w, db.top, Region.Op.UNION);
20017            }
20018            if (db.bottom < h) {
20019                //Log.i("VIEW", "Drawable bottom " + db.bottom + " < view " + h);
20020                r.op(0, db.bottom, w, h, Region.Op.UNION);
20021            }
20022            final int[] location = attachInfo.mTransparentLocation;
20023            getLocationInWindow(location);
20024            r.translate(location[0], location[1]);
20025            region.op(r, Region.Op.INTERSECT);
20026        } else {
20027            region.op(db, Region.Op.DIFFERENCE);
20028        }
20029    }
20030
20031    private void checkForLongClick(int delayOffset, float x, float y) {
20032        if ((mViewFlags & LONG_CLICKABLE) == LONG_CLICKABLE) {
20033            mHasPerformedLongPress = false;
20034
20035            if (mPendingCheckForLongPress == null) {
20036                mPendingCheckForLongPress = new CheckForLongPress();
20037            }
20038            mPendingCheckForLongPress.setAnchor(x, y);
20039            mPendingCheckForLongPress.rememberWindowAttachCount();
20040            postDelayed(mPendingCheckForLongPress,
20041                    ViewConfiguration.getLongPressTimeout() - delayOffset);
20042        }
20043    }
20044
20045    /**
20046     * Inflate a view from an XML resource.  This convenience method wraps the {@link
20047     * LayoutInflater} class, which provides a full range of options for view inflation.
20048     *
20049     * @param context The Context object for your activity or application.
20050     * @param resource The resource ID to inflate
20051     * @param root A view group that will be the parent.  Used to properly inflate the
20052     * layout_* parameters.
20053     * @see LayoutInflater
20054     */
20055    public static View inflate(Context context, @LayoutRes int resource, ViewGroup root) {
20056        LayoutInflater factory = LayoutInflater.from(context);
20057        return factory.inflate(resource, root);
20058    }
20059
20060    /**
20061     * Scroll the view with standard behavior for scrolling beyond the normal
20062     * content boundaries. Views that call this method should override
20063     * {@link #onOverScrolled(int, int, boolean, boolean)} to respond to the
20064     * results of an over-scroll operation.
20065     *
20066     * Views can use this method to handle any touch or fling-based scrolling.
20067     *
20068     * @param deltaX Change in X in pixels
20069     * @param deltaY Change in Y in pixels
20070     * @param scrollX Current X scroll value in pixels before applying deltaX
20071     * @param scrollY Current Y scroll value in pixels before applying deltaY
20072     * @param scrollRangeX Maximum content scroll range along the X axis
20073     * @param scrollRangeY Maximum content scroll range along the Y axis
20074     * @param maxOverScrollX Number of pixels to overscroll by in either direction
20075     *          along the X axis.
20076     * @param maxOverScrollY Number of pixels to overscroll by in either direction
20077     *          along the Y axis.
20078     * @param isTouchEvent true if this scroll operation is the result of a touch event.
20079     * @return true if scrolling was clamped to an over-scroll boundary along either
20080     *          axis, false otherwise.
20081     */
20082    @SuppressWarnings({"UnusedParameters"})
20083    protected boolean overScrollBy(int deltaX, int deltaY,
20084            int scrollX, int scrollY,
20085            int scrollRangeX, int scrollRangeY,
20086            int maxOverScrollX, int maxOverScrollY,
20087            boolean isTouchEvent) {
20088        final int overScrollMode = mOverScrollMode;
20089        final boolean canScrollHorizontal =
20090                computeHorizontalScrollRange() > computeHorizontalScrollExtent();
20091        final boolean canScrollVertical =
20092                computeVerticalScrollRange() > computeVerticalScrollExtent();
20093        final boolean overScrollHorizontal = overScrollMode == OVER_SCROLL_ALWAYS ||
20094                (overScrollMode == OVER_SCROLL_IF_CONTENT_SCROLLS && canScrollHorizontal);
20095        final boolean overScrollVertical = overScrollMode == OVER_SCROLL_ALWAYS ||
20096                (overScrollMode == OVER_SCROLL_IF_CONTENT_SCROLLS && canScrollVertical);
20097
20098        int newScrollX = scrollX + deltaX;
20099        if (!overScrollHorizontal) {
20100            maxOverScrollX = 0;
20101        }
20102
20103        int newScrollY = scrollY + deltaY;
20104        if (!overScrollVertical) {
20105            maxOverScrollY = 0;
20106        }
20107
20108        // Clamp values if at the limits and record
20109        final int left = -maxOverScrollX;
20110        final int right = maxOverScrollX + scrollRangeX;
20111        final int top = -maxOverScrollY;
20112        final int bottom = maxOverScrollY + scrollRangeY;
20113
20114        boolean clampedX = false;
20115        if (newScrollX > right) {
20116            newScrollX = right;
20117            clampedX = true;
20118        } else if (newScrollX < left) {
20119            newScrollX = left;
20120            clampedX = true;
20121        }
20122
20123        boolean clampedY = false;
20124        if (newScrollY > bottom) {
20125            newScrollY = bottom;
20126            clampedY = true;
20127        } else if (newScrollY < top) {
20128            newScrollY = top;
20129            clampedY = true;
20130        }
20131
20132        onOverScrolled(newScrollX, newScrollY, clampedX, clampedY);
20133
20134        return clampedX || clampedY;
20135    }
20136
20137    /**
20138     * Called by {@link #overScrollBy(int, int, int, int, int, int, int, int, boolean)} to
20139     * respond to the results of an over-scroll operation.
20140     *
20141     * @param scrollX New X scroll value in pixels
20142     * @param scrollY New Y scroll value in pixels
20143     * @param clampedX True if scrollX was clamped to an over-scroll boundary
20144     * @param clampedY True if scrollY was clamped to an over-scroll boundary
20145     */
20146    protected void onOverScrolled(int scrollX, int scrollY,
20147            boolean clampedX, boolean clampedY) {
20148        // Intentionally empty.
20149    }
20150
20151    /**
20152     * Returns the over-scroll mode for this view. The result will be
20153     * one of {@link #OVER_SCROLL_ALWAYS} (default), {@link #OVER_SCROLL_IF_CONTENT_SCROLLS}
20154     * (allow over-scrolling only if the view content is larger than the container),
20155     * or {@link #OVER_SCROLL_NEVER}.
20156     *
20157     * @return This view's over-scroll mode.
20158     */
20159    public int getOverScrollMode() {
20160        return mOverScrollMode;
20161    }
20162
20163    /**
20164     * Set the over-scroll mode for this view. Valid over-scroll modes are
20165     * {@link #OVER_SCROLL_ALWAYS} (default), {@link #OVER_SCROLL_IF_CONTENT_SCROLLS}
20166     * (allow over-scrolling only if the view content is larger than the container),
20167     * or {@link #OVER_SCROLL_NEVER}.
20168     *
20169     * Setting the over-scroll mode of a view will have an effect only if the
20170     * view is capable of scrolling.
20171     *
20172     * @param overScrollMode The new over-scroll mode for this view.
20173     */
20174    public void setOverScrollMode(int overScrollMode) {
20175        if (overScrollMode != OVER_SCROLL_ALWAYS &&
20176                overScrollMode != OVER_SCROLL_IF_CONTENT_SCROLLS &&
20177                overScrollMode != OVER_SCROLL_NEVER) {
20178            throw new IllegalArgumentException("Invalid overscroll mode " + overScrollMode);
20179        }
20180        mOverScrollMode = overScrollMode;
20181    }
20182
20183    /**
20184     * Enable or disable nested scrolling for this view.
20185     *
20186     * <p>If this property is set to true the view will be permitted to initiate nested
20187     * scrolling operations with a compatible parent view in the current hierarchy. If this
20188     * view does not implement nested scrolling this will have no effect. Disabling nested scrolling
20189     * while a nested scroll is in progress has the effect of {@link #stopNestedScroll() stopping}
20190     * the nested scroll.</p>
20191     *
20192     * @param enabled true to enable nested scrolling, false to disable
20193     *
20194     * @see #isNestedScrollingEnabled()
20195     */
20196    public void setNestedScrollingEnabled(boolean enabled) {
20197        if (enabled) {
20198            mPrivateFlags3 |= PFLAG3_NESTED_SCROLLING_ENABLED;
20199        } else {
20200            stopNestedScroll();
20201            mPrivateFlags3 &= ~PFLAG3_NESTED_SCROLLING_ENABLED;
20202        }
20203    }
20204
20205    /**
20206     * Returns true if nested scrolling is enabled for this view.
20207     *
20208     * <p>If nested scrolling is enabled and this View class implementation supports it,
20209     * this view will act as a nested scrolling child view when applicable, forwarding data
20210     * about the scroll operation in progress to a compatible and cooperating nested scrolling
20211     * parent.</p>
20212     *
20213     * @return true if nested scrolling is enabled
20214     *
20215     * @see #setNestedScrollingEnabled(boolean)
20216     */
20217    public boolean isNestedScrollingEnabled() {
20218        return (mPrivateFlags3 & PFLAG3_NESTED_SCROLLING_ENABLED) ==
20219                PFLAG3_NESTED_SCROLLING_ENABLED;
20220    }
20221
20222    /**
20223     * Begin a nestable scroll operation along the given axes.
20224     *
20225     * <p>A view starting a nested scroll promises to abide by the following contract:</p>
20226     *
20227     * <p>The view will call startNestedScroll upon initiating a scroll operation. In the case
20228     * of a touch scroll this corresponds to the initial {@link MotionEvent#ACTION_DOWN}.
20229     * In the case of touch scrolling the nested scroll will be terminated automatically in
20230     * the same manner as {@link ViewParent#requestDisallowInterceptTouchEvent(boolean)}.
20231     * In the event of programmatic scrolling the caller must explicitly call
20232     * {@link #stopNestedScroll()} to indicate the end of the nested scroll.</p>
20233     *
20234     * <p>If <code>startNestedScroll</code> returns true, a cooperative parent was found.
20235     * If it returns false the caller may ignore the rest of this contract until the next scroll.
20236     * Calling startNestedScroll while a nested scroll is already in progress will return true.</p>
20237     *
20238     * <p>At each incremental step of the scroll the caller should invoke
20239     * {@link #dispatchNestedPreScroll(int, int, int[], int[]) dispatchNestedPreScroll}
20240     * once it has calculated the requested scrolling delta. If it returns true the nested scrolling
20241     * parent at least partially consumed the scroll and the caller should adjust the amount it
20242     * scrolls by.</p>
20243     *
20244     * <p>After applying the remainder of the scroll delta the caller should invoke
20245     * {@link #dispatchNestedScroll(int, int, int, int, int[]) dispatchNestedScroll}, passing
20246     * both the delta consumed and the delta unconsumed. A nested scrolling parent may treat
20247     * these values differently. See {@link ViewParent#onNestedScroll(View, int, int, int, int)}.
20248     * </p>
20249     *
20250     * @param axes Flags consisting of a combination of {@link #SCROLL_AXIS_HORIZONTAL} and/or
20251     *             {@link #SCROLL_AXIS_VERTICAL}.
20252     * @return true if a cooperative parent was found and nested scrolling has been enabled for
20253     *         the current gesture.
20254     *
20255     * @see #stopNestedScroll()
20256     * @see #dispatchNestedPreScroll(int, int, int[], int[])
20257     * @see #dispatchNestedScroll(int, int, int, int, int[])
20258     */
20259    public boolean startNestedScroll(int axes) {
20260        if (hasNestedScrollingParent()) {
20261            // Already in progress
20262            return true;
20263        }
20264        if (isNestedScrollingEnabled()) {
20265            ViewParent p = getParent();
20266            View child = this;
20267            while (p != null) {
20268                try {
20269                    if (p.onStartNestedScroll(child, this, axes)) {
20270                        mNestedScrollingParent = p;
20271                        p.onNestedScrollAccepted(child, this, axes);
20272                        return true;
20273                    }
20274                } catch (AbstractMethodError e) {
20275                    Log.e(VIEW_LOG_TAG, "ViewParent " + p + " does not implement interface " +
20276                            "method onStartNestedScroll", e);
20277                    // Allow the search upward to continue
20278                }
20279                if (p instanceof View) {
20280                    child = (View) p;
20281                }
20282                p = p.getParent();
20283            }
20284        }
20285        return false;
20286    }
20287
20288    /**
20289     * Stop a nested scroll in progress.
20290     *
20291     * <p>Calling this method when a nested scroll is not currently in progress is harmless.</p>
20292     *
20293     * @see #startNestedScroll(int)
20294     */
20295    public void stopNestedScroll() {
20296        if (mNestedScrollingParent != null) {
20297            mNestedScrollingParent.onStopNestedScroll(this);
20298            mNestedScrollingParent = null;
20299        }
20300    }
20301
20302    /**
20303     * Returns true if this view has a nested scrolling parent.
20304     *
20305     * <p>The presence of a nested scrolling parent indicates that this view has initiated
20306     * a nested scroll and it was accepted by an ancestor view further up the view hierarchy.</p>
20307     *
20308     * @return whether this view has a nested scrolling parent
20309     */
20310    public boolean hasNestedScrollingParent() {
20311        return mNestedScrollingParent != null;
20312    }
20313
20314    /**
20315     * Dispatch one step of a nested scroll in progress.
20316     *
20317     * <p>Implementations of views that support nested scrolling should call this to report
20318     * info about a scroll in progress to the current nested scrolling parent. If a nested scroll
20319     * is not currently in progress or nested scrolling is not
20320     * {@link #isNestedScrollingEnabled() enabled} for this view this method does nothing.</p>
20321     *
20322     * <p>Compatible View implementations should also call
20323     * {@link #dispatchNestedPreScroll(int, int, int[], int[]) dispatchNestedPreScroll} before
20324     * consuming a component of the scroll event themselves.</p>
20325     *
20326     * @param dxConsumed Horizontal distance in pixels consumed by this view during this scroll step
20327     * @param dyConsumed Vertical distance in pixels consumed by this view during this scroll step
20328     * @param dxUnconsumed Horizontal scroll distance in pixels not consumed by this view
20329     * @param dyUnconsumed Horizontal scroll distance in pixels not consumed by this view
20330     * @param offsetInWindow Optional. If not null, on return this will contain the offset
20331     *                       in local view coordinates of this view from before this operation
20332     *                       to after it completes. View implementations may use this to adjust
20333     *                       expected input coordinate tracking.
20334     * @return true if the event was dispatched, false if it could not be dispatched.
20335     * @see #dispatchNestedPreScroll(int, int, int[], int[])
20336     */
20337    public boolean dispatchNestedScroll(int dxConsumed, int dyConsumed,
20338            int dxUnconsumed, int dyUnconsumed, @Nullable @Size(2) int[] offsetInWindow) {
20339        if (isNestedScrollingEnabled() && mNestedScrollingParent != null) {
20340            if (dxConsumed != 0 || dyConsumed != 0 || dxUnconsumed != 0 || dyUnconsumed != 0) {
20341                int startX = 0;
20342                int startY = 0;
20343                if (offsetInWindow != null) {
20344                    getLocationInWindow(offsetInWindow);
20345                    startX = offsetInWindow[0];
20346                    startY = offsetInWindow[1];
20347                }
20348
20349                mNestedScrollingParent.onNestedScroll(this, dxConsumed, dyConsumed,
20350                        dxUnconsumed, dyUnconsumed);
20351
20352                if (offsetInWindow != null) {
20353                    getLocationInWindow(offsetInWindow);
20354                    offsetInWindow[0] -= startX;
20355                    offsetInWindow[1] -= startY;
20356                }
20357                return true;
20358            } else if (offsetInWindow != null) {
20359                // No motion, no dispatch. Keep offsetInWindow up to date.
20360                offsetInWindow[0] = 0;
20361                offsetInWindow[1] = 0;
20362            }
20363        }
20364        return false;
20365    }
20366
20367    /**
20368     * Dispatch one step of a nested scroll in progress before this view consumes any portion of it.
20369     *
20370     * <p>Nested pre-scroll events are to nested scroll events what touch intercept is to touch.
20371     * <code>dispatchNestedPreScroll</code> offers an opportunity for the parent view in a nested
20372     * scrolling operation to consume some or all of the scroll operation before the child view
20373     * consumes it.</p>
20374     *
20375     * @param dx Horizontal scroll distance in pixels
20376     * @param dy Vertical scroll distance in pixels
20377     * @param consumed Output. If not null, consumed[0] will contain the consumed component of dx
20378     *                 and consumed[1] the consumed dy.
20379     * @param offsetInWindow Optional. If not null, on return this will contain the offset
20380     *                       in local view coordinates of this view from before this operation
20381     *                       to after it completes. View implementations may use this to adjust
20382     *                       expected input coordinate tracking.
20383     * @return true if the parent consumed some or all of the scroll delta
20384     * @see #dispatchNestedScroll(int, int, int, int, int[])
20385     */
20386    public boolean dispatchNestedPreScroll(int dx, int dy,
20387            @Nullable @Size(2) int[] consumed, @Nullable @Size(2) int[] offsetInWindow) {
20388        if (isNestedScrollingEnabled() && mNestedScrollingParent != null) {
20389            if (dx != 0 || dy != 0) {
20390                int startX = 0;
20391                int startY = 0;
20392                if (offsetInWindow != null) {
20393                    getLocationInWindow(offsetInWindow);
20394                    startX = offsetInWindow[0];
20395                    startY = offsetInWindow[1];
20396                }
20397
20398                if (consumed == null) {
20399                    if (mTempNestedScrollConsumed == null) {
20400                        mTempNestedScrollConsumed = new int[2];
20401                    }
20402                    consumed = mTempNestedScrollConsumed;
20403                }
20404                consumed[0] = 0;
20405                consumed[1] = 0;
20406                mNestedScrollingParent.onNestedPreScroll(this, dx, dy, consumed);
20407
20408                if (offsetInWindow != null) {
20409                    getLocationInWindow(offsetInWindow);
20410                    offsetInWindow[0] -= startX;
20411                    offsetInWindow[1] -= startY;
20412                }
20413                return consumed[0] != 0 || consumed[1] != 0;
20414            } else if (offsetInWindow != null) {
20415                offsetInWindow[0] = 0;
20416                offsetInWindow[1] = 0;
20417            }
20418        }
20419        return false;
20420    }
20421
20422    /**
20423     * Dispatch a fling to a nested scrolling parent.
20424     *
20425     * <p>This method should be used to indicate that a nested scrolling child has detected
20426     * suitable conditions for a fling. Generally this means that a touch scroll has ended with a
20427     * {@link VelocityTracker velocity} in the direction of scrolling that meets or exceeds
20428     * the {@link ViewConfiguration#getScaledMinimumFlingVelocity() minimum fling velocity}
20429     * along a scrollable axis.</p>
20430     *
20431     * <p>If a nested scrolling child view would normally fling but it is at the edge of
20432     * its own content, it can use this method to delegate the fling to its nested scrolling
20433     * parent instead. The parent may optionally consume the fling or observe a child fling.</p>
20434     *
20435     * @param velocityX Horizontal fling velocity in pixels per second
20436     * @param velocityY Vertical fling velocity in pixels per second
20437     * @param consumed true if the child consumed the fling, false otherwise
20438     * @return true if the nested scrolling parent consumed or otherwise reacted to the fling
20439     */
20440    public boolean dispatchNestedFling(float velocityX, float velocityY, boolean consumed) {
20441        if (isNestedScrollingEnabled() && mNestedScrollingParent != null) {
20442            return mNestedScrollingParent.onNestedFling(this, velocityX, velocityY, consumed);
20443        }
20444        return false;
20445    }
20446
20447    /**
20448     * Dispatch a fling to a nested scrolling parent before it is processed by this view.
20449     *
20450     * <p>Nested pre-fling events are to nested fling events what touch intercept is to touch
20451     * and what nested pre-scroll is to nested scroll. <code>dispatchNestedPreFling</code>
20452     * offsets an opportunity for the parent view in a nested fling to fully consume the fling
20453     * before the child view consumes it. If this method returns <code>true</code>, a nested
20454     * parent view consumed the fling and this view should not scroll as a result.</p>
20455     *
20456     * <p>For a better user experience, only one view in a nested scrolling chain should consume
20457     * the fling at a time. If a parent view consumed the fling this method will return false.
20458     * Custom view implementations should account for this in two ways:</p>
20459     *
20460     * <ul>
20461     *     <li>If a custom view is paged and needs to settle to a fixed page-point, do not
20462     *     call <code>dispatchNestedPreFling</code>; consume the fling and settle to a valid
20463     *     position regardless.</li>
20464     *     <li>If a nested parent does consume the fling, this view should not scroll at all,
20465     *     even to settle back to a valid idle position.</li>
20466     * </ul>
20467     *
20468     * <p>Views should also not offer fling velocities to nested parent views along an axis
20469     * where scrolling is not currently supported; a {@link android.widget.ScrollView ScrollView}
20470     * should not offer a horizontal fling velocity to its parents since scrolling along that
20471     * axis is not permitted and carrying velocity along that motion does not make sense.</p>
20472     *
20473     * @param velocityX Horizontal fling velocity in pixels per second
20474     * @param velocityY Vertical fling velocity in pixels per second
20475     * @return true if a nested scrolling parent consumed the fling
20476     */
20477    public boolean dispatchNestedPreFling(float velocityX, float velocityY) {
20478        if (isNestedScrollingEnabled() && mNestedScrollingParent != null) {
20479            return mNestedScrollingParent.onNestedPreFling(this, velocityX, velocityY);
20480        }
20481        return false;
20482    }
20483
20484    /**
20485     * Gets a scale factor that determines the distance the view should scroll
20486     * vertically in response to {@link MotionEvent#ACTION_SCROLL}.
20487     * @return The vertical scroll scale factor.
20488     * @hide
20489     */
20490    protected float getVerticalScrollFactor() {
20491        if (mVerticalScrollFactor == 0) {
20492            TypedValue outValue = new TypedValue();
20493            if (!mContext.getTheme().resolveAttribute(
20494                    com.android.internal.R.attr.listPreferredItemHeight, outValue, true)) {
20495                throw new IllegalStateException(
20496                        "Expected theme to define listPreferredItemHeight.");
20497            }
20498            mVerticalScrollFactor = outValue.getDimension(
20499                    mContext.getResources().getDisplayMetrics());
20500        }
20501        return mVerticalScrollFactor;
20502    }
20503
20504    /**
20505     * Gets a scale factor that determines the distance the view should scroll
20506     * horizontally in response to {@link MotionEvent#ACTION_SCROLL}.
20507     * @return The horizontal scroll scale factor.
20508     * @hide
20509     */
20510    protected float getHorizontalScrollFactor() {
20511        // TODO: Should use something else.
20512        return getVerticalScrollFactor();
20513    }
20514
20515    /**
20516     * Return the value specifying the text direction or policy that was set with
20517     * {@link #setTextDirection(int)}.
20518     *
20519     * @return the defined text direction. It can be one of:
20520     *
20521     * {@link #TEXT_DIRECTION_INHERIT},
20522     * {@link #TEXT_DIRECTION_FIRST_STRONG},
20523     * {@link #TEXT_DIRECTION_ANY_RTL},
20524     * {@link #TEXT_DIRECTION_LTR},
20525     * {@link #TEXT_DIRECTION_RTL},
20526     * {@link #TEXT_DIRECTION_LOCALE},
20527     * {@link #TEXT_DIRECTION_FIRST_STRONG_LTR},
20528     * {@link #TEXT_DIRECTION_FIRST_STRONG_RTL}
20529     *
20530     * @attr ref android.R.styleable#View_textDirection
20531     *
20532     * @hide
20533     */
20534    @ViewDebug.ExportedProperty(category = "text", mapping = {
20535            @ViewDebug.IntToString(from = TEXT_DIRECTION_INHERIT, to = "INHERIT"),
20536            @ViewDebug.IntToString(from = TEXT_DIRECTION_FIRST_STRONG, to = "FIRST_STRONG"),
20537            @ViewDebug.IntToString(from = TEXT_DIRECTION_ANY_RTL, to = "ANY_RTL"),
20538            @ViewDebug.IntToString(from = TEXT_DIRECTION_LTR, to = "LTR"),
20539            @ViewDebug.IntToString(from = TEXT_DIRECTION_RTL, to = "RTL"),
20540            @ViewDebug.IntToString(from = TEXT_DIRECTION_LOCALE, to = "LOCALE"),
20541            @ViewDebug.IntToString(from = TEXT_DIRECTION_FIRST_STRONG_LTR, to = "FIRST_STRONG_LTR"),
20542            @ViewDebug.IntToString(from = TEXT_DIRECTION_FIRST_STRONG_RTL, to = "FIRST_STRONG_RTL")
20543    })
20544    public int getRawTextDirection() {
20545        return (mPrivateFlags2 & PFLAG2_TEXT_DIRECTION_MASK) >> PFLAG2_TEXT_DIRECTION_MASK_SHIFT;
20546    }
20547
20548    /**
20549     * Set the text direction.
20550     *
20551     * @param textDirection the direction to set. Should be one of:
20552     *
20553     * {@link #TEXT_DIRECTION_INHERIT},
20554     * {@link #TEXT_DIRECTION_FIRST_STRONG},
20555     * {@link #TEXT_DIRECTION_ANY_RTL},
20556     * {@link #TEXT_DIRECTION_LTR},
20557     * {@link #TEXT_DIRECTION_RTL},
20558     * {@link #TEXT_DIRECTION_LOCALE}
20559     * {@link #TEXT_DIRECTION_FIRST_STRONG_LTR},
20560     * {@link #TEXT_DIRECTION_FIRST_STRONG_RTL},
20561     *
20562     * Resolution will be done if the value is set to TEXT_DIRECTION_INHERIT. The resolution
20563     * proceeds up the parent chain of the view to get the value. If there is no parent, then it will
20564     * return the default {@link #TEXT_DIRECTION_FIRST_STRONG}.
20565     *
20566     * @attr ref android.R.styleable#View_textDirection
20567     */
20568    public void setTextDirection(int textDirection) {
20569        if (getRawTextDirection() != textDirection) {
20570            // Reset the current text direction and the resolved one
20571            mPrivateFlags2 &= ~PFLAG2_TEXT_DIRECTION_MASK;
20572            resetResolvedTextDirection();
20573            // Set the new text direction
20574            mPrivateFlags2 |= ((textDirection << PFLAG2_TEXT_DIRECTION_MASK_SHIFT) & PFLAG2_TEXT_DIRECTION_MASK);
20575            // Do resolution
20576            resolveTextDirection();
20577            // Notify change
20578            onRtlPropertiesChanged(getLayoutDirection());
20579            // Refresh
20580            requestLayout();
20581            invalidate(true);
20582        }
20583    }
20584
20585    /**
20586     * Return the resolved text direction.
20587     *
20588     * @return the resolved text direction. Returns one of:
20589     *
20590     * {@link #TEXT_DIRECTION_FIRST_STRONG},
20591     * {@link #TEXT_DIRECTION_ANY_RTL},
20592     * {@link #TEXT_DIRECTION_LTR},
20593     * {@link #TEXT_DIRECTION_RTL},
20594     * {@link #TEXT_DIRECTION_LOCALE},
20595     * {@link #TEXT_DIRECTION_FIRST_STRONG_LTR},
20596     * {@link #TEXT_DIRECTION_FIRST_STRONG_RTL}
20597     *
20598     * @attr ref android.R.styleable#View_textDirection
20599     */
20600    @ViewDebug.ExportedProperty(category = "text", mapping = {
20601            @ViewDebug.IntToString(from = TEXT_DIRECTION_INHERIT, to = "INHERIT"),
20602            @ViewDebug.IntToString(from = TEXT_DIRECTION_FIRST_STRONG, to = "FIRST_STRONG"),
20603            @ViewDebug.IntToString(from = TEXT_DIRECTION_ANY_RTL, to = "ANY_RTL"),
20604            @ViewDebug.IntToString(from = TEXT_DIRECTION_LTR, to = "LTR"),
20605            @ViewDebug.IntToString(from = TEXT_DIRECTION_RTL, to = "RTL"),
20606            @ViewDebug.IntToString(from = TEXT_DIRECTION_LOCALE, to = "LOCALE"),
20607            @ViewDebug.IntToString(from = TEXT_DIRECTION_FIRST_STRONG_LTR, to = "FIRST_STRONG_LTR"),
20608            @ViewDebug.IntToString(from = TEXT_DIRECTION_FIRST_STRONG_RTL, to = "FIRST_STRONG_RTL")
20609    })
20610    public int getTextDirection() {
20611        return (mPrivateFlags2 & PFLAG2_TEXT_DIRECTION_RESOLVED_MASK) >> PFLAG2_TEXT_DIRECTION_RESOLVED_MASK_SHIFT;
20612    }
20613
20614    /**
20615     * Resolve the text direction.
20616     *
20617     * @return true if resolution has been done, false otherwise.
20618     *
20619     * @hide
20620     */
20621    public boolean resolveTextDirection() {
20622        // Reset any previous text direction resolution
20623        mPrivateFlags2 &= ~(PFLAG2_TEXT_DIRECTION_RESOLVED | PFLAG2_TEXT_DIRECTION_RESOLVED_MASK);
20624
20625        if (hasRtlSupport()) {
20626            // Set resolved text direction flag depending on text direction flag
20627            final int textDirection = getRawTextDirection();
20628            switch(textDirection) {
20629                case TEXT_DIRECTION_INHERIT:
20630                    if (!canResolveTextDirection()) {
20631                        // We cannot do the resolution if there is no parent, so use the default one
20632                        mPrivateFlags2 |= PFLAG2_TEXT_DIRECTION_RESOLVED_DEFAULT;
20633                        // Resolution will need to happen again later
20634                        return false;
20635                    }
20636
20637                    // Parent has not yet resolved, so we still return the default
20638                    try {
20639                        if (!mParent.isTextDirectionResolved()) {
20640                            mPrivateFlags2 |= PFLAG2_TEXT_DIRECTION_RESOLVED_DEFAULT;
20641                            // Resolution will need to happen again later
20642                            return false;
20643                        }
20644                    } catch (AbstractMethodError e) {
20645                        Log.e(VIEW_LOG_TAG, mParent.getClass().getSimpleName() +
20646                                " does not fully implement ViewParent", e);
20647                        mPrivateFlags2 |= PFLAG2_TEXT_DIRECTION_RESOLVED |
20648                                PFLAG2_TEXT_DIRECTION_RESOLVED_DEFAULT;
20649                        return true;
20650                    }
20651
20652                    // Set current resolved direction to the same value as the parent's one
20653                    int parentResolvedDirection;
20654                    try {
20655                        parentResolvedDirection = mParent.getTextDirection();
20656                    } catch (AbstractMethodError e) {
20657                        Log.e(VIEW_LOG_TAG, mParent.getClass().getSimpleName() +
20658                                " does not fully implement ViewParent", e);
20659                        parentResolvedDirection = TEXT_DIRECTION_LTR;
20660                    }
20661                    switch (parentResolvedDirection) {
20662                        case TEXT_DIRECTION_FIRST_STRONG:
20663                        case TEXT_DIRECTION_ANY_RTL:
20664                        case TEXT_DIRECTION_LTR:
20665                        case TEXT_DIRECTION_RTL:
20666                        case TEXT_DIRECTION_LOCALE:
20667                        case TEXT_DIRECTION_FIRST_STRONG_LTR:
20668                        case TEXT_DIRECTION_FIRST_STRONG_RTL:
20669                            mPrivateFlags2 |=
20670                                    (parentResolvedDirection << PFLAG2_TEXT_DIRECTION_RESOLVED_MASK_SHIFT);
20671                            break;
20672                        default:
20673                            // Default resolved direction is "first strong" heuristic
20674                            mPrivateFlags2 |= PFLAG2_TEXT_DIRECTION_RESOLVED_DEFAULT;
20675                    }
20676                    break;
20677                case TEXT_DIRECTION_FIRST_STRONG:
20678                case TEXT_DIRECTION_ANY_RTL:
20679                case TEXT_DIRECTION_LTR:
20680                case TEXT_DIRECTION_RTL:
20681                case TEXT_DIRECTION_LOCALE:
20682                case TEXT_DIRECTION_FIRST_STRONG_LTR:
20683                case TEXT_DIRECTION_FIRST_STRONG_RTL:
20684                    // Resolved direction is the same as text direction
20685                    mPrivateFlags2 |= (textDirection << PFLAG2_TEXT_DIRECTION_RESOLVED_MASK_SHIFT);
20686                    break;
20687                default:
20688                    // Default resolved direction is "first strong" heuristic
20689                    mPrivateFlags2 |= PFLAG2_TEXT_DIRECTION_RESOLVED_DEFAULT;
20690            }
20691        } else {
20692            // Default resolved direction is "first strong" heuristic
20693            mPrivateFlags2 |= PFLAG2_TEXT_DIRECTION_RESOLVED_DEFAULT;
20694        }
20695
20696        // Set to resolved
20697        mPrivateFlags2 |= PFLAG2_TEXT_DIRECTION_RESOLVED;
20698        return true;
20699    }
20700
20701    /**
20702     * Check if text direction resolution can be done.
20703     *
20704     * @return true if text direction resolution can be done otherwise return false.
20705     */
20706    public boolean canResolveTextDirection() {
20707        switch (getRawTextDirection()) {
20708            case TEXT_DIRECTION_INHERIT:
20709                if (mParent != null) {
20710                    try {
20711                        return mParent.canResolveTextDirection();
20712                    } catch (AbstractMethodError e) {
20713                        Log.e(VIEW_LOG_TAG, mParent.getClass().getSimpleName() +
20714                                " does not fully implement ViewParent", e);
20715                    }
20716                }
20717                return false;
20718
20719            default:
20720                return true;
20721        }
20722    }
20723
20724    /**
20725     * Reset resolved text direction. Text direction will be resolved during a call to
20726     * {@link #onMeasure(int, int)}.
20727     *
20728     * @hide
20729     */
20730    public void resetResolvedTextDirection() {
20731        // Reset any previous text direction resolution
20732        mPrivateFlags2 &= ~(PFLAG2_TEXT_DIRECTION_RESOLVED | PFLAG2_TEXT_DIRECTION_RESOLVED_MASK);
20733        // Set to default value
20734        mPrivateFlags2 |= PFLAG2_TEXT_DIRECTION_RESOLVED_DEFAULT;
20735    }
20736
20737    /**
20738     * @return true if text direction is inherited.
20739     *
20740     * @hide
20741     */
20742    public boolean isTextDirectionInherited() {
20743        return (getRawTextDirection() == TEXT_DIRECTION_INHERIT);
20744    }
20745
20746    /**
20747     * @return true if text direction is resolved.
20748     */
20749    public boolean isTextDirectionResolved() {
20750        return (mPrivateFlags2 & PFLAG2_TEXT_DIRECTION_RESOLVED) == PFLAG2_TEXT_DIRECTION_RESOLVED;
20751    }
20752
20753    /**
20754     * Return the value specifying the text alignment or policy that was set with
20755     * {@link #setTextAlignment(int)}.
20756     *
20757     * @return the defined text alignment. It can be one of:
20758     *
20759     * {@link #TEXT_ALIGNMENT_INHERIT},
20760     * {@link #TEXT_ALIGNMENT_GRAVITY},
20761     * {@link #TEXT_ALIGNMENT_CENTER},
20762     * {@link #TEXT_ALIGNMENT_TEXT_START},
20763     * {@link #TEXT_ALIGNMENT_TEXT_END},
20764     * {@link #TEXT_ALIGNMENT_VIEW_START},
20765     * {@link #TEXT_ALIGNMENT_VIEW_END}
20766     *
20767     * @attr ref android.R.styleable#View_textAlignment
20768     *
20769     * @hide
20770     */
20771    @ViewDebug.ExportedProperty(category = "text", mapping = {
20772            @ViewDebug.IntToString(from = TEXT_ALIGNMENT_INHERIT, to = "INHERIT"),
20773            @ViewDebug.IntToString(from = TEXT_ALIGNMENT_GRAVITY, to = "GRAVITY"),
20774            @ViewDebug.IntToString(from = TEXT_ALIGNMENT_TEXT_START, to = "TEXT_START"),
20775            @ViewDebug.IntToString(from = TEXT_ALIGNMENT_TEXT_END, to = "TEXT_END"),
20776            @ViewDebug.IntToString(from = TEXT_ALIGNMENT_CENTER, to = "CENTER"),
20777            @ViewDebug.IntToString(from = TEXT_ALIGNMENT_VIEW_START, to = "VIEW_START"),
20778            @ViewDebug.IntToString(from = TEXT_ALIGNMENT_VIEW_END, to = "VIEW_END")
20779    })
20780    @TextAlignment
20781    public int getRawTextAlignment() {
20782        return (mPrivateFlags2 & PFLAG2_TEXT_ALIGNMENT_MASK) >> PFLAG2_TEXT_ALIGNMENT_MASK_SHIFT;
20783    }
20784
20785    /**
20786     * Set the text alignment.
20787     *
20788     * @param textAlignment The text alignment to set. Should be one of
20789     *
20790     * {@link #TEXT_ALIGNMENT_INHERIT},
20791     * {@link #TEXT_ALIGNMENT_GRAVITY},
20792     * {@link #TEXT_ALIGNMENT_CENTER},
20793     * {@link #TEXT_ALIGNMENT_TEXT_START},
20794     * {@link #TEXT_ALIGNMENT_TEXT_END},
20795     * {@link #TEXT_ALIGNMENT_VIEW_START},
20796     * {@link #TEXT_ALIGNMENT_VIEW_END}
20797     *
20798     * Resolution will be done if the value is set to TEXT_ALIGNMENT_INHERIT. The resolution
20799     * proceeds up the parent chain of the view to get the value. If there is no parent, then it
20800     * will return the default {@link #TEXT_ALIGNMENT_GRAVITY}.
20801     *
20802     * @attr ref android.R.styleable#View_textAlignment
20803     */
20804    public void setTextAlignment(@TextAlignment int textAlignment) {
20805        if (textAlignment != getRawTextAlignment()) {
20806            // Reset the current and resolved text alignment
20807            mPrivateFlags2 &= ~PFLAG2_TEXT_ALIGNMENT_MASK;
20808            resetResolvedTextAlignment();
20809            // Set the new text alignment
20810            mPrivateFlags2 |=
20811                    ((textAlignment << PFLAG2_TEXT_ALIGNMENT_MASK_SHIFT) & PFLAG2_TEXT_ALIGNMENT_MASK);
20812            // Do resolution
20813            resolveTextAlignment();
20814            // Notify change
20815            onRtlPropertiesChanged(getLayoutDirection());
20816            // Refresh
20817            requestLayout();
20818            invalidate(true);
20819        }
20820    }
20821
20822    /**
20823     * Return the resolved text alignment.
20824     *
20825     * @return the resolved text alignment. Returns one of:
20826     *
20827     * {@link #TEXT_ALIGNMENT_GRAVITY},
20828     * {@link #TEXT_ALIGNMENT_CENTER},
20829     * {@link #TEXT_ALIGNMENT_TEXT_START},
20830     * {@link #TEXT_ALIGNMENT_TEXT_END},
20831     * {@link #TEXT_ALIGNMENT_VIEW_START},
20832     * {@link #TEXT_ALIGNMENT_VIEW_END}
20833     *
20834     * @attr ref android.R.styleable#View_textAlignment
20835     */
20836    @ViewDebug.ExportedProperty(category = "text", mapping = {
20837            @ViewDebug.IntToString(from = TEXT_ALIGNMENT_INHERIT, to = "INHERIT"),
20838            @ViewDebug.IntToString(from = TEXT_ALIGNMENT_GRAVITY, to = "GRAVITY"),
20839            @ViewDebug.IntToString(from = TEXT_ALIGNMENT_TEXT_START, to = "TEXT_START"),
20840            @ViewDebug.IntToString(from = TEXT_ALIGNMENT_TEXT_END, to = "TEXT_END"),
20841            @ViewDebug.IntToString(from = TEXT_ALIGNMENT_CENTER, to = "CENTER"),
20842            @ViewDebug.IntToString(from = TEXT_ALIGNMENT_VIEW_START, to = "VIEW_START"),
20843            @ViewDebug.IntToString(from = TEXT_ALIGNMENT_VIEW_END, to = "VIEW_END")
20844    })
20845    @TextAlignment
20846    public int getTextAlignment() {
20847        return (mPrivateFlags2 & PFLAG2_TEXT_ALIGNMENT_RESOLVED_MASK) >>
20848                PFLAG2_TEXT_ALIGNMENT_RESOLVED_MASK_SHIFT;
20849    }
20850
20851    /**
20852     * Resolve the text alignment.
20853     *
20854     * @return true if resolution has been done, false otherwise.
20855     *
20856     * @hide
20857     */
20858    public boolean resolveTextAlignment() {
20859        // Reset any previous text alignment resolution
20860        mPrivateFlags2 &= ~(PFLAG2_TEXT_ALIGNMENT_RESOLVED | PFLAG2_TEXT_ALIGNMENT_RESOLVED_MASK);
20861
20862        if (hasRtlSupport()) {
20863            // Set resolved text alignment flag depending on text alignment flag
20864            final int textAlignment = getRawTextAlignment();
20865            switch (textAlignment) {
20866                case TEXT_ALIGNMENT_INHERIT:
20867                    // Check if we can resolve the text alignment
20868                    if (!canResolveTextAlignment()) {
20869                        // We cannot do the resolution if there is no parent so use the default
20870                        mPrivateFlags2 |= PFLAG2_TEXT_ALIGNMENT_RESOLVED_DEFAULT;
20871                        // Resolution will need to happen again later
20872                        return false;
20873                    }
20874
20875                    // Parent has not yet resolved, so we still return the default
20876                    try {
20877                        if (!mParent.isTextAlignmentResolved()) {
20878                            mPrivateFlags2 |= PFLAG2_TEXT_ALIGNMENT_RESOLVED_DEFAULT;
20879                            // Resolution will need to happen again later
20880                            return false;
20881                        }
20882                    } catch (AbstractMethodError e) {
20883                        Log.e(VIEW_LOG_TAG, mParent.getClass().getSimpleName() +
20884                                " does not fully implement ViewParent", e);
20885                        mPrivateFlags2 |= PFLAG2_TEXT_ALIGNMENT_RESOLVED |
20886                                PFLAG2_TEXT_ALIGNMENT_RESOLVED_DEFAULT;
20887                        return true;
20888                    }
20889
20890                    int parentResolvedTextAlignment;
20891                    try {
20892                        parentResolvedTextAlignment = mParent.getTextAlignment();
20893                    } catch (AbstractMethodError e) {
20894                        Log.e(VIEW_LOG_TAG, mParent.getClass().getSimpleName() +
20895                                " does not fully implement ViewParent", e);
20896                        parentResolvedTextAlignment = TEXT_ALIGNMENT_GRAVITY;
20897                    }
20898                    switch (parentResolvedTextAlignment) {
20899                        case TEXT_ALIGNMENT_GRAVITY:
20900                        case TEXT_ALIGNMENT_TEXT_START:
20901                        case TEXT_ALIGNMENT_TEXT_END:
20902                        case TEXT_ALIGNMENT_CENTER:
20903                        case TEXT_ALIGNMENT_VIEW_START:
20904                        case TEXT_ALIGNMENT_VIEW_END:
20905                            // Resolved text alignment is the same as the parent resolved
20906                            // text alignment
20907                            mPrivateFlags2 |=
20908                                    (parentResolvedTextAlignment << PFLAG2_TEXT_ALIGNMENT_RESOLVED_MASK_SHIFT);
20909                            break;
20910                        default:
20911                            // Use default resolved text alignment
20912                            mPrivateFlags2 |= PFLAG2_TEXT_ALIGNMENT_RESOLVED_DEFAULT;
20913                    }
20914                    break;
20915                case TEXT_ALIGNMENT_GRAVITY:
20916                case TEXT_ALIGNMENT_TEXT_START:
20917                case TEXT_ALIGNMENT_TEXT_END:
20918                case TEXT_ALIGNMENT_CENTER:
20919                case TEXT_ALIGNMENT_VIEW_START:
20920                case TEXT_ALIGNMENT_VIEW_END:
20921                    // Resolved text alignment is the same as text alignment
20922                    mPrivateFlags2 |= (textAlignment << PFLAG2_TEXT_ALIGNMENT_RESOLVED_MASK_SHIFT);
20923                    break;
20924                default:
20925                    // Use default resolved text alignment
20926                    mPrivateFlags2 |= PFLAG2_TEXT_ALIGNMENT_RESOLVED_DEFAULT;
20927            }
20928        } else {
20929            // Use default resolved text alignment
20930            mPrivateFlags2 |= PFLAG2_TEXT_ALIGNMENT_RESOLVED_DEFAULT;
20931        }
20932
20933        // Set the resolved
20934        mPrivateFlags2 |= PFLAG2_TEXT_ALIGNMENT_RESOLVED;
20935        return true;
20936    }
20937
20938    /**
20939     * Check if text alignment resolution can be done.
20940     *
20941     * @return true if text alignment resolution can be done otherwise return false.
20942     */
20943    public boolean canResolveTextAlignment() {
20944        switch (getRawTextAlignment()) {
20945            case TEXT_DIRECTION_INHERIT:
20946                if (mParent != null) {
20947                    try {
20948                        return mParent.canResolveTextAlignment();
20949                    } catch (AbstractMethodError e) {
20950                        Log.e(VIEW_LOG_TAG, mParent.getClass().getSimpleName() +
20951                                " does not fully implement ViewParent", e);
20952                    }
20953                }
20954                return false;
20955
20956            default:
20957                return true;
20958        }
20959    }
20960
20961    /**
20962     * Reset resolved text alignment. Text alignment will be resolved during a call to
20963     * {@link #onMeasure(int, int)}.
20964     *
20965     * @hide
20966     */
20967    public void resetResolvedTextAlignment() {
20968        // Reset any previous text alignment resolution
20969        mPrivateFlags2 &= ~(PFLAG2_TEXT_ALIGNMENT_RESOLVED | PFLAG2_TEXT_ALIGNMENT_RESOLVED_MASK);
20970        // Set to default
20971        mPrivateFlags2 |= PFLAG2_TEXT_ALIGNMENT_RESOLVED_DEFAULT;
20972    }
20973
20974    /**
20975     * @return true if text alignment is inherited.
20976     *
20977     * @hide
20978     */
20979    public boolean isTextAlignmentInherited() {
20980        return (getRawTextAlignment() == TEXT_ALIGNMENT_INHERIT);
20981    }
20982
20983    /**
20984     * @return true if text alignment is resolved.
20985     */
20986    public boolean isTextAlignmentResolved() {
20987        return (mPrivateFlags2 & PFLAG2_TEXT_ALIGNMENT_RESOLVED) == PFLAG2_TEXT_ALIGNMENT_RESOLVED;
20988    }
20989
20990    /**
20991     * Generate a value suitable for use in {@link #setId(int)}.
20992     * This value will not collide with ID values generated at build time by aapt for R.id.
20993     *
20994     * @return a generated ID value
20995     */
20996    public static int generateViewId() {
20997        for (;;) {
20998            final int result = sNextGeneratedId.get();
20999            // aapt-generated IDs have the high byte nonzero; clamp to the range under that.
21000            int newValue = result + 1;
21001            if (newValue > 0x00FFFFFF) newValue = 1; // Roll over to 1, not 0.
21002            if (sNextGeneratedId.compareAndSet(result, newValue)) {
21003                return result;
21004            }
21005        }
21006    }
21007
21008    /**
21009     * Gets the Views in the hierarchy affected by entering and exiting Activity Scene transitions.
21010     * @param transitioningViews This View will be added to transitioningViews if it is VISIBLE and
21011     *                           a normal View or a ViewGroup with
21012     *                           {@link android.view.ViewGroup#isTransitionGroup()} true.
21013     * @hide
21014     */
21015    public void captureTransitioningViews(List<View> transitioningViews) {
21016        if (getVisibility() == View.VISIBLE) {
21017            transitioningViews.add(this);
21018        }
21019    }
21020
21021    /**
21022     * Adds all Views that have {@link #getTransitionName()} non-null to namedElements.
21023     * @param namedElements Will contain all Views in the hierarchy having a transitionName.
21024     * @hide
21025     */
21026    public void findNamedViews(Map<String, View> namedElements) {
21027        if (getVisibility() == VISIBLE || mGhostView != null) {
21028            String transitionName = getTransitionName();
21029            if (transitionName != null) {
21030                namedElements.put(transitionName, this);
21031            }
21032        }
21033    }
21034
21035    /** @hide */
21036    public int getPointerShape(MotionEvent event, float x, float y) {
21037        return PointerIcon.STYLE_NOT_SPECIFIED;
21038    }
21039
21040    //
21041    // Properties
21042    //
21043    /**
21044     * A Property wrapper around the <code>alpha</code> functionality handled by the
21045     * {@link View#setAlpha(float)} and {@link View#getAlpha()} methods.
21046     */
21047    public static final Property<View, Float> ALPHA = new FloatProperty<View>("alpha") {
21048        @Override
21049        public void setValue(View object, float value) {
21050            object.setAlpha(value);
21051        }
21052
21053        @Override
21054        public Float get(View object) {
21055            return object.getAlpha();
21056        }
21057    };
21058
21059    /**
21060     * A Property wrapper around the <code>translationX</code> functionality handled by the
21061     * {@link View#setTranslationX(float)} and {@link View#getTranslationX()} methods.
21062     */
21063    public static final Property<View, Float> TRANSLATION_X = new FloatProperty<View>("translationX") {
21064        @Override
21065        public void setValue(View object, float value) {
21066            object.setTranslationX(value);
21067        }
21068
21069                @Override
21070        public Float get(View object) {
21071            return object.getTranslationX();
21072        }
21073    };
21074
21075    /**
21076     * A Property wrapper around the <code>translationY</code> functionality handled by the
21077     * {@link View#setTranslationY(float)} and {@link View#getTranslationY()} methods.
21078     */
21079    public static final Property<View, Float> TRANSLATION_Y = new FloatProperty<View>("translationY") {
21080        @Override
21081        public void setValue(View object, float value) {
21082            object.setTranslationY(value);
21083        }
21084
21085        @Override
21086        public Float get(View object) {
21087            return object.getTranslationY();
21088        }
21089    };
21090
21091    /**
21092     * A Property wrapper around the <code>translationZ</code> functionality handled by the
21093     * {@link View#setTranslationZ(float)} and {@link View#getTranslationZ()} methods.
21094     */
21095    public static final Property<View, Float> TRANSLATION_Z = new FloatProperty<View>("translationZ") {
21096        @Override
21097        public void setValue(View object, float value) {
21098            object.setTranslationZ(value);
21099        }
21100
21101        @Override
21102        public Float get(View object) {
21103            return object.getTranslationZ();
21104        }
21105    };
21106
21107    /**
21108     * A Property wrapper around the <code>x</code> functionality handled by the
21109     * {@link View#setX(float)} and {@link View#getX()} methods.
21110     */
21111    public static final Property<View, Float> X = new FloatProperty<View>("x") {
21112        @Override
21113        public void setValue(View object, float value) {
21114            object.setX(value);
21115        }
21116
21117        @Override
21118        public Float get(View object) {
21119            return object.getX();
21120        }
21121    };
21122
21123    /**
21124     * A Property wrapper around the <code>y</code> functionality handled by the
21125     * {@link View#setY(float)} and {@link View#getY()} methods.
21126     */
21127    public static final Property<View, Float> Y = new FloatProperty<View>("y") {
21128        @Override
21129        public void setValue(View object, float value) {
21130            object.setY(value);
21131        }
21132
21133        @Override
21134        public Float get(View object) {
21135            return object.getY();
21136        }
21137    };
21138
21139    /**
21140     * A Property wrapper around the <code>z</code> functionality handled by the
21141     * {@link View#setZ(float)} and {@link View#getZ()} methods.
21142     */
21143    public static final Property<View, Float> Z = new FloatProperty<View>("z") {
21144        @Override
21145        public void setValue(View object, float value) {
21146            object.setZ(value);
21147        }
21148
21149        @Override
21150        public Float get(View object) {
21151            return object.getZ();
21152        }
21153    };
21154
21155    /**
21156     * A Property wrapper around the <code>rotation</code> functionality handled by the
21157     * {@link View#setRotation(float)} and {@link View#getRotation()} methods.
21158     */
21159    public static final Property<View, Float> ROTATION = new FloatProperty<View>("rotation") {
21160        @Override
21161        public void setValue(View object, float value) {
21162            object.setRotation(value);
21163        }
21164
21165        @Override
21166        public Float get(View object) {
21167            return object.getRotation();
21168        }
21169    };
21170
21171    /**
21172     * A Property wrapper around the <code>rotationX</code> functionality handled by the
21173     * {@link View#setRotationX(float)} and {@link View#getRotationX()} methods.
21174     */
21175    public static final Property<View, Float> ROTATION_X = new FloatProperty<View>("rotationX") {
21176        @Override
21177        public void setValue(View object, float value) {
21178            object.setRotationX(value);
21179        }
21180
21181        @Override
21182        public Float get(View object) {
21183            return object.getRotationX();
21184        }
21185    };
21186
21187    /**
21188     * A Property wrapper around the <code>rotationY</code> functionality handled by the
21189     * {@link View#setRotationY(float)} and {@link View#getRotationY()} methods.
21190     */
21191    public static final Property<View, Float> ROTATION_Y = new FloatProperty<View>("rotationY") {
21192        @Override
21193        public void setValue(View object, float value) {
21194            object.setRotationY(value);
21195        }
21196
21197        @Override
21198        public Float get(View object) {
21199            return object.getRotationY();
21200        }
21201    };
21202
21203    /**
21204     * A Property wrapper around the <code>scaleX</code> functionality handled by the
21205     * {@link View#setScaleX(float)} and {@link View#getScaleX()} methods.
21206     */
21207    public static final Property<View, Float> SCALE_X = new FloatProperty<View>("scaleX") {
21208        @Override
21209        public void setValue(View object, float value) {
21210            object.setScaleX(value);
21211        }
21212
21213        @Override
21214        public Float get(View object) {
21215            return object.getScaleX();
21216        }
21217    };
21218
21219    /**
21220     * A Property wrapper around the <code>scaleY</code> functionality handled by the
21221     * {@link View#setScaleY(float)} and {@link View#getScaleY()} methods.
21222     */
21223    public static final Property<View, Float> SCALE_Y = new FloatProperty<View>("scaleY") {
21224        @Override
21225        public void setValue(View object, float value) {
21226            object.setScaleY(value);
21227        }
21228
21229        @Override
21230        public Float get(View object) {
21231            return object.getScaleY();
21232        }
21233    };
21234
21235    /**
21236     * A MeasureSpec encapsulates the layout requirements passed from parent to child.
21237     * Each MeasureSpec represents a requirement for either the width or the height.
21238     * A MeasureSpec is comprised of a size and a mode. There are three possible
21239     * modes:
21240     * <dl>
21241     * <dt>UNSPECIFIED</dt>
21242     * <dd>
21243     * The parent has not imposed any constraint on the child. It can be whatever size
21244     * it wants.
21245     * </dd>
21246     *
21247     * <dt>EXACTLY</dt>
21248     * <dd>
21249     * The parent has determined an exact size for the child. The child is going to be
21250     * given those bounds regardless of how big it wants to be.
21251     * </dd>
21252     *
21253     * <dt>AT_MOST</dt>
21254     * <dd>
21255     * The child can be as large as it wants up to the specified size.
21256     * </dd>
21257     * </dl>
21258     *
21259     * MeasureSpecs are implemented as ints to reduce object allocation. This class
21260     * is provided to pack and unpack the &lt;size, mode&gt; tuple into the int.
21261     */
21262    public static class MeasureSpec {
21263        private static final int MODE_SHIFT = 30;
21264        private static final int MODE_MASK  = 0x3 << MODE_SHIFT;
21265
21266        /**
21267         * Measure specification mode: The parent has not imposed any constraint
21268         * on the child. It can be whatever size it wants.
21269         */
21270        public static final int UNSPECIFIED = 0 << MODE_SHIFT;
21271
21272        /**
21273         * Measure specification mode: The parent has determined an exact size
21274         * for the child. The child is going to be given those bounds regardless
21275         * of how big it wants to be.
21276         */
21277        public static final int EXACTLY     = 1 << MODE_SHIFT;
21278
21279        /**
21280         * Measure specification mode: The child can be as large as it wants up
21281         * to the specified size.
21282         */
21283        public static final int AT_MOST     = 2 << MODE_SHIFT;
21284
21285        /**
21286         * Creates a measure specification based on the supplied size and mode.
21287         *
21288         * The mode must always be one of the following:
21289         * <ul>
21290         *  <li>{@link android.view.View.MeasureSpec#UNSPECIFIED}</li>
21291         *  <li>{@link android.view.View.MeasureSpec#EXACTLY}</li>
21292         *  <li>{@link android.view.View.MeasureSpec#AT_MOST}</li>
21293         * </ul>
21294         *
21295         * <p><strong>Note:</strong> On API level 17 and lower, makeMeasureSpec's
21296         * implementation was such that the order of arguments did not matter
21297         * and overflow in either value could impact the resulting MeasureSpec.
21298         * {@link android.widget.RelativeLayout} was affected by this bug.
21299         * Apps targeting API levels greater than 17 will get the fixed, more strict
21300         * behavior.</p>
21301         *
21302         * @param size the size of the measure specification
21303         * @param mode the mode of the measure specification
21304         * @return the measure specification based on size and mode
21305         */
21306        public static int makeMeasureSpec(int size, int mode) {
21307            if (sUseBrokenMakeMeasureSpec) {
21308                return size + mode;
21309            } else {
21310                return (size & ~MODE_MASK) | (mode & MODE_MASK);
21311            }
21312        }
21313
21314        /**
21315         * Like {@link #makeMeasureSpec(int, int)}, but any spec with a mode of UNSPECIFIED
21316         * will automatically get a size of 0. Older apps expect this.
21317         *
21318         * @hide internal use only for compatibility with system widgets and older apps
21319         */
21320        public static int makeSafeMeasureSpec(int size, int mode) {
21321            if (sUseZeroUnspecifiedMeasureSpec && mode == UNSPECIFIED) {
21322                return 0;
21323            }
21324            return makeMeasureSpec(size, mode);
21325        }
21326
21327        /**
21328         * Extracts the mode from the supplied measure specification.
21329         *
21330         * @param measureSpec the measure specification to extract the mode from
21331         * @return {@link android.view.View.MeasureSpec#UNSPECIFIED},
21332         *         {@link android.view.View.MeasureSpec#AT_MOST} or
21333         *         {@link android.view.View.MeasureSpec#EXACTLY}
21334         */
21335        public static int getMode(int measureSpec) {
21336            return (measureSpec & MODE_MASK);
21337        }
21338
21339        /**
21340         * Extracts the size from the supplied measure specification.
21341         *
21342         * @param measureSpec the measure specification to extract the size from
21343         * @return the size in pixels defined in the supplied measure specification
21344         */
21345        public static int getSize(int measureSpec) {
21346            return (measureSpec & ~MODE_MASK);
21347        }
21348
21349        static int adjust(int measureSpec, int delta) {
21350            final int mode = getMode(measureSpec);
21351            int size = getSize(measureSpec);
21352            if (mode == UNSPECIFIED) {
21353                // No need to adjust size for UNSPECIFIED mode.
21354                return makeMeasureSpec(size, UNSPECIFIED);
21355            }
21356            size += delta;
21357            if (size < 0) {
21358                Log.e(VIEW_LOG_TAG, "MeasureSpec.adjust: new size would be negative! (" + size +
21359                        ") spec: " + toString(measureSpec) + " delta: " + delta);
21360                size = 0;
21361            }
21362            return makeMeasureSpec(size, mode);
21363        }
21364
21365        /**
21366         * Returns a String representation of the specified measure
21367         * specification.
21368         *
21369         * @param measureSpec the measure specification to convert to a String
21370         * @return a String with the following format: "MeasureSpec: MODE SIZE"
21371         */
21372        public static String toString(int measureSpec) {
21373            int mode = getMode(measureSpec);
21374            int size = getSize(measureSpec);
21375
21376            StringBuilder sb = new StringBuilder("MeasureSpec: ");
21377
21378            if (mode == UNSPECIFIED)
21379                sb.append("UNSPECIFIED ");
21380            else if (mode == EXACTLY)
21381                sb.append("EXACTLY ");
21382            else if (mode == AT_MOST)
21383                sb.append("AT_MOST ");
21384            else
21385                sb.append(mode).append(" ");
21386
21387            sb.append(size);
21388            return sb.toString();
21389        }
21390    }
21391
21392    private final class CheckForLongPress implements Runnable {
21393        private int mOriginalWindowAttachCount;
21394        private float mX;
21395        private float mY;
21396
21397        @Override
21398        public void run() {
21399            if (isPressed() && (mParent != null)
21400                    && mOriginalWindowAttachCount == mWindowAttachCount) {
21401                if (performLongClick(mX, mY)) {
21402                    mHasPerformedLongPress = true;
21403                }
21404            }
21405        }
21406
21407        public void setAnchor(float x, float y) {
21408            mX = x;
21409            mY = y;
21410        }
21411
21412        public void rememberWindowAttachCount() {
21413            mOriginalWindowAttachCount = mWindowAttachCount;
21414        }
21415    }
21416
21417    private final class CheckForTap implements Runnable {
21418        public float x;
21419        public float y;
21420
21421        @Override
21422        public void run() {
21423            mPrivateFlags &= ~PFLAG_PREPRESSED;
21424            setPressed(true, x, y);
21425            checkForLongClick(ViewConfiguration.getTapTimeout(), x, y);
21426        }
21427    }
21428
21429    private final class PerformClick implements Runnable {
21430        @Override
21431        public void run() {
21432            performClick();
21433        }
21434    }
21435
21436    /**
21437     * This method returns a ViewPropertyAnimator object, which can be used to animate
21438     * specific properties on this View.
21439     *
21440     * @return ViewPropertyAnimator The ViewPropertyAnimator associated with this View.
21441     */
21442    public ViewPropertyAnimator animate() {
21443        if (mAnimator == null) {
21444            mAnimator = new ViewPropertyAnimator(this);
21445        }
21446        return mAnimator;
21447    }
21448
21449    /**
21450     * Sets the name of the View to be used to identify Views in Transitions.
21451     * Names should be unique in the View hierarchy.
21452     *
21453     * @param transitionName The name of the View to uniquely identify it for Transitions.
21454     */
21455    public final void setTransitionName(String transitionName) {
21456        mTransitionName = transitionName;
21457    }
21458
21459    /**
21460     * Returns the name of the View to be used to identify Views in Transitions.
21461     * Names should be unique in the View hierarchy.
21462     *
21463     * <p>This returns null if the View has not been given a name.</p>
21464     *
21465     * @return The name used of the View to be used to identify Views in Transitions or null
21466     * if no name has been given.
21467     */
21468    @ViewDebug.ExportedProperty
21469    public String getTransitionName() {
21470        return mTransitionName;
21471    }
21472
21473    /**
21474     * Interface definition for a callback to be invoked when a hardware key event is
21475     * dispatched to this view. The callback will be invoked before the key event is
21476     * given to the view. This is only useful for hardware keyboards; a software input
21477     * method has no obligation to trigger this listener.
21478     */
21479    public interface OnKeyListener {
21480        /**
21481         * Called when a hardware key is dispatched to a view. This allows listeners to
21482         * get a chance to respond before the target view.
21483         * <p>Key presses in software keyboards will generally NOT trigger this method,
21484         * although some may elect to do so in some situations. Do not assume a
21485         * software input method has to be key-based; even if it is, it may use key presses
21486         * in a different way than you expect, so there is no way to reliably catch soft
21487         * input key presses.
21488         *
21489         * @param v The view the key has been dispatched to.
21490         * @param keyCode The code for the physical key that was pressed
21491         * @param event The KeyEvent object containing full information about
21492         *        the event.
21493         * @return True if the listener has consumed the event, false otherwise.
21494         */
21495        boolean onKey(View v, int keyCode, KeyEvent event);
21496    }
21497
21498    /**
21499     * Interface definition for a callback to be invoked when a touch event is
21500     * dispatched to this view. The callback will be invoked before the touch
21501     * event is given to the view.
21502     */
21503    public interface OnTouchListener {
21504        /**
21505         * Called when a touch event is dispatched to a view. This allows listeners to
21506         * get a chance to respond before the target view.
21507         *
21508         * @param v The view the touch event has been dispatched to.
21509         * @param event The MotionEvent object containing full information about
21510         *        the event.
21511         * @return True if the listener has consumed the event, false otherwise.
21512         */
21513        boolean onTouch(View v, MotionEvent event);
21514    }
21515
21516    /**
21517     * Interface definition for a callback to be invoked when a hover event is
21518     * dispatched to this view. The callback will be invoked before the hover
21519     * event is given to the view.
21520     */
21521    public interface OnHoverListener {
21522        /**
21523         * Called when a hover event is dispatched to a view. This allows listeners to
21524         * get a chance to respond before the target view.
21525         *
21526         * @param v The view the hover event has been dispatched to.
21527         * @param event The MotionEvent object containing full information about
21528         *        the event.
21529         * @return True if the listener has consumed the event, false otherwise.
21530         */
21531        boolean onHover(View v, MotionEvent event);
21532    }
21533
21534    /**
21535     * Interface definition for a callback to be invoked when a generic motion event is
21536     * dispatched to this view. The callback will be invoked before the generic motion
21537     * event is given to the view.
21538     */
21539    public interface OnGenericMotionListener {
21540        /**
21541         * Called when a generic motion event is dispatched to a view. This allows listeners to
21542         * get a chance to respond before the target view.
21543         *
21544         * @param v The view the generic motion event has been dispatched to.
21545         * @param event The MotionEvent object containing full information about
21546         *        the event.
21547         * @return True if the listener has consumed the event, false otherwise.
21548         */
21549        boolean onGenericMotion(View v, MotionEvent event);
21550    }
21551
21552    /**
21553     * Interface definition for a callback to be invoked when a view has been clicked and held.
21554     */
21555    public interface OnLongClickListener {
21556        /**
21557         * Called when a view has been clicked and held.
21558         *
21559         * @param v The view that was clicked and held.
21560         *
21561         * @return true if the callback consumed the long click, false otherwise.
21562         */
21563        boolean onLongClick(View v);
21564    }
21565
21566    /**
21567     * Interface definition for a callback to be invoked when a drag is being dispatched
21568     * to this view.  The callback will be invoked before the hosting view's own
21569     * onDrag(event) method.  If the listener wants to fall back to the hosting view's
21570     * onDrag(event) behavior, it should return 'false' from this callback.
21571     *
21572     * <div class="special reference">
21573     * <h3>Developer Guides</h3>
21574     * <p>For a guide to implementing drag and drop features, read the
21575     * <a href="{@docRoot}guide/topics/ui/drag-drop.html">Drag and Drop</a> developer guide.</p>
21576     * </div>
21577     */
21578    public interface OnDragListener {
21579        /**
21580         * Called when a drag event is dispatched to a view. This allows listeners
21581         * to get a chance to override base View behavior.
21582         *
21583         * @param v The View that received the drag event.
21584         * @param event The {@link android.view.DragEvent} object for the drag event.
21585         * @return {@code true} if the drag event was handled successfully, or {@code false}
21586         * if the drag event was not handled. Note that {@code false} will trigger the View
21587         * to call its {@link #onDragEvent(DragEvent) onDragEvent()} handler.
21588         */
21589        boolean onDrag(View v, DragEvent event);
21590    }
21591
21592    /**
21593     * Interface definition for a callback to be invoked when the focus state of
21594     * a view changed.
21595     */
21596    public interface OnFocusChangeListener {
21597        /**
21598         * Called when the focus state of a view has changed.
21599         *
21600         * @param v The view whose state has changed.
21601         * @param hasFocus The new focus state of v.
21602         */
21603        void onFocusChange(View v, boolean hasFocus);
21604    }
21605
21606    /**
21607     * Interface definition for a callback to be invoked when a view is clicked.
21608     */
21609    public interface OnClickListener {
21610        /**
21611         * Called when a view has been clicked.
21612         *
21613         * @param v The view that was clicked.
21614         */
21615        void onClick(View v);
21616    }
21617
21618    /**
21619     * Interface definition for a callback to be invoked when a view is context clicked.
21620     */
21621    public interface OnContextClickListener {
21622        /**
21623         * Called when a view is context clicked.
21624         *
21625         * @param v The view that has been context clicked.
21626         * @return true if the callback consumed the context click, false otherwise.
21627         */
21628        boolean onContextClick(View v);
21629    }
21630
21631    /**
21632     * Interface definition for a callback to be invoked when the context menu
21633     * for this view is being built.
21634     */
21635    public interface OnCreateContextMenuListener {
21636        /**
21637         * Called when the context menu for this view is being built. It is not
21638         * safe to hold onto the menu after this method returns.
21639         *
21640         * @param menu The context menu that is being built
21641         * @param v The view for which the context menu is being built
21642         * @param menuInfo Extra information about the item for which the
21643         *            context menu should be shown. This information will vary
21644         *            depending on the class of v.
21645         */
21646        void onCreateContextMenu(ContextMenu menu, View v, ContextMenuInfo menuInfo);
21647    }
21648
21649    /**
21650     * Interface definition for a callback to be invoked when the status bar changes
21651     * visibility.  This reports <strong>global</strong> changes to the system UI
21652     * state, not what the application is requesting.
21653     *
21654     * @see View#setOnSystemUiVisibilityChangeListener(android.view.View.OnSystemUiVisibilityChangeListener)
21655     */
21656    public interface OnSystemUiVisibilityChangeListener {
21657        /**
21658         * Called when the status bar changes visibility because of a call to
21659         * {@link View#setSystemUiVisibility(int)}.
21660         *
21661         * @param visibility  Bitwise-or of flags {@link #SYSTEM_UI_FLAG_LOW_PROFILE},
21662         * {@link #SYSTEM_UI_FLAG_HIDE_NAVIGATION}, and {@link #SYSTEM_UI_FLAG_FULLSCREEN}.
21663         * This tells you the <strong>global</strong> state of these UI visibility
21664         * flags, not what your app is currently applying.
21665         */
21666        public void onSystemUiVisibilityChange(int visibility);
21667    }
21668
21669    /**
21670     * Interface definition for a callback to be invoked when this view is attached
21671     * or detached from its window.
21672     */
21673    public interface OnAttachStateChangeListener {
21674        /**
21675         * Called when the view is attached to a window.
21676         * @param v The view that was attached
21677         */
21678        public void onViewAttachedToWindow(View v);
21679        /**
21680         * Called when the view is detached from a window.
21681         * @param v The view that was detached
21682         */
21683        public void onViewDetachedFromWindow(View v);
21684    }
21685
21686    /**
21687     * Listener for applying window insets on a view in a custom way.
21688     *
21689     * <p>Apps may choose to implement this interface if they want to apply custom policy
21690     * to the way that window insets are treated for a view. If an OnApplyWindowInsetsListener
21691     * is set, its
21692     * {@link OnApplyWindowInsetsListener#onApplyWindowInsets(View, WindowInsets) onApplyWindowInsets}
21693     * method will be called instead of the View's own
21694     * {@link #onApplyWindowInsets(WindowInsets) onApplyWindowInsets} method. The listener
21695     * may optionally call the parameter View's <code>onApplyWindowInsets</code> method to apply
21696     * the View's normal behavior as part of its own.</p>
21697     */
21698    public interface OnApplyWindowInsetsListener {
21699        /**
21700         * When {@link View#setOnApplyWindowInsetsListener(View.OnApplyWindowInsetsListener) set}
21701         * on a View, this listener method will be called instead of the view's own
21702         * {@link View#onApplyWindowInsets(WindowInsets) onApplyWindowInsets} method.
21703         *
21704         * @param v The view applying window insets
21705         * @param insets The insets to apply
21706         * @return The insets supplied, minus any insets that were consumed
21707         */
21708        public WindowInsets onApplyWindowInsets(View v, WindowInsets insets);
21709    }
21710
21711    private final class UnsetPressedState implements Runnable {
21712        @Override
21713        public void run() {
21714            setPressed(false);
21715        }
21716    }
21717
21718    /**
21719     * Base class for derived classes that want to save and restore their own
21720     * state in {@link android.view.View#onSaveInstanceState()}.
21721     */
21722    public static class BaseSavedState extends AbsSavedState {
21723        String mStartActivityRequestWhoSaved;
21724
21725        /**
21726         * Constructor used when reading from a parcel. Reads the state of the superclass.
21727         *
21728         * @param source
21729         */
21730        public BaseSavedState(Parcel source) {
21731            super(source);
21732            mStartActivityRequestWhoSaved = source.readString();
21733        }
21734
21735        /**
21736         * Constructor called by derived classes when creating their SavedState objects
21737         *
21738         * @param superState The state of the superclass of this view
21739         */
21740        public BaseSavedState(Parcelable superState) {
21741            super(superState);
21742        }
21743
21744        @Override
21745        public void writeToParcel(Parcel out, int flags) {
21746            super.writeToParcel(out, flags);
21747            out.writeString(mStartActivityRequestWhoSaved);
21748        }
21749
21750        public static final Parcelable.Creator<BaseSavedState> CREATOR =
21751                new Parcelable.Creator<BaseSavedState>() {
21752            public BaseSavedState createFromParcel(Parcel in) {
21753                return new BaseSavedState(in);
21754            }
21755
21756            public BaseSavedState[] newArray(int size) {
21757                return new BaseSavedState[size];
21758            }
21759        };
21760    }
21761
21762    /**
21763     * A set of information given to a view when it is attached to its parent
21764     * window.
21765     */
21766    final static class AttachInfo {
21767        interface Callbacks {
21768            void playSoundEffect(int effectId);
21769            boolean performHapticFeedback(int effectId, boolean always);
21770        }
21771
21772        /**
21773         * InvalidateInfo is used to post invalidate(int, int, int, int) messages
21774         * to a Handler. This class contains the target (View) to invalidate and
21775         * the coordinates of the dirty rectangle.
21776         *
21777         * For performance purposes, this class also implements a pool of up to
21778         * POOL_LIMIT objects that get reused. This reduces memory allocations
21779         * whenever possible.
21780         */
21781        static class InvalidateInfo {
21782            private static final int POOL_LIMIT = 10;
21783
21784            private static final SynchronizedPool<InvalidateInfo> sPool =
21785                    new SynchronizedPool<InvalidateInfo>(POOL_LIMIT);
21786
21787            View target;
21788
21789            int left;
21790            int top;
21791            int right;
21792            int bottom;
21793
21794            public static InvalidateInfo obtain() {
21795                InvalidateInfo instance = sPool.acquire();
21796                return (instance != null) ? instance : new InvalidateInfo();
21797            }
21798
21799            public void recycle() {
21800                target = null;
21801                sPool.release(this);
21802            }
21803        }
21804
21805        final IWindowSession mSession;
21806
21807        final IWindow mWindow;
21808
21809        final IBinder mWindowToken;
21810
21811        final Display mDisplay;
21812
21813        final Callbacks mRootCallbacks;
21814
21815        IWindowId mIWindowId;
21816        WindowId mWindowId;
21817
21818        /**
21819         * The top view of the hierarchy.
21820         */
21821        View mRootView;
21822
21823        IBinder mPanelParentWindowToken;
21824
21825        boolean mHardwareAccelerated;
21826        boolean mHardwareAccelerationRequested;
21827        HardwareRenderer mHardwareRenderer;
21828        List<RenderNode> mPendingAnimatingRenderNodes;
21829
21830        /**
21831         * The state of the display to which the window is attached, as reported
21832         * by {@link Display#getState()}.  Note that the display state constants
21833         * declared by {@link Display} do not exactly line up with the screen state
21834         * constants declared by {@link View} (there are more display states than
21835         * screen states).
21836         */
21837        int mDisplayState = Display.STATE_UNKNOWN;
21838
21839        /**
21840         * Scale factor used by the compatibility mode
21841         */
21842        float mApplicationScale;
21843
21844        /**
21845         * Indicates whether the application is in compatibility mode
21846         */
21847        boolean mScalingRequired;
21848
21849        /**
21850         * Left position of this view's window
21851         */
21852        int mWindowLeft;
21853
21854        /**
21855         * Top position of this view's window
21856         */
21857        int mWindowTop;
21858
21859        /**
21860         * Indicates whether views need to use 32-bit drawing caches
21861         */
21862        boolean mUse32BitDrawingCache;
21863
21864        /**
21865         * For windows that are full-screen but using insets to layout inside
21866         * of the screen areas, these are the current insets to appear inside
21867         * the overscan area of the display.
21868         */
21869        final Rect mOverscanInsets = new Rect();
21870
21871        /**
21872         * For windows that are full-screen but using insets to layout inside
21873         * of the screen decorations, these are the current insets for the
21874         * content of the window.
21875         */
21876        final Rect mContentInsets = new Rect();
21877
21878        /**
21879         * For windows that are full-screen but using insets to layout inside
21880         * of the screen decorations, these are the current insets for the
21881         * actual visible parts of the window.
21882         */
21883        final Rect mVisibleInsets = new Rect();
21884
21885        /**
21886         * For windows that are full-screen but using insets to layout inside
21887         * of the screen decorations, these are the current insets for the
21888         * stable system windows.
21889         */
21890        final Rect mStableInsets = new Rect();
21891
21892        /**
21893         * For windows that include areas that are not covered by real surface these are the outsets
21894         * for real surface.
21895         */
21896        final Rect mOutsets = new Rect();
21897
21898        /**
21899         * The internal insets given by this window.  This value is
21900         * supplied by the client (through
21901         * {@link ViewTreeObserver.OnComputeInternalInsetsListener}) and will
21902         * be given to the window manager when changed to be used in laying
21903         * out windows behind it.
21904         */
21905        final ViewTreeObserver.InternalInsetsInfo mGivenInternalInsets
21906                = new ViewTreeObserver.InternalInsetsInfo();
21907
21908        /**
21909         * Set to true when mGivenInternalInsets is non-empty.
21910         */
21911        boolean mHasNonEmptyGivenInternalInsets;
21912
21913        /**
21914         * All views in the window's hierarchy that serve as scroll containers,
21915         * used to determine if the window can be resized or must be panned
21916         * to adjust for a soft input area.
21917         */
21918        final ArrayList<View> mScrollContainers = new ArrayList<View>();
21919
21920        final KeyEvent.DispatcherState mKeyDispatchState
21921                = new KeyEvent.DispatcherState();
21922
21923        /**
21924         * Indicates whether the view's window currently has the focus.
21925         */
21926        boolean mHasWindowFocus;
21927
21928        /**
21929         * The current visibility of the window.
21930         */
21931        int mWindowVisibility;
21932
21933        /**
21934         * Indicates the time at which drawing started to occur.
21935         */
21936        long mDrawingTime;
21937
21938        /**
21939         * Indicates whether or not ignoring the DIRTY_MASK flags.
21940         */
21941        boolean mIgnoreDirtyState;
21942
21943        /**
21944         * This flag tracks when the mIgnoreDirtyState flag is set during draw(),
21945         * to avoid clearing that flag prematurely.
21946         */
21947        boolean mSetIgnoreDirtyState = false;
21948
21949        /**
21950         * Indicates whether the view's window is currently in touch mode.
21951         */
21952        boolean mInTouchMode;
21953
21954        /**
21955         * Indicates whether the view has requested unbuffered input dispatching for the current
21956         * event stream.
21957         */
21958        boolean mUnbufferedDispatchRequested;
21959
21960        /**
21961         * Indicates that ViewAncestor should trigger a global layout change
21962         * the next time it performs a traversal
21963         */
21964        boolean mRecomputeGlobalAttributes;
21965
21966        /**
21967         * Always report new attributes at next traversal.
21968         */
21969        boolean mForceReportNewAttributes;
21970
21971        /**
21972         * Set during a traveral if any views want to keep the screen on.
21973         */
21974        boolean mKeepScreenOn;
21975
21976        /**
21977         * Bitwise-or of all of the values that views have passed to setSystemUiVisibility().
21978         */
21979        int mSystemUiVisibility;
21980
21981        /**
21982         * Hack to force certain system UI visibility flags to be cleared.
21983         */
21984        int mDisabledSystemUiVisibility;
21985
21986        /**
21987         * Last global system UI visibility reported by the window manager.
21988         */
21989        int mGlobalSystemUiVisibility;
21990
21991        /**
21992         * True if a view in this hierarchy has an OnSystemUiVisibilityChangeListener
21993         * attached.
21994         */
21995        boolean mHasSystemUiListeners;
21996
21997        /**
21998         * Set if the window has requested to extend into the overscan region
21999         * via WindowManager.LayoutParams.FLAG_LAYOUT_IN_OVERSCAN.
22000         */
22001        boolean mOverscanRequested;
22002
22003        /**
22004         * Set if the visibility of any views has changed.
22005         */
22006        boolean mViewVisibilityChanged;
22007
22008        /**
22009         * Set to true if a view has been scrolled.
22010         */
22011        boolean mViewScrollChanged;
22012
22013        /**
22014         * Set to true if high contrast mode enabled
22015         */
22016        boolean mHighContrastText;
22017
22018        /**
22019         * Global to the view hierarchy used as a temporary for dealing with
22020         * x/y points in the transparent region computations.
22021         */
22022        final int[] mTransparentLocation = new int[2];
22023
22024        /**
22025         * Global to the view hierarchy used as a temporary for dealing with
22026         * x/y points in the ViewGroup.invalidateChild implementation.
22027         */
22028        final int[] mInvalidateChildLocation = new int[2];
22029
22030        /**
22031         * Global to the view hierarchy used as a temporary for dealng with
22032         * computing absolute on-screen location.
22033         */
22034        final int[] mTmpLocation = new int[2];
22035
22036        /**
22037         * Global to the view hierarchy used as a temporary for dealing with
22038         * x/y location when view is transformed.
22039         */
22040        final float[] mTmpTransformLocation = new float[2];
22041
22042        /**
22043         * The view tree observer used to dispatch global events like
22044         * layout, pre-draw, touch mode change, etc.
22045         */
22046        final ViewTreeObserver mTreeObserver = new ViewTreeObserver();
22047
22048        /**
22049         * A Canvas used by the view hierarchy to perform bitmap caching.
22050         */
22051        Canvas mCanvas;
22052
22053        /**
22054         * The view root impl.
22055         */
22056        final ViewRootImpl mViewRootImpl;
22057
22058        /**
22059         * A Handler supplied by a view's {@link android.view.ViewRootImpl}. This
22060         * handler can be used to pump events in the UI events queue.
22061         */
22062        final Handler mHandler;
22063
22064        /**
22065         * Temporary for use in computing invalidate rectangles while
22066         * calling up the hierarchy.
22067         */
22068        final Rect mTmpInvalRect = new Rect();
22069
22070        /**
22071         * Temporary for use in computing hit areas with transformed views
22072         */
22073        final RectF mTmpTransformRect = new RectF();
22074
22075        /**
22076         * Temporary for use in computing hit areas with transformed views
22077         */
22078        final RectF mTmpTransformRect1 = new RectF();
22079
22080        /**
22081         * Temporary list of rectanges.
22082         */
22083        final List<RectF> mTmpRectList = new ArrayList<>();
22084
22085        /**
22086         * Temporary for use in transforming invalidation rect
22087         */
22088        final Matrix mTmpMatrix = new Matrix();
22089
22090        /**
22091         * Temporary for use in transforming invalidation rect
22092         */
22093        final Transformation mTmpTransformation = new Transformation();
22094
22095        /**
22096         * Temporary for use in querying outlines from OutlineProviders
22097         */
22098        final Outline mTmpOutline = new Outline();
22099
22100        /**
22101         * Temporary list for use in collecting focusable descendents of a view.
22102         */
22103        final ArrayList<View> mTempArrayList = new ArrayList<View>(24);
22104
22105        /**
22106         * The id of the window for accessibility purposes.
22107         */
22108        int mAccessibilityWindowId = AccessibilityNodeInfo.UNDEFINED_ITEM_ID;
22109
22110        /**
22111         * Flags related to accessibility processing.
22112         *
22113         * @see AccessibilityNodeInfo#FLAG_INCLUDE_NOT_IMPORTANT_VIEWS
22114         * @see AccessibilityNodeInfo#FLAG_REPORT_VIEW_IDS
22115         */
22116        int mAccessibilityFetchFlags;
22117
22118        /**
22119         * The drawable for highlighting accessibility focus.
22120         */
22121        Drawable mAccessibilityFocusDrawable;
22122
22123        /**
22124         * Show where the margins, bounds and layout bounds are for each view.
22125         */
22126        boolean mDebugLayout = SystemProperties.getBoolean(DEBUG_LAYOUT_PROPERTY, false);
22127
22128        /**
22129         * Point used to compute visible regions.
22130         */
22131        final Point mPoint = new Point();
22132
22133        /**
22134         * Used to track which View originated a requestLayout() call, used when
22135         * requestLayout() is called during layout.
22136         */
22137        View mViewRequestingLayout;
22138
22139        /**
22140         * Creates a new set of attachment information with the specified
22141         * events handler and thread.
22142         *
22143         * @param handler the events handler the view must use
22144         */
22145        AttachInfo(IWindowSession session, IWindow window, Display display,
22146                ViewRootImpl viewRootImpl, Handler handler, Callbacks effectPlayer) {
22147            mSession = session;
22148            mWindow = window;
22149            mWindowToken = window.asBinder();
22150            mDisplay = display;
22151            mViewRootImpl = viewRootImpl;
22152            mHandler = handler;
22153            mRootCallbacks = effectPlayer;
22154        }
22155    }
22156
22157    /**
22158     * <p>ScrollabilityCache holds various fields used by a View when scrolling
22159     * is supported. This avoids keeping too many unused fields in most
22160     * instances of View.</p>
22161     */
22162    private static class ScrollabilityCache implements Runnable {
22163
22164        /**
22165         * Scrollbars are not visible
22166         */
22167        public static final int OFF = 0;
22168
22169        /**
22170         * Scrollbars are visible
22171         */
22172        public static final int ON = 1;
22173
22174        /**
22175         * Scrollbars are fading away
22176         */
22177        public static final int FADING = 2;
22178
22179        public boolean fadeScrollBars;
22180
22181        public int fadingEdgeLength;
22182        public int scrollBarDefaultDelayBeforeFade;
22183        public int scrollBarFadeDuration;
22184
22185        public int scrollBarSize;
22186        public ScrollBarDrawable scrollBar;
22187        public float[] interpolatorValues;
22188        public View host;
22189
22190        public final Paint paint;
22191        public final Matrix matrix;
22192        public Shader shader;
22193
22194        public final Interpolator scrollBarInterpolator = new Interpolator(1, 2);
22195
22196        private static final float[] OPAQUE = { 255 };
22197        private static final float[] TRANSPARENT = { 0.0f };
22198
22199        /**
22200         * When fading should start. This time moves into the future every time
22201         * a new scroll happens. Measured based on SystemClock.uptimeMillis()
22202         */
22203        public long fadeStartTime;
22204
22205
22206        /**
22207         * The current state of the scrollbars: ON, OFF, or FADING
22208         */
22209        public int state = OFF;
22210
22211        private int mLastColor;
22212
22213        public ScrollabilityCache(ViewConfiguration configuration, View host) {
22214            fadingEdgeLength = configuration.getScaledFadingEdgeLength();
22215            scrollBarSize = configuration.getScaledScrollBarSize();
22216            scrollBarDefaultDelayBeforeFade = ViewConfiguration.getScrollDefaultDelay();
22217            scrollBarFadeDuration = ViewConfiguration.getScrollBarFadeDuration();
22218
22219            paint = new Paint();
22220            matrix = new Matrix();
22221            // use use a height of 1, and then wack the matrix each time we
22222            // actually use it.
22223            shader = new LinearGradient(0, 0, 0, 1, 0xFF000000, 0, Shader.TileMode.CLAMP);
22224            paint.setShader(shader);
22225            paint.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.DST_OUT));
22226
22227            this.host = host;
22228        }
22229
22230        public void setFadeColor(int color) {
22231            if (color != mLastColor) {
22232                mLastColor = color;
22233
22234                if (color != 0) {
22235                    shader = new LinearGradient(0, 0, 0, 1, color | 0xFF000000,
22236                            color & 0x00FFFFFF, Shader.TileMode.CLAMP);
22237                    paint.setShader(shader);
22238                    // Restore the default transfer mode (src_over)
22239                    paint.setXfermode(null);
22240                } else {
22241                    shader = new LinearGradient(0, 0, 0, 1, 0xFF000000, 0, Shader.TileMode.CLAMP);
22242                    paint.setShader(shader);
22243                    paint.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.DST_OUT));
22244                }
22245            }
22246        }
22247
22248        public void run() {
22249            long now = AnimationUtils.currentAnimationTimeMillis();
22250            if (now >= fadeStartTime) {
22251
22252                // the animation fades the scrollbars out by changing
22253                // the opacity (alpha) from fully opaque to fully
22254                // transparent
22255                int nextFrame = (int) now;
22256                int framesCount = 0;
22257
22258                Interpolator interpolator = scrollBarInterpolator;
22259
22260                // Start opaque
22261                interpolator.setKeyFrame(framesCount++, nextFrame, OPAQUE);
22262
22263                // End transparent
22264                nextFrame += scrollBarFadeDuration;
22265                interpolator.setKeyFrame(framesCount, nextFrame, TRANSPARENT);
22266
22267                state = FADING;
22268
22269                // Kick off the fade animation
22270                host.invalidate(true);
22271            }
22272        }
22273    }
22274
22275    /**
22276     * Resuable callback for sending
22277     * {@link AccessibilityEvent#TYPE_VIEW_SCROLLED} accessibility event.
22278     */
22279    private class SendViewScrolledAccessibilityEvent implements Runnable {
22280        public volatile boolean mIsPending;
22281
22282        public void run() {
22283            sendAccessibilityEvent(AccessibilityEvent.TYPE_VIEW_SCROLLED);
22284            mIsPending = false;
22285        }
22286    }
22287
22288    /**
22289     * <p>
22290     * This class represents a delegate that can be registered in a {@link View}
22291     * to enhance accessibility support via composition rather via inheritance.
22292     * It is specifically targeted to widget developers that extend basic View
22293     * classes i.e. classes in package android.view, that would like their
22294     * applications to be backwards compatible.
22295     * </p>
22296     * <div class="special reference">
22297     * <h3>Developer Guides</h3>
22298     * <p>For more information about making applications accessible, read the
22299     * <a href="{@docRoot}guide/topics/ui/accessibility/index.html">Accessibility</a>
22300     * developer guide.</p>
22301     * </div>
22302     * <p>
22303     * A scenario in which a developer would like to use an accessibility delegate
22304     * is overriding a method introduced in a later API version then the minimal API
22305     * version supported by the application. For example, the method
22306     * {@link View#onInitializeAccessibilityNodeInfo(AccessibilityNodeInfo)} is not available
22307     * in API version 4 when the accessibility APIs were first introduced. If a
22308     * developer would like his application to run on API version 4 devices (assuming
22309     * all other APIs used by the application are version 4 or lower) and take advantage
22310     * of this method, instead of overriding the method which would break the application's
22311     * backwards compatibility, he can override the corresponding method in this
22312     * delegate and register the delegate in the target View if the API version of
22313     * the system is high enough i.e. the API version is same or higher to the API
22314     * version that introduced
22315     * {@link View#onInitializeAccessibilityNodeInfo(AccessibilityNodeInfo)}.
22316     * </p>
22317     * <p>
22318     * Here is an example implementation:
22319     * </p>
22320     * <code><pre><p>
22321     * if (Build.VERSION.SDK_INT >= 14) {
22322     *     // If the API version is equal of higher than the version in
22323     *     // which onInitializeAccessibilityNodeInfo was introduced we
22324     *     // register a delegate with a customized implementation.
22325     *     View view = findViewById(R.id.view_id);
22326     *     view.setAccessibilityDelegate(new AccessibilityDelegate() {
22327     *         public void onInitializeAccessibilityNodeInfo(View host,
22328     *                 AccessibilityNodeInfo info) {
22329     *             // Let the default implementation populate the info.
22330     *             super.onInitializeAccessibilityNodeInfo(host, info);
22331     *             // Set some other information.
22332     *             info.setEnabled(host.isEnabled());
22333     *         }
22334     *     });
22335     * }
22336     * </code></pre></p>
22337     * <p>
22338     * This delegate contains methods that correspond to the accessibility methods
22339     * in View. If a delegate has been specified the implementation in View hands
22340     * off handling to the corresponding method in this delegate. The default
22341     * implementation the delegate methods behaves exactly as the corresponding
22342     * method in View for the case of no accessibility delegate been set. Hence,
22343     * to customize the behavior of a View method, clients can override only the
22344     * corresponding delegate method without altering the behavior of the rest
22345     * accessibility related methods of the host view.
22346     * </p>
22347     * <p>
22348     * <strong>Note:</strong> On platform versions prior to
22349     * {@link android.os.Build.VERSION_CODES#M API 23}, delegate methods on
22350     * views in the {@code android.widget.*} package are called <i>before</i>
22351     * host methods. This prevents certain properties such as class name from
22352     * being modified by overriding
22353     * {@link AccessibilityDelegate#onInitializeAccessibilityNodeInfo(View, AccessibilityNodeInfo)},
22354     * as any changes will be overwritten by the host class.
22355     * <p>
22356     * Starting in {@link android.os.Build.VERSION_CODES#M API 23}, delegate
22357     * methods are called <i>after</i> host methods, which all properties to be
22358     * modified without being overwritten by the host class.
22359     */
22360    public static class AccessibilityDelegate {
22361
22362        /**
22363         * Sends an accessibility event of the given type. If accessibility is not
22364         * enabled this method has no effect.
22365         * <p>
22366         * The default implementation behaves as {@link View#sendAccessibilityEvent(int)
22367         *  View#sendAccessibilityEvent(int)} for the case of no accessibility delegate
22368         * been set.
22369         * </p>
22370         *
22371         * @param host The View hosting the delegate.
22372         * @param eventType The type of the event to send.
22373         *
22374         * @see View#sendAccessibilityEvent(int) View#sendAccessibilityEvent(int)
22375         */
22376        public void sendAccessibilityEvent(View host, int eventType) {
22377            host.sendAccessibilityEventInternal(eventType);
22378        }
22379
22380        /**
22381         * Performs the specified accessibility action on the view. For
22382         * possible accessibility actions look at {@link AccessibilityNodeInfo}.
22383         * <p>
22384         * The default implementation behaves as
22385         * {@link View#performAccessibilityAction(int, Bundle)
22386         *  View#performAccessibilityAction(int, Bundle)} for the case of
22387         *  no accessibility delegate been set.
22388         * </p>
22389         *
22390         * @param action The action to perform.
22391         * @return Whether the action was performed.
22392         *
22393         * @see View#performAccessibilityAction(int, Bundle)
22394         *      View#performAccessibilityAction(int, Bundle)
22395         */
22396        public boolean performAccessibilityAction(View host, int action, Bundle args) {
22397            return host.performAccessibilityActionInternal(action, args);
22398        }
22399
22400        /**
22401         * Sends an accessibility event. This method behaves exactly as
22402         * {@link #sendAccessibilityEvent(View, int)} but takes as an argument an
22403         * empty {@link AccessibilityEvent} and does not perform a check whether
22404         * accessibility is enabled.
22405         * <p>
22406         * The default implementation behaves as
22407         * {@link View#sendAccessibilityEventUnchecked(AccessibilityEvent)
22408         *  View#sendAccessibilityEventUnchecked(AccessibilityEvent)} for
22409         * the case of no accessibility delegate been set.
22410         * </p>
22411         *
22412         * @param host The View hosting the delegate.
22413         * @param event The event to send.
22414         *
22415         * @see View#sendAccessibilityEventUnchecked(AccessibilityEvent)
22416         *      View#sendAccessibilityEventUnchecked(AccessibilityEvent)
22417         */
22418        public void sendAccessibilityEventUnchecked(View host, AccessibilityEvent event) {
22419            host.sendAccessibilityEventUncheckedInternal(event);
22420        }
22421
22422        /**
22423         * Dispatches an {@link AccessibilityEvent} to the host {@link View} first and then
22424         * to its children for adding their text content to the event.
22425         * <p>
22426         * The default implementation behaves as
22427         * {@link View#dispatchPopulateAccessibilityEvent(AccessibilityEvent)
22428         *  View#dispatchPopulateAccessibilityEvent(AccessibilityEvent)} for
22429         * the case of no accessibility delegate been set.
22430         * </p>
22431         *
22432         * @param host The View hosting the delegate.
22433         * @param event The event.
22434         * @return True if the event population was completed.
22435         *
22436         * @see View#dispatchPopulateAccessibilityEvent(AccessibilityEvent)
22437         *      View#dispatchPopulateAccessibilityEvent(AccessibilityEvent)
22438         */
22439        public boolean dispatchPopulateAccessibilityEvent(View host, AccessibilityEvent event) {
22440            return host.dispatchPopulateAccessibilityEventInternal(event);
22441        }
22442
22443        /**
22444         * Gives a chance to the host View to populate the accessibility event with its
22445         * text content.
22446         * <p>
22447         * The default implementation behaves as
22448         * {@link View#onPopulateAccessibilityEvent(AccessibilityEvent)
22449         *  View#onPopulateAccessibilityEvent(AccessibilityEvent)} for
22450         * the case of no accessibility delegate been set.
22451         * </p>
22452         *
22453         * @param host The View hosting the delegate.
22454         * @param event The accessibility event which to populate.
22455         *
22456         * @see View#onPopulateAccessibilityEvent(AccessibilityEvent)
22457         *      View#onPopulateAccessibilityEvent(AccessibilityEvent)
22458         */
22459        public void onPopulateAccessibilityEvent(View host, AccessibilityEvent event) {
22460            host.onPopulateAccessibilityEventInternal(event);
22461        }
22462
22463        /**
22464         * Initializes an {@link AccessibilityEvent} with information about the
22465         * the host View which is the event source.
22466         * <p>
22467         * The default implementation behaves as
22468         * {@link View#onInitializeAccessibilityEvent(AccessibilityEvent)
22469         *  View#onInitializeAccessibilityEvent(AccessibilityEvent)} for
22470         * the case of no accessibility delegate been set.
22471         * </p>
22472         *
22473         * @param host The View hosting the delegate.
22474         * @param event The event to initialize.
22475         *
22476         * @see View#onInitializeAccessibilityEvent(AccessibilityEvent)
22477         *      View#onInitializeAccessibilityEvent(AccessibilityEvent)
22478         */
22479        public void onInitializeAccessibilityEvent(View host, AccessibilityEvent event) {
22480            host.onInitializeAccessibilityEventInternal(event);
22481        }
22482
22483        /**
22484         * Initializes an {@link AccessibilityNodeInfo} with information about the host view.
22485         * <p>
22486         * The default implementation behaves as
22487         * {@link View#onInitializeAccessibilityNodeInfo(AccessibilityNodeInfo)
22488         *  View#onInitializeAccessibilityNodeInfo(AccessibilityNodeInfo)} for
22489         * the case of no accessibility delegate been set.
22490         * </p>
22491         *
22492         * @param host The View hosting the delegate.
22493         * @param info The instance to initialize.
22494         *
22495         * @see View#onInitializeAccessibilityNodeInfo(AccessibilityNodeInfo)
22496         *      View#onInitializeAccessibilityNodeInfo(AccessibilityNodeInfo)
22497         */
22498        public void onInitializeAccessibilityNodeInfo(View host, AccessibilityNodeInfo info) {
22499            host.onInitializeAccessibilityNodeInfoInternal(info);
22500        }
22501
22502        /**
22503         * Called when a child of the host View has requested sending an
22504         * {@link AccessibilityEvent} and gives an opportunity to the parent (the host)
22505         * to augment the event.
22506         * <p>
22507         * The default implementation behaves as
22508         * {@link ViewGroup#onRequestSendAccessibilityEvent(View, AccessibilityEvent)
22509         *  ViewGroup#onRequestSendAccessibilityEvent(View, AccessibilityEvent)} for
22510         * the case of no accessibility delegate been set.
22511         * </p>
22512         *
22513         * @param host The View hosting the delegate.
22514         * @param child The child which requests sending the event.
22515         * @param event The event to be sent.
22516         * @return True if the event should be sent
22517         *
22518         * @see ViewGroup#onRequestSendAccessibilityEvent(View, AccessibilityEvent)
22519         *      ViewGroup#onRequestSendAccessibilityEvent(View, AccessibilityEvent)
22520         */
22521        public boolean onRequestSendAccessibilityEvent(ViewGroup host, View child,
22522                AccessibilityEvent event) {
22523            return host.onRequestSendAccessibilityEventInternal(child, event);
22524        }
22525
22526        /**
22527         * Gets the provider for managing a virtual view hierarchy rooted at this View
22528         * and reported to {@link android.accessibilityservice.AccessibilityService}s
22529         * that explore the window content.
22530         * <p>
22531         * The default implementation behaves as
22532         * {@link View#getAccessibilityNodeProvider() View#getAccessibilityNodeProvider()} for
22533         * the case of no accessibility delegate been set.
22534         * </p>
22535         *
22536         * @return The provider.
22537         *
22538         * @see AccessibilityNodeProvider
22539         */
22540        public AccessibilityNodeProvider getAccessibilityNodeProvider(View host) {
22541            return null;
22542        }
22543
22544        /**
22545         * Returns an {@link AccessibilityNodeInfo} representing the host view from the
22546         * point of view of an {@link android.accessibilityservice.AccessibilityService}.
22547         * This method is responsible for obtaining an accessibility node info from a
22548         * pool of reusable instances and calling
22549         * {@link #onInitializeAccessibilityNodeInfo(AccessibilityNodeInfo)} on the host
22550         * view to initialize the former.
22551         * <p>
22552         * <strong>Note:</strong> The client is responsible for recycling the obtained
22553         * instance by calling {@link AccessibilityNodeInfo#recycle()} to minimize object
22554         * creation.
22555         * </p>
22556         * <p>
22557         * The default implementation behaves as
22558         * {@link View#createAccessibilityNodeInfo() View#createAccessibilityNodeInfo()} for
22559         * the case of no accessibility delegate been set.
22560         * </p>
22561         * @return A populated {@link AccessibilityNodeInfo}.
22562         *
22563         * @see AccessibilityNodeInfo
22564         *
22565         * @hide
22566         */
22567        public AccessibilityNodeInfo createAccessibilityNodeInfo(View host) {
22568            return host.createAccessibilityNodeInfoInternal();
22569        }
22570    }
22571
22572    private class MatchIdPredicate implements Predicate<View> {
22573        public int mId;
22574
22575        @Override
22576        public boolean apply(View view) {
22577            return (view.mID == mId);
22578        }
22579    }
22580
22581    private class MatchLabelForPredicate implements Predicate<View> {
22582        private int mLabeledId;
22583
22584        @Override
22585        public boolean apply(View view) {
22586            return (view.mLabelForId == mLabeledId);
22587        }
22588    }
22589
22590    private class SendViewStateChangedAccessibilityEvent implements Runnable {
22591        private int mChangeTypes = 0;
22592        private boolean mPosted;
22593        private boolean mPostedWithDelay;
22594        private long mLastEventTimeMillis;
22595
22596        @Override
22597        public void run() {
22598            mPosted = false;
22599            mPostedWithDelay = false;
22600            mLastEventTimeMillis = SystemClock.uptimeMillis();
22601            if (AccessibilityManager.getInstance(mContext).isEnabled()) {
22602                final AccessibilityEvent event = AccessibilityEvent.obtain();
22603                event.setEventType(AccessibilityEvent.TYPE_WINDOW_CONTENT_CHANGED);
22604                event.setContentChangeTypes(mChangeTypes);
22605                sendAccessibilityEventUnchecked(event);
22606            }
22607            mChangeTypes = 0;
22608        }
22609
22610        public void runOrPost(int changeType) {
22611            mChangeTypes |= changeType;
22612
22613            // If this is a live region or the child of a live region, collect
22614            // all events from this frame and send them on the next frame.
22615            if (inLiveRegion()) {
22616                // If we're already posted with a delay, remove that.
22617                if (mPostedWithDelay) {
22618                    removeCallbacks(this);
22619                    mPostedWithDelay = false;
22620                }
22621                // Only post if we're not already posted.
22622                if (!mPosted) {
22623                    post(this);
22624                    mPosted = true;
22625                }
22626                return;
22627            }
22628
22629            if (mPosted) {
22630                return;
22631            }
22632
22633            final long timeSinceLastMillis = SystemClock.uptimeMillis() - mLastEventTimeMillis;
22634            final long minEventIntevalMillis =
22635                    ViewConfiguration.getSendRecurringAccessibilityEventsInterval();
22636            if (timeSinceLastMillis >= minEventIntevalMillis) {
22637                removeCallbacks(this);
22638                run();
22639            } else {
22640                postDelayed(this, minEventIntevalMillis - timeSinceLastMillis);
22641                mPostedWithDelay = true;
22642            }
22643        }
22644    }
22645
22646    private boolean inLiveRegion() {
22647        if (getAccessibilityLiveRegion() != View.ACCESSIBILITY_LIVE_REGION_NONE) {
22648            return true;
22649        }
22650
22651        ViewParent parent = getParent();
22652        while (parent instanceof View) {
22653            if (((View) parent).getAccessibilityLiveRegion()
22654                    != View.ACCESSIBILITY_LIVE_REGION_NONE) {
22655                return true;
22656            }
22657            parent = parent.getParent();
22658        }
22659
22660        return false;
22661    }
22662
22663    /**
22664     * Dump all private flags in readable format, useful for documentation and
22665     * sanity checking.
22666     */
22667    private static void dumpFlags() {
22668        final HashMap<String, String> found = Maps.newHashMap();
22669        try {
22670            for (Field field : View.class.getDeclaredFields()) {
22671                final int modifiers = field.getModifiers();
22672                if (Modifier.isStatic(modifiers) && Modifier.isFinal(modifiers)) {
22673                    if (field.getType().equals(int.class)) {
22674                        final int value = field.getInt(null);
22675                        dumpFlag(found, field.getName(), value);
22676                    } else if (field.getType().equals(int[].class)) {
22677                        final int[] values = (int[]) field.get(null);
22678                        for (int i = 0; i < values.length; i++) {
22679                            dumpFlag(found, field.getName() + "[" + i + "]", values[i]);
22680                        }
22681                    }
22682                }
22683            }
22684        } catch (IllegalAccessException e) {
22685            throw new RuntimeException(e);
22686        }
22687
22688        final ArrayList<String> keys = Lists.newArrayList();
22689        keys.addAll(found.keySet());
22690        Collections.sort(keys);
22691        for (String key : keys) {
22692            Log.d(VIEW_LOG_TAG, found.get(key));
22693        }
22694    }
22695
22696    private static void dumpFlag(HashMap<String, String> found, String name, int value) {
22697        // Sort flags by prefix, then by bits, always keeping unique keys
22698        final String bits = String.format("%32s", Integer.toBinaryString(value)).replace('0', ' ');
22699        final int prefix = name.indexOf('_');
22700        final String key = (prefix > 0 ? name.substring(0, prefix) : name) + bits + name;
22701        final String output = bits + " " + name;
22702        found.put(key, output);
22703    }
22704
22705    /** {@hide} */
22706    public void encode(@NonNull ViewHierarchyEncoder stream) {
22707        stream.beginObject(this);
22708        encodeProperties(stream);
22709        stream.endObject();
22710    }
22711
22712    /** {@hide} */
22713    @CallSuper
22714    protected void encodeProperties(@NonNull ViewHierarchyEncoder stream) {
22715        Object resolveId = ViewDebug.resolveId(getContext(), mID);
22716        if (resolveId instanceof String) {
22717            stream.addProperty("id", (String) resolveId);
22718        } else {
22719            stream.addProperty("id", mID);
22720        }
22721
22722        stream.addProperty("misc:transformation.alpha",
22723                mTransformationInfo != null ? mTransformationInfo.mAlpha : 0);
22724        stream.addProperty("misc:transitionName", getTransitionName());
22725
22726        // layout
22727        stream.addProperty("layout:left", mLeft);
22728        stream.addProperty("layout:right", mRight);
22729        stream.addProperty("layout:top", mTop);
22730        stream.addProperty("layout:bottom", mBottom);
22731        stream.addProperty("layout:width", getWidth());
22732        stream.addProperty("layout:height", getHeight());
22733        stream.addProperty("layout:layoutDirection", getLayoutDirection());
22734        stream.addProperty("layout:layoutRtl", isLayoutRtl());
22735        stream.addProperty("layout:hasTransientState", hasTransientState());
22736        stream.addProperty("layout:baseline", getBaseline());
22737
22738        // layout params
22739        ViewGroup.LayoutParams layoutParams = getLayoutParams();
22740        if (layoutParams != null) {
22741            stream.addPropertyKey("layoutParams");
22742            layoutParams.encode(stream);
22743        }
22744
22745        // scrolling
22746        stream.addProperty("scrolling:scrollX", mScrollX);
22747        stream.addProperty("scrolling:scrollY", mScrollY);
22748
22749        // padding
22750        stream.addProperty("padding:paddingLeft", mPaddingLeft);
22751        stream.addProperty("padding:paddingRight", mPaddingRight);
22752        stream.addProperty("padding:paddingTop", mPaddingTop);
22753        stream.addProperty("padding:paddingBottom", mPaddingBottom);
22754        stream.addProperty("padding:userPaddingRight", mUserPaddingRight);
22755        stream.addProperty("padding:userPaddingLeft", mUserPaddingLeft);
22756        stream.addProperty("padding:userPaddingBottom", mUserPaddingBottom);
22757        stream.addProperty("padding:userPaddingStart", mUserPaddingStart);
22758        stream.addProperty("padding:userPaddingEnd", mUserPaddingEnd);
22759
22760        // measurement
22761        stream.addProperty("measurement:minHeight", mMinHeight);
22762        stream.addProperty("measurement:minWidth", mMinWidth);
22763        stream.addProperty("measurement:measuredWidth", mMeasuredWidth);
22764        stream.addProperty("measurement:measuredHeight", mMeasuredHeight);
22765
22766        // drawing
22767        stream.addProperty("drawing:elevation", getElevation());
22768        stream.addProperty("drawing:translationX", getTranslationX());
22769        stream.addProperty("drawing:translationY", getTranslationY());
22770        stream.addProperty("drawing:translationZ", getTranslationZ());
22771        stream.addProperty("drawing:rotation", getRotation());
22772        stream.addProperty("drawing:rotationX", getRotationX());
22773        stream.addProperty("drawing:rotationY", getRotationY());
22774        stream.addProperty("drawing:scaleX", getScaleX());
22775        stream.addProperty("drawing:scaleY", getScaleY());
22776        stream.addProperty("drawing:pivotX", getPivotX());
22777        stream.addProperty("drawing:pivotY", getPivotY());
22778        stream.addProperty("drawing:opaque", isOpaque());
22779        stream.addProperty("drawing:alpha", getAlpha());
22780        stream.addProperty("drawing:transitionAlpha", getTransitionAlpha());
22781        stream.addProperty("drawing:shadow", hasShadow());
22782        stream.addProperty("drawing:solidColor", getSolidColor());
22783        stream.addProperty("drawing:layerType", mLayerType);
22784        stream.addProperty("drawing:willNotDraw", willNotDraw());
22785        stream.addProperty("drawing:hardwareAccelerated", isHardwareAccelerated());
22786        stream.addProperty("drawing:willNotCacheDrawing", willNotCacheDrawing());
22787        stream.addProperty("drawing:drawingCacheEnabled", isDrawingCacheEnabled());
22788        stream.addProperty("drawing:overlappingRendering", hasOverlappingRendering());
22789
22790        // focus
22791        stream.addProperty("focus:hasFocus", hasFocus());
22792        stream.addProperty("focus:isFocused", isFocused());
22793        stream.addProperty("focus:isFocusable", isFocusable());
22794        stream.addProperty("focus:isFocusableInTouchMode", isFocusableInTouchMode());
22795
22796        stream.addProperty("misc:clickable", isClickable());
22797        stream.addProperty("misc:pressed", isPressed());
22798        stream.addProperty("misc:selected", isSelected());
22799        stream.addProperty("misc:touchMode", isInTouchMode());
22800        stream.addProperty("misc:hovered", isHovered());
22801        stream.addProperty("misc:activated", isActivated());
22802
22803        stream.addProperty("misc:visibility", getVisibility());
22804        stream.addProperty("misc:fitsSystemWindows", getFitsSystemWindows());
22805        stream.addProperty("misc:filterTouchesWhenObscured", getFilterTouchesWhenObscured());
22806
22807        stream.addProperty("misc:enabled", isEnabled());
22808        stream.addProperty("misc:soundEffectsEnabled", isSoundEffectsEnabled());
22809        stream.addProperty("misc:hapticFeedbackEnabled", isHapticFeedbackEnabled());
22810
22811        // theme attributes
22812        Resources.Theme theme = getContext().getTheme();
22813        if (theme != null) {
22814            stream.addPropertyKey("theme");
22815            theme.encode(stream);
22816        }
22817
22818        // view attribute information
22819        int n = mAttributes != null ? mAttributes.length : 0;
22820        stream.addProperty("meta:__attrCount__", n/2);
22821        for (int i = 0; i < n; i += 2) {
22822            stream.addProperty("meta:__attr__" + mAttributes[i], mAttributes[i+1]);
22823        }
22824
22825        stream.addProperty("misc:scrollBarStyle", getScrollBarStyle());
22826
22827        // text
22828        stream.addProperty("text:textDirection", getTextDirection());
22829        stream.addProperty("text:textAlignment", getTextAlignment());
22830
22831        // accessibility
22832        CharSequence contentDescription = getContentDescription();
22833        stream.addProperty("accessibility:contentDescription",
22834                contentDescription == null ? "" : contentDescription.toString());
22835        stream.addProperty("accessibility:labelFor", getLabelFor());
22836        stream.addProperty("accessibility:importantForAccessibility", getImportantForAccessibility());
22837    }
22838}
22839