View.java revision 794469916c4da8236b91cf5f8813ab4a1682cf86
1/*
2 * Copyright (C) 2006 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 *      http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17package android.view;
18
19import android.animation.AnimatorInflater;
20import android.animation.StateListAnimator;
21import android.annotation.CallSuper;
22import android.annotation.ColorInt;
23import android.annotation.DrawableRes;
24import android.annotation.FloatRange;
25import android.annotation.IdRes;
26import android.annotation.IntDef;
27import android.annotation.LayoutRes;
28import android.annotation.NonNull;
29import android.annotation.Nullable;
30import android.annotation.Size;
31import android.annotation.UiThread;
32import android.content.ClipData;
33import android.content.Context;
34import android.content.ContextWrapper;
35import android.content.Intent;
36import android.content.res.ColorStateList;
37import android.content.res.Configuration;
38import android.content.res.Resources;
39import android.content.res.TypedArray;
40import android.graphics.Bitmap;
41import android.graphics.Canvas;
42import android.graphics.Insets;
43import android.graphics.Interpolator;
44import android.graphics.LinearGradient;
45import android.graphics.Matrix;
46import android.graphics.Outline;
47import android.graphics.Paint;
48import android.graphics.PixelFormat;
49import android.graphics.Point;
50import android.graphics.PorterDuff;
51import android.graphics.PorterDuffXfermode;
52import android.graphics.Rect;
53import android.graphics.RectF;
54import android.graphics.Region;
55import android.graphics.Shader;
56import android.graphics.drawable.ColorDrawable;
57import android.graphics.drawable.Drawable;
58import android.hardware.display.DisplayManagerGlobal;
59import android.os.Build.VERSION_CODES;
60import android.os.Bundle;
61import android.os.Handler;
62import android.os.IBinder;
63import android.os.Parcel;
64import android.os.Parcelable;
65import android.os.RemoteException;
66import android.os.SystemClock;
67import android.os.SystemProperties;
68import android.os.Trace;
69import android.text.TextUtils;
70import android.util.AttributeSet;
71import android.util.FloatProperty;
72import android.util.LayoutDirection;
73import android.util.Log;
74import android.util.LongSparseLongArray;
75import android.util.Pools.SynchronizedPool;
76import android.util.Property;
77import android.util.SparseArray;
78import android.util.StateSet;
79import android.util.SuperNotCalledException;
80import android.util.TypedValue;
81import android.view.ContextMenu.ContextMenuInfo;
82import android.view.AccessibilityIterators.TextSegmentIterator;
83import android.view.AccessibilityIterators.CharacterTextSegmentIterator;
84import android.view.AccessibilityIterators.WordTextSegmentIterator;
85import android.view.AccessibilityIterators.ParagraphTextSegmentIterator;
86import android.view.accessibility.AccessibilityEvent;
87import android.view.accessibility.AccessibilityEventSource;
88import android.view.accessibility.AccessibilityManager;
89import android.view.accessibility.AccessibilityNodeInfo;
90import android.view.accessibility.AccessibilityNodeInfo.AccessibilityAction;
91import android.view.accessibility.AccessibilityNodeProvider;
92import android.view.animation.Animation;
93import android.view.animation.AnimationUtils;
94import android.view.animation.Transformation;
95import android.view.inputmethod.EditorInfo;
96import android.view.inputmethod.InputConnection;
97import android.view.inputmethod.InputMethodManager;
98import android.widget.Checkable;
99import android.widget.FrameLayout;
100import android.widget.ScrollBarDrawable;
101
102import static android.os.Build.VERSION_CODES.*;
103import static java.lang.Math.max;
104
105import com.android.internal.R;
106import com.android.internal.util.Predicate;
107import com.android.internal.view.menu.MenuBuilder;
108import com.google.android.collect.Lists;
109import com.google.android.collect.Maps;
110
111import java.lang.annotation.Retention;
112import java.lang.annotation.RetentionPolicy;
113import java.lang.ref.WeakReference;
114import java.lang.reflect.Field;
115import java.lang.reflect.InvocationTargetException;
116import java.lang.reflect.Method;
117import java.lang.reflect.Modifier;
118import java.util.ArrayList;
119import java.util.Arrays;
120import java.util.Collections;
121import java.util.HashMap;
122import java.util.List;
123import java.util.Locale;
124import java.util.Map;
125import java.util.concurrent.CopyOnWriteArrayList;
126import java.util.concurrent.atomic.AtomicInteger;
127
128/**
129 * <p>
130 * This class represents the basic building block for user interface components. A View
131 * occupies a rectangular area on the screen and is responsible for drawing and
132 * event handling. View is the base class for <em>widgets</em>, which are
133 * used to create interactive UI components (buttons, text fields, etc.). The
134 * {@link android.view.ViewGroup} subclass is the base class for <em>layouts</em>, which
135 * are invisible containers that hold other Views (or other ViewGroups) and define
136 * their layout properties.
137 * </p>
138 *
139 * <div class="special reference">
140 * <h3>Developer Guides</h3>
141 * <p>For information about using this class to develop your application's user interface,
142 * read the <a href="{@docRoot}guide/topics/ui/index.html">User Interface</a> developer guide.
143 * </div>
144 *
145 * <a name="Using"></a>
146 * <h3>Using Views</h3>
147 * <p>
148 * All of the views in a window are arranged in a single tree. You can add views
149 * either from code or by specifying a tree of views in one or more XML layout
150 * files. There are many specialized subclasses of views that act as controls or
151 * are capable of displaying text, images, or other content.
152 * </p>
153 * <p>
154 * Once you have created a tree of views, there are typically a few types of
155 * common operations you may wish to perform:
156 * <ul>
157 * <li><strong>Set properties:</strong> for example setting the text of a
158 * {@link android.widget.TextView}. The available properties and the methods
159 * that set them will vary among the different subclasses of views. Note that
160 * properties that are known at build time can be set in the XML layout
161 * files.</li>
162 * <li><strong>Set focus:</strong> The framework will handled moving focus in
163 * response to user input. To force focus to a specific view, call
164 * {@link #requestFocus}.</li>
165 * <li><strong>Set up listeners:</strong> Views allow clients to set listeners
166 * that will be notified when something interesting happens to the view. For
167 * example, all views will let you set a listener to be notified when the view
168 * gains or loses focus. You can register such a listener using
169 * {@link #setOnFocusChangeListener(android.view.View.OnFocusChangeListener)}.
170 * Other view subclasses offer more specialized listeners. For example, a Button
171 * exposes a listener to notify clients when the button is clicked.</li>
172 * <li><strong>Set visibility:</strong> You can hide or show views using
173 * {@link #setVisibility(int)}.</li>
174 * </ul>
175 * </p>
176 * <p><em>
177 * Note: The Android framework is responsible for measuring, laying out and
178 * drawing views. You should not call methods that perform these actions on
179 * views yourself unless you are actually implementing a
180 * {@link android.view.ViewGroup}.
181 * </em></p>
182 *
183 * <a name="Lifecycle"></a>
184 * <h3>Implementing a Custom View</h3>
185 *
186 * <p>
187 * To implement a custom view, you will usually begin by providing overrides for
188 * some of the standard methods that the framework calls on all views. You do
189 * not need to override all of these methods. In fact, you can start by just
190 * overriding {@link #onDraw(android.graphics.Canvas)}.
191 * <table border="2" width="85%" align="center" cellpadding="5">
192 *     <thead>
193 *         <tr><th>Category</th> <th>Methods</th> <th>Description</th></tr>
194 *     </thead>
195 *
196 *     <tbody>
197 *     <tr>
198 *         <td rowspan="2">Creation</td>
199 *         <td>Constructors</td>
200 *         <td>There is a form of the constructor that are called when the view
201 *         is created from code and a form that is called when the view is
202 *         inflated from a layout file. The second form should parse and apply
203 *         any attributes defined in the layout file.
204 *         </td>
205 *     </tr>
206 *     <tr>
207 *         <td><code>{@link #onFinishInflate()}</code></td>
208 *         <td>Called after a view and all of its children has been inflated
209 *         from XML.</td>
210 *     </tr>
211 *
212 *     <tr>
213 *         <td rowspan="3">Layout</td>
214 *         <td><code>{@link #onMeasure(int, int)}</code></td>
215 *         <td>Called to determine the size requirements for this view and all
216 *         of its children.
217 *         </td>
218 *     </tr>
219 *     <tr>
220 *         <td><code>{@link #onLayout(boolean, int, int, int, int)}</code></td>
221 *         <td>Called when this view should assign a size and position to all
222 *         of its children.
223 *         </td>
224 *     </tr>
225 *     <tr>
226 *         <td><code>{@link #onSizeChanged(int, int, int, int)}</code></td>
227 *         <td>Called when the size of this view has changed.
228 *         </td>
229 *     </tr>
230 *
231 *     <tr>
232 *         <td>Drawing</td>
233 *         <td><code>{@link #onDraw(android.graphics.Canvas)}</code></td>
234 *         <td>Called when the view should render its content.
235 *         </td>
236 *     </tr>
237 *
238 *     <tr>
239 *         <td rowspan="4">Event processing</td>
240 *         <td><code>{@link #onKeyDown(int, KeyEvent)}</code></td>
241 *         <td>Called when a new hardware key event occurs.
242 *         </td>
243 *     </tr>
244 *     <tr>
245 *         <td><code>{@link #onKeyUp(int, KeyEvent)}</code></td>
246 *         <td>Called when a hardware key up event occurs.
247 *         </td>
248 *     </tr>
249 *     <tr>
250 *         <td><code>{@link #onTrackballEvent(MotionEvent)}</code></td>
251 *         <td>Called when a trackball motion event occurs.
252 *         </td>
253 *     </tr>
254 *     <tr>
255 *         <td><code>{@link #onTouchEvent(MotionEvent)}</code></td>
256 *         <td>Called when a touch screen motion event occurs.
257 *         </td>
258 *     </tr>
259 *
260 *     <tr>
261 *         <td rowspan="2">Focus</td>
262 *         <td><code>{@link #onFocusChanged(boolean, int, android.graphics.Rect)}</code></td>
263 *         <td>Called when the view gains or loses focus.
264 *         </td>
265 *     </tr>
266 *
267 *     <tr>
268 *         <td><code>{@link #onWindowFocusChanged(boolean)}</code></td>
269 *         <td>Called when the window containing the view gains or loses focus.
270 *         </td>
271 *     </tr>
272 *
273 *     <tr>
274 *         <td rowspan="3">Attaching</td>
275 *         <td><code>{@link #onAttachedToWindow()}</code></td>
276 *         <td>Called when the view is attached to a window.
277 *         </td>
278 *     </tr>
279 *
280 *     <tr>
281 *         <td><code>{@link #onDetachedFromWindow}</code></td>
282 *         <td>Called when the view is detached from its window.
283 *         </td>
284 *     </tr>
285 *
286 *     <tr>
287 *         <td><code>{@link #onWindowVisibilityChanged(int)}</code></td>
288 *         <td>Called when the visibility of the window containing the view
289 *         has changed.
290 *         </td>
291 *     </tr>
292 *     </tbody>
293 *
294 * </table>
295 * </p>
296 *
297 * <a name="IDs"></a>
298 * <h3>IDs</h3>
299 * Views may have an integer id associated with them. These ids are typically
300 * assigned in the layout XML files, and are used to find specific views within
301 * the view tree. A common pattern is to:
302 * <ul>
303 * <li>Define a Button in the layout file and assign it a unique ID.
304 * <pre>
305 * &lt;Button
306 *     android:id="@+id/my_button"
307 *     android:layout_width="wrap_content"
308 *     android:layout_height="wrap_content"
309 *     android:text="@string/my_button_text"/&gt;
310 * </pre></li>
311 * <li>From the onCreate method of an Activity, find the Button
312 * <pre class="prettyprint">
313 *      Button myButton = (Button) findViewById(R.id.my_button);
314 * </pre></li>
315 * </ul>
316 * <p>
317 * View IDs need not be unique throughout the tree, but it is good practice to
318 * ensure that they are at least unique within the part of the tree you are
319 * searching.
320 * </p>
321 *
322 * <a name="Position"></a>
323 * <h3>Position</h3>
324 * <p>
325 * The geometry of a view is that of a rectangle. A view has a location,
326 * expressed as a pair of <em>left</em> and <em>top</em> coordinates, and
327 * two dimensions, expressed as a width and a height. The unit for location
328 * and dimensions is the pixel.
329 * </p>
330 *
331 * <p>
332 * It is possible to retrieve the location of a view by invoking the methods
333 * {@link #getLeft()} and {@link #getTop()}. The former returns the left, or X,
334 * coordinate of the rectangle representing the view. The latter returns the
335 * top, or Y, coordinate of the rectangle representing the view. These methods
336 * both return the location of the view relative to its parent. For instance,
337 * when getLeft() returns 20, that means the view is located 20 pixels to the
338 * right of the left edge of its direct parent.
339 * </p>
340 *
341 * <p>
342 * In addition, several convenience methods are offered to avoid unnecessary
343 * computations, namely {@link #getRight()} and {@link #getBottom()}.
344 * These methods return the coordinates of the right and bottom edges of the
345 * rectangle representing the view. For instance, calling {@link #getRight()}
346 * is similar to the following computation: <code>getLeft() + getWidth()</code>
347 * (see <a href="#SizePaddingMargins">Size</a> for more information about the width.)
348 * </p>
349 *
350 * <a name="SizePaddingMargins"></a>
351 * <h3>Size, padding and margins</h3>
352 * <p>
353 * The size of a view is expressed with a width and a height. A view actually
354 * possess two pairs of width and height values.
355 * </p>
356 *
357 * <p>
358 * The first pair is known as <em>measured width</em> and
359 * <em>measured height</em>. These dimensions define how big a view wants to be
360 * within its parent (see <a href="#Layout">Layout</a> for more details.) The
361 * measured dimensions can be obtained by calling {@link #getMeasuredWidth()}
362 * and {@link #getMeasuredHeight()}.
363 * </p>
364 *
365 * <p>
366 * The second pair is simply known as <em>width</em> and <em>height</em>, or
367 * sometimes <em>drawing width</em> and <em>drawing height</em>. These
368 * dimensions define the actual size of the view on screen, at drawing time and
369 * after layout. These values may, but do not have to, be different from the
370 * measured width and height. The width and height can be obtained by calling
371 * {@link #getWidth()} and {@link #getHeight()}.
372 * </p>
373 *
374 * <p>
375 * To measure its dimensions, a view takes into account its padding. The padding
376 * is expressed in pixels for the left, top, right and bottom parts of the view.
377 * Padding can be used to offset the content of the view by a specific amount of
378 * pixels. For instance, a left padding of 2 will push the view's content by
379 * 2 pixels to the right of the left edge. Padding can be set using the
380 * {@link #setPadding(int, int, int, int)} or {@link #setPaddingRelative(int, int, int, int)}
381 * method and queried by calling {@link #getPaddingLeft()}, {@link #getPaddingTop()},
382 * {@link #getPaddingRight()}, {@link #getPaddingBottom()}, {@link #getPaddingStart()},
383 * {@link #getPaddingEnd()}.
384 * </p>
385 *
386 * <p>
387 * Even though a view can define a padding, it does not provide any support for
388 * margins. However, view groups provide such a support. Refer to
389 * {@link android.view.ViewGroup} and
390 * {@link android.view.ViewGroup.MarginLayoutParams} for further information.
391 * </p>
392 *
393 * <a name="Layout"></a>
394 * <h3>Layout</h3>
395 * <p>
396 * Layout is a two pass process: a measure pass and a layout pass. The measuring
397 * pass is implemented in {@link #measure(int, int)} and is a top-down traversal
398 * of the view tree. Each view pushes dimension specifications down the tree
399 * during the recursion. At the end of the measure pass, every view has stored
400 * its measurements. The second pass happens in
401 * {@link #layout(int,int,int,int)} and is also top-down. During
402 * this pass each parent is responsible for positioning all of its children
403 * using the sizes computed in the measure pass.
404 * </p>
405 *
406 * <p>
407 * When a view's measure() method returns, its {@link #getMeasuredWidth()} and
408 * {@link #getMeasuredHeight()} values must be set, along with those for all of
409 * that view's descendants. A view's measured width and measured height values
410 * must respect the constraints imposed by the view's parents. This guarantees
411 * that at the end of the measure pass, all parents accept all of their
412 * children's measurements. A parent view may call measure() more than once on
413 * its children. For example, the parent may measure each child once with
414 * unspecified dimensions to find out how big they want to be, then call
415 * measure() on them again with actual numbers if the sum of all the children's
416 * unconstrained sizes is too big or too small.
417 * </p>
418 *
419 * <p>
420 * The measure pass uses two classes to communicate dimensions. The
421 * {@link MeasureSpec} class is used by views to tell their parents how they
422 * want to be measured and positioned. The base LayoutParams class just
423 * describes how big the view wants to be for both width and height. For each
424 * dimension, it can specify one of:
425 * <ul>
426 * <li> an exact number
427 * <li>MATCH_PARENT, which means the view wants to be as big as its parent
428 * (minus padding)
429 * <li> WRAP_CONTENT, which means that the view wants to be just big enough to
430 * enclose its content (plus padding).
431 * </ul>
432 * There are subclasses of LayoutParams for different subclasses of ViewGroup.
433 * For example, AbsoluteLayout has its own subclass of LayoutParams which adds
434 * an X and Y value.
435 * </p>
436 *
437 * <p>
438 * MeasureSpecs are used to push requirements down the tree from parent to
439 * child. A MeasureSpec can be in one of three modes:
440 * <ul>
441 * <li>UNSPECIFIED: This is used by a parent to determine the desired dimension
442 * of a child view. For example, a LinearLayout may call measure() on its child
443 * with the height set to UNSPECIFIED and a width of EXACTLY 240 to find out how
444 * tall the child view wants to be given a width of 240 pixels.
445 * <li>EXACTLY: This is used by the parent to impose an exact size on the
446 * child. The child must use this size, and guarantee that all of its
447 * descendants will fit within this size.
448 * <li>AT_MOST: This is used by the parent to impose a maximum size on the
449 * child. The child must guarantee that it and all of its descendants will fit
450 * within this size.
451 * </ul>
452 * </p>
453 *
454 * <p>
455 * To initiate a layout, call {@link #requestLayout}. This method is typically
456 * called by a view on itself when it believes that is can no longer fit within
457 * its current bounds.
458 * </p>
459 *
460 * <a name="Drawing"></a>
461 * <h3>Drawing</h3>
462 * <p>
463 * Drawing is handled by walking the tree and recording the drawing commands of
464 * any View that needs to update. After this, the drawing commands of the
465 * entire tree are issued to screen, clipped to the newly damaged area.
466 * </p>
467 *
468 * <p>
469 * The tree is largely recorded and drawn in order, with parents drawn before
470 * (i.e., behind) their children, with siblings drawn in the order they appear
471 * in the tree. If you set a background drawable for a View, then the View will
472 * draw it before calling back to its <code>onDraw()</code> method. The child
473 * drawing order can be overridden with
474 * {@link ViewGroup#setChildrenDrawingOrderEnabled(boolean) custom child drawing order}
475 * in a ViewGroup, and with {@link #setZ(float)} custom Z values} set on Views.
476 * </p>
477 *
478 * <p>
479 * To force a view to draw, call {@link #invalidate()}.
480 * </p>
481 *
482 * <a name="EventHandlingThreading"></a>
483 * <h3>Event Handling and Threading</h3>
484 * <p>
485 * The basic cycle of a view is as follows:
486 * <ol>
487 * <li>An event comes in and is dispatched to the appropriate view. The view
488 * handles the event and notifies any listeners.</li>
489 * <li>If in the course of processing the event, the view's bounds may need
490 * to be changed, the view will call {@link #requestLayout()}.</li>
491 * <li>Similarly, if in the course of processing the event the view's appearance
492 * may need to be changed, the view will call {@link #invalidate()}.</li>
493 * <li>If either {@link #requestLayout()} or {@link #invalidate()} were called,
494 * the framework will take care of measuring, laying out, and drawing the tree
495 * as appropriate.</li>
496 * </ol>
497 * </p>
498 *
499 * <p><em>Note: The entire view tree is single threaded. You must always be on
500 * the UI thread when calling any method on any view.</em>
501 * If you are doing work on other threads and want to update the state of a view
502 * from that thread, you should use a {@link Handler}.
503 * </p>
504 *
505 * <a name="FocusHandling"></a>
506 * <h3>Focus Handling</h3>
507 * <p>
508 * The framework will handle routine focus movement in response to user input.
509 * This includes changing the focus as views are removed or hidden, or as new
510 * views become available. Views indicate their willingness to take focus
511 * through the {@link #isFocusable} method. To change whether a view can take
512 * focus, call {@link #setFocusable(boolean)}.  When in touch mode (see notes below)
513 * views indicate whether they still would like focus via {@link #isFocusableInTouchMode}
514 * and can change this via {@link #setFocusableInTouchMode(boolean)}.
515 * </p>
516 * <p>
517 * Focus movement is based on an algorithm which finds the nearest neighbor in a
518 * given direction. In rare cases, the default algorithm may not match the
519 * intended behavior of the developer. In these situations, you can provide
520 * explicit overrides by using these XML attributes in the layout file:
521 * <pre>
522 * nextFocusDown
523 * nextFocusLeft
524 * nextFocusRight
525 * nextFocusUp
526 * </pre>
527 * </p>
528 *
529 *
530 * <p>
531 * To get a particular view to take focus, call {@link #requestFocus()}.
532 * </p>
533 *
534 * <a name="TouchMode"></a>
535 * <h3>Touch Mode</h3>
536 * <p>
537 * When a user is navigating a user interface via directional keys such as a D-pad, it is
538 * necessary to give focus to actionable items such as buttons so the user can see
539 * what will take input.  If the device has touch capabilities, however, and the user
540 * begins interacting with the interface by touching it, it is no longer necessary to
541 * always highlight, or give focus to, a particular view.  This motivates a mode
542 * for interaction named 'touch mode'.
543 * </p>
544 * <p>
545 * For a touch capable device, once the user touches the screen, the device
546 * will enter touch mode.  From this point onward, only views for which
547 * {@link #isFocusableInTouchMode} is true will be focusable, such as text editing widgets.
548 * Other views that are touchable, like buttons, will not take focus when touched; they will
549 * only fire the on click listeners.
550 * </p>
551 * <p>
552 * Any time a user hits a directional key, such as a D-pad direction, the view device will
553 * exit touch mode, and find a view to take focus, so that the user may resume interacting
554 * with the user interface without touching the screen again.
555 * </p>
556 * <p>
557 * The touch mode state is maintained across {@link android.app.Activity}s.  Call
558 * {@link #isInTouchMode} to see whether the device is currently in touch mode.
559 * </p>
560 *
561 * <a name="Scrolling"></a>
562 * <h3>Scrolling</h3>
563 * <p>
564 * The framework provides basic support for views that wish to internally
565 * scroll their content. This includes keeping track of the X and Y scroll
566 * offset as well as mechanisms for drawing scrollbars. See
567 * {@link #scrollBy(int, int)}, {@link #scrollTo(int, int)}, and
568 * {@link #awakenScrollBars()} for more details.
569 * </p>
570 *
571 * <a name="Tags"></a>
572 * <h3>Tags</h3>
573 * <p>
574 * Unlike IDs, tags are not used to identify views. Tags are essentially an
575 * extra piece of information that can be associated with a view. They are most
576 * often used as a convenience to store data related to views in the views
577 * themselves rather than by putting them in a separate structure.
578 * </p>
579 * <p>
580 * Tags may be specified with character sequence values in layout XML as either
581 * a single tag using the {@link android.R.styleable#View_tag android:tag}
582 * attribute or multiple tags using the {@code &lt;tag&gt;} child element:
583 * <pre>
584 *     &ltView ...
585 *           android:tag="@string/mytag_value" /&gt;
586 *     &ltView ...&gt;
587 *         &lttag android:id="@+id/mytag"
588 *              android:value="@string/mytag_value" /&gt;
589 *     &lt/View>
590 * </pre>
591 * </p>
592 * <p>
593 * Tags may also be specified with arbitrary objects from code using
594 * {@link #setTag(Object)} or {@link #setTag(int, Object)}.
595 * </p>
596 *
597 * <a name="Themes"></a>
598 * <h3>Themes</h3>
599 * <p>
600 * By default, Views are created using the theme of the Context object supplied
601 * to their constructor; however, a different theme may be specified by using
602 * the {@link android.R.styleable#View_theme android:theme} attribute in layout
603 * XML or by passing a {@link ContextThemeWrapper} to the constructor from
604 * code.
605 * </p>
606 * <p>
607 * When the {@link android.R.styleable#View_theme android:theme} attribute is
608 * used in XML, the specified theme is applied on top of the inflation
609 * context's theme (see {@link LayoutInflater}) and used for the view itself as
610 * well as any child elements.
611 * </p>
612 * <p>
613 * In the following example, both views will be created using the Material dark
614 * color scheme; however, because an overlay theme is used which only defines a
615 * subset of attributes, the value of
616 * {@link android.R.styleable#Theme_colorAccent android:colorAccent} defined on
617 * the inflation context's theme (e.g. the Activity theme) will be preserved.
618 * <pre>
619 *     &ltLinearLayout
620 *             ...
621 *             android:theme="@android:theme/ThemeOverlay.Material.Dark"&gt;
622 *         &ltView ...&gt;
623 *     &lt/LinearLayout&gt;
624 * </pre>
625 * </p>
626 *
627 * <a name="Properties"></a>
628 * <h3>Properties</h3>
629 * <p>
630 * The View class exposes an {@link #ALPHA} property, as well as several transform-related
631 * properties, such as {@link #TRANSLATION_X} and {@link #TRANSLATION_Y}. These properties are
632 * available both in the {@link Property} form as well as in similarly-named setter/getter
633 * methods (such as {@link #setAlpha(float)} for {@link #ALPHA}). These properties can
634 * be used to set persistent state associated with these rendering-related properties on the view.
635 * The properties and methods can also be used in conjunction with
636 * {@link android.animation.Animator Animator}-based animations, described more in the
637 * <a href="#Animation">Animation</a> section.
638 * </p>
639 *
640 * <a name="Animation"></a>
641 * <h3>Animation</h3>
642 * <p>
643 * Starting with Android 3.0, the preferred way of animating views is to use the
644 * {@link android.animation} package APIs. These {@link android.animation.Animator Animator}-based
645 * classes change actual properties of the View object, such as {@link #setAlpha(float) alpha} and
646 * {@link #setTranslationX(float) translationX}. This behavior is contrasted to that of the pre-3.0
647 * {@link android.view.animation.Animation Animation}-based classes, which instead animate only
648 * how the view is drawn on the display. In particular, the {@link ViewPropertyAnimator} class
649 * makes animating these View properties particularly easy and efficient.
650 * </p>
651 * <p>
652 * Alternatively, you can use the pre-3.0 animation classes to animate how Views are rendered.
653 * You can attach an {@link Animation} object to a view using
654 * {@link #setAnimation(Animation)} or
655 * {@link #startAnimation(Animation)}. The animation can alter the scale,
656 * rotation, translation and alpha of a view over time. If the animation is
657 * attached to a view that has children, the animation will affect the entire
658 * subtree rooted by that node. When an animation is started, the framework will
659 * take care of redrawing the appropriate views until the animation completes.
660 * </p>
661 *
662 * <a name="Security"></a>
663 * <h3>Security</h3>
664 * <p>
665 * Sometimes it is essential that an application be able to verify that an action
666 * is being performed with the full knowledge and consent of the user, such as
667 * granting a permission request, making a purchase or clicking on an advertisement.
668 * Unfortunately, a malicious application could try to spoof the user into
669 * performing these actions, unaware, by concealing the intended purpose of the view.
670 * As a remedy, the framework offers a touch filtering mechanism that can be used to
671 * improve the security of views that provide access to sensitive functionality.
672 * </p><p>
673 * To enable touch filtering, call {@link #setFilterTouchesWhenObscured(boolean)} or set the
674 * android:filterTouchesWhenObscured layout attribute to true.  When enabled, the framework
675 * will discard touches that are received whenever the view's window is obscured by
676 * another visible window.  As a result, the view will not receive touches whenever a
677 * toast, dialog or other window appears above the view's window.
678 * </p><p>
679 * For more fine-grained control over security, consider overriding the
680 * {@link #onFilterTouchEventForSecurity(MotionEvent)} method to implement your own
681 * security policy. See also {@link MotionEvent#FLAG_WINDOW_IS_OBSCURED}.
682 * </p>
683 *
684 * @attr ref android.R.styleable#View_alpha
685 * @attr ref android.R.styleable#View_background
686 * @attr ref android.R.styleable#View_clickable
687 * @attr ref android.R.styleable#View_contentDescription
688 * @attr ref android.R.styleable#View_drawingCacheQuality
689 * @attr ref android.R.styleable#View_duplicateParentState
690 * @attr ref android.R.styleable#View_id
691 * @attr ref android.R.styleable#View_requiresFadingEdge
692 * @attr ref android.R.styleable#View_fadeScrollbars
693 * @attr ref android.R.styleable#View_fadingEdgeLength
694 * @attr ref android.R.styleable#View_filterTouchesWhenObscured
695 * @attr ref android.R.styleable#View_fitsSystemWindows
696 * @attr ref android.R.styleable#View_isScrollContainer
697 * @attr ref android.R.styleable#View_focusable
698 * @attr ref android.R.styleable#View_focusableInTouchMode
699 * @attr ref android.R.styleable#View_hapticFeedbackEnabled
700 * @attr ref android.R.styleable#View_keepScreenOn
701 * @attr ref android.R.styleable#View_layerType
702 * @attr ref android.R.styleable#View_layoutDirection
703 * @attr ref android.R.styleable#View_longClickable
704 * @attr ref android.R.styleable#View_minHeight
705 * @attr ref android.R.styleable#View_minWidth
706 * @attr ref android.R.styleable#View_nextFocusDown
707 * @attr ref android.R.styleable#View_nextFocusLeft
708 * @attr ref android.R.styleable#View_nextFocusRight
709 * @attr ref android.R.styleable#View_nextFocusUp
710 * @attr ref android.R.styleable#View_onClick
711 * @attr ref android.R.styleable#View_padding
712 * @attr ref android.R.styleable#View_paddingBottom
713 * @attr ref android.R.styleable#View_paddingLeft
714 * @attr ref android.R.styleable#View_paddingRight
715 * @attr ref android.R.styleable#View_paddingTop
716 * @attr ref android.R.styleable#View_paddingStart
717 * @attr ref android.R.styleable#View_paddingEnd
718 * @attr ref android.R.styleable#View_saveEnabled
719 * @attr ref android.R.styleable#View_rotation
720 * @attr ref android.R.styleable#View_rotationX
721 * @attr ref android.R.styleable#View_rotationY
722 * @attr ref android.R.styleable#View_scaleX
723 * @attr ref android.R.styleable#View_scaleY
724 * @attr ref android.R.styleable#View_scrollX
725 * @attr ref android.R.styleable#View_scrollY
726 * @attr ref android.R.styleable#View_scrollbarSize
727 * @attr ref android.R.styleable#View_scrollbarStyle
728 * @attr ref android.R.styleable#View_scrollbars
729 * @attr ref android.R.styleable#View_scrollbarDefaultDelayBeforeFade
730 * @attr ref android.R.styleable#View_scrollbarFadeDuration
731 * @attr ref android.R.styleable#View_scrollbarTrackHorizontal
732 * @attr ref android.R.styleable#View_scrollbarThumbHorizontal
733 * @attr ref android.R.styleable#View_scrollbarThumbVertical
734 * @attr ref android.R.styleable#View_scrollbarTrackVertical
735 * @attr ref android.R.styleable#View_scrollbarAlwaysDrawHorizontalTrack
736 * @attr ref android.R.styleable#View_scrollbarAlwaysDrawVerticalTrack
737 * @attr ref android.R.styleable#View_stateListAnimator
738 * @attr ref android.R.styleable#View_transitionName
739 * @attr ref android.R.styleable#View_soundEffectsEnabled
740 * @attr ref android.R.styleable#View_tag
741 * @attr ref android.R.styleable#View_textAlignment
742 * @attr ref android.R.styleable#View_textDirection
743 * @attr ref android.R.styleable#View_transformPivotX
744 * @attr ref android.R.styleable#View_transformPivotY
745 * @attr ref android.R.styleable#View_translationX
746 * @attr ref android.R.styleable#View_translationY
747 * @attr ref android.R.styleable#View_translationZ
748 * @attr ref android.R.styleable#View_visibility
749 * @attr ref android.R.styleable#View_theme
750 *
751 * @see android.view.ViewGroup
752 */
753@UiThread
754public class View implements Drawable.Callback, KeyEvent.Callback,
755        AccessibilityEventSource {
756    private static final boolean DBG = false;
757
758    /**
759     * The logging tag used by this class with android.util.Log.
760     */
761    protected static final String VIEW_LOG_TAG = "View";
762
763    /**
764     * When set to true, apps will draw debugging information about their layouts.
765     *
766     * @hide
767     */
768    public static final String DEBUG_LAYOUT_PROPERTY = "debug.layout";
769
770    /**
771     * When set to true, this view will save its attribute data.
772     *
773     * @hide
774     */
775    public static boolean mDebugViewAttributes = false;
776
777    /**
778     * Used to mark a View that has no ID.
779     */
780    public static final int NO_ID = -1;
781
782    /**
783     * Signals that compatibility booleans have been initialized according to
784     * target SDK versions.
785     */
786    private static boolean sCompatibilityDone = false;
787
788    /**
789     * Use the old (broken) way of building MeasureSpecs.
790     */
791    private static boolean sUseBrokenMakeMeasureSpec = false;
792
793    /**
794     * Always return a size of 0 for MeasureSpec values with a mode of UNSPECIFIED
795     */
796    static boolean sUseZeroUnspecifiedMeasureSpec = false;
797
798    /**
799     * Ignore any optimizations using the measure cache.
800     */
801    private static boolean sIgnoreMeasureCache = false;
802
803    /**
804     * Ignore an optimization that skips unnecessary EXACTLY layout passes.
805     */
806    private static boolean sAlwaysRemeasureExactly = false;
807
808    /**
809     * This view does not want keystrokes. Use with TAKES_FOCUS_MASK when
810     * calling setFlags.
811     */
812    private static final int NOT_FOCUSABLE = 0x00000000;
813
814    /**
815     * This view wants keystrokes. Use with TAKES_FOCUS_MASK when calling
816     * setFlags.
817     */
818    private static final int FOCUSABLE = 0x00000001;
819
820    /**
821     * Mask for use with setFlags indicating bits used for focus.
822     */
823    private static final int FOCUSABLE_MASK = 0x00000001;
824
825    /**
826     * This view will adjust its padding to fit sytem windows (e.g. status bar)
827     */
828    private static final int FITS_SYSTEM_WINDOWS = 0x00000002;
829
830    /** @hide */
831    @IntDef({VISIBLE, INVISIBLE, GONE})
832    @Retention(RetentionPolicy.SOURCE)
833    public @interface Visibility {}
834
835    /**
836     * This view is visible.
837     * Use with {@link #setVisibility} and <a href="#attr_android:visibility">{@code
838     * android:visibility}.
839     */
840    public static final int VISIBLE = 0x00000000;
841
842    /**
843     * This view is invisible, but it still takes up space for layout purposes.
844     * Use with {@link #setVisibility} and <a href="#attr_android:visibility">{@code
845     * android:visibility}.
846     */
847    public static final int INVISIBLE = 0x00000004;
848
849    /**
850     * This view is invisible, and it doesn't take any space for layout
851     * purposes. Use with {@link #setVisibility} and <a href="#attr_android:visibility">{@code
852     * android:visibility}.
853     */
854    public static final int GONE = 0x00000008;
855
856    /**
857     * Mask for use with setFlags indicating bits used for visibility.
858     * {@hide}
859     */
860    static final int VISIBILITY_MASK = 0x0000000C;
861
862    private static final int[] VISIBILITY_FLAGS = {VISIBLE, INVISIBLE, GONE};
863
864    /**
865     * This view is enabled. Interpretation varies by subclass.
866     * Use with ENABLED_MASK when calling setFlags.
867     * {@hide}
868     */
869    static final int ENABLED = 0x00000000;
870
871    /**
872     * This view is disabled. Interpretation varies by subclass.
873     * Use with ENABLED_MASK when calling setFlags.
874     * {@hide}
875     */
876    static final int DISABLED = 0x00000020;
877
878   /**
879    * Mask for use with setFlags indicating bits used for indicating whether
880    * this view is enabled
881    * {@hide}
882    */
883    static final int ENABLED_MASK = 0x00000020;
884
885    /**
886     * This view won't draw. {@link #onDraw(android.graphics.Canvas)} won't be
887     * called and further optimizations will be performed. It is okay to have
888     * this flag set and a background. Use with DRAW_MASK when calling setFlags.
889     * {@hide}
890     */
891    static final int WILL_NOT_DRAW = 0x00000080;
892
893    /**
894     * Mask for use with setFlags indicating bits used for indicating whether
895     * this view is will draw
896     * {@hide}
897     */
898    static final int DRAW_MASK = 0x00000080;
899
900    /**
901     * <p>This view doesn't show scrollbars.</p>
902     * {@hide}
903     */
904    static final int SCROLLBARS_NONE = 0x00000000;
905
906    /**
907     * <p>This view shows horizontal scrollbars.</p>
908     * {@hide}
909     */
910    static final int SCROLLBARS_HORIZONTAL = 0x00000100;
911
912    /**
913     * <p>This view shows vertical scrollbars.</p>
914     * {@hide}
915     */
916    static final int SCROLLBARS_VERTICAL = 0x00000200;
917
918    /**
919     * <p>Mask for use with setFlags indicating bits used for indicating which
920     * scrollbars are enabled.</p>
921     * {@hide}
922     */
923    static final int SCROLLBARS_MASK = 0x00000300;
924
925    /**
926     * Indicates that the view should filter touches when its window is obscured.
927     * Refer to the class comments for more information about this security feature.
928     * {@hide}
929     */
930    static final int FILTER_TOUCHES_WHEN_OBSCURED = 0x00000400;
931
932    /**
933     * Set for framework elements that use FITS_SYSTEM_WINDOWS, to indicate
934     * that they are optional and should be skipped if the window has
935     * requested system UI flags that ignore those insets for layout.
936     */
937    static final int OPTIONAL_FITS_SYSTEM_WINDOWS = 0x00000800;
938
939    /**
940     * <p>This view doesn't show fading edges.</p>
941     * {@hide}
942     */
943    static final int FADING_EDGE_NONE = 0x00000000;
944
945    /**
946     * <p>This view shows horizontal fading edges.</p>
947     * {@hide}
948     */
949    static final int FADING_EDGE_HORIZONTAL = 0x00001000;
950
951    /**
952     * <p>This view shows vertical fading edges.</p>
953     * {@hide}
954     */
955    static final int FADING_EDGE_VERTICAL = 0x00002000;
956
957    /**
958     * <p>Mask for use with setFlags indicating bits used for indicating which
959     * fading edges are enabled.</p>
960     * {@hide}
961     */
962    static final int FADING_EDGE_MASK = 0x00003000;
963
964    /**
965     * <p>Indicates this view can be clicked. When clickable, a View reacts
966     * to clicks by notifying the OnClickListener.<p>
967     * {@hide}
968     */
969    static final int CLICKABLE = 0x00004000;
970
971    /**
972     * <p>Indicates this view is caching its drawing into a bitmap.</p>
973     * {@hide}
974     */
975    static final int DRAWING_CACHE_ENABLED = 0x00008000;
976
977    /**
978     * <p>Indicates that no icicle should be saved for this view.<p>
979     * {@hide}
980     */
981    static final int SAVE_DISABLED = 0x000010000;
982
983    /**
984     * <p>Mask for use with setFlags indicating bits used for the saveEnabled
985     * property.</p>
986     * {@hide}
987     */
988    static final int SAVE_DISABLED_MASK = 0x000010000;
989
990    /**
991     * <p>Indicates that no drawing cache should ever be created for this view.<p>
992     * {@hide}
993     */
994    static final int WILL_NOT_CACHE_DRAWING = 0x000020000;
995
996    /**
997     * <p>Indicates this view can take / keep focus when int touch mode.</p>
998     * {@hide}
999     */
1000    static final int FOCUSABLE_IN_TOUCH_MODE = 0x00040000;
1001
1002    /** @hide */
1003    @Retention(RetentionPolicy.SOURCE)
1004    @IntDef({DRAWING_CACHE_QUALITY_LOW, DRAWING_CACHE_QUALITY_HIGH, DRAWING_CACHE_QUALITY_AUTO})
1005    public @interface DrawingCacheQuality {}
1006
1007    /**
1008     * <p>Enables low quality mode for the drawing cache.</p>
1009     */
1010    public static final int DRAWING_CACHE_QUALITY_LOW = 0x00080000;
1011
1012    /**
1013     * <p>Enables high quality mode for the drawing cache.</p>
1014     */
1015    public static final int DRAWING_CACHE_QUALITY_HIGH = 0x00100000;
1016
1017    /**
1018     * <p>Enables automatic quality mode for the drawing cache.</p>
1019     */
1020    public static final int DRAWING_CACHE_QUALITY_AUTO = 0x00000000;
1021
1022    private static final int[] DRAWING_CACHE_QUALITY_FLAGS = {
1023            DRAWING_CACHE_QUALITY_AUTO, DRAWING_CACHE_QUALITY_LOW, DRAWING_CACHE_QUALITY_HIGH
1024    };
1025
1026    /**
1027     * <p>Mask for use with setFlags indicating bits used for the cache
1028     * quality property.</p>
1029     * {@hide}
1030     */
1031    static final int DRAWING_CACHE_QUALITY_MASK = 0x00180000;
1032
1033    /**
1034     * <p>
1035     * Indicates this view can be long clicked. When long clickable, a View
1036     * reacts to long clicks by notifying the OnLongClickListener or showing a
1037     * context menu.
1038     * </p>
1039     * {@hide}
1040     */
1041    static final int LONG_CLICKABLE = 0x00200000;
1042
1043    /**
1044     * <p>Indicates that this view gets its drawable states from its direct parent
1045     * and ignores its original internal states.</p>
1046     *
1047     * @hide
1048     */
1049    static final int DUPLICATE_PARENT_STATE = 0x00400000;
1050
1051    /**
1052     * <p>
1053     * Indicates this view can be context clicked. When context clickable, a View reacts to a
1054     * context click (e.g. a primary stylus button press or right mouse click) by notifying the
1055     * OnContextClickListener.
1056     * </p>
1057     * {@hide}
1058     */
1059    static final int CONTEXT_CLICKABLE = 0x00800000;
1060
1061
1062    /** @hide */
1063    @IntDef({
1064        SCROLLBARS_INSIDE_OVERLAY,
1065        SCROLLBARS_INSIDE_INSET,
1066        SCROLLBARS_OUTSIDE_OVERLAY,
1067        SCROLLBARS_OUTSIDE_INSET
1068    })
1069    @Retention(RetentionPolicy.SOURCE)
1070    public @interface ScrollBarStyle {}
1071
1072    /**
1073     * The scrollbar style to display the scrollbars inside the content area,
1074     * without increasing the padding. The scrollbars will be overlaid with
1075     * translucency on the view's content.
1076     */
1077    public static final int SCROLLBARS_INSIDE_OVERLAY = 0;
1078
1079    /**
1080     * The scrollbar style to display the scrollbars inside the padded area,
1081     * increasing the padding of the view. The scrollbars will not overlap the
1082     * content area of the view.
1083     */
1084    public static final int SCROLLBARS_INSIDE_INSET = 0x01000000;
1085
1086    /**
1087     * The scrollbar style to display the scrollbars at the edge of the view,
1088     * without increasing the padding. The scrollbars will be overlaid with
1089     * translucency.
1090     */
1091    public static final int SCROLLBARS_OUTSIDE_OVERLAY = 0x02000000;
1092
1093    /**
1094     * The scrollbar style to display the scrollbars at the edge of the view,
1095     * increasing the padding of the view. The scrollbars will only overlap the
1096     * background, if any.
1097     */
1098    public static final int SCROLLBARS_OUTSIDE_INSET = 0x03000000;
1099
1100    /**
1101     * Mask to check if the scrollbar style is overlay or inset.
1102     * {@hide}
1103     */
1104    static final int SCROLLBARS_INSET_MASK = 0x01000000;
1105
1106    /**
1107     * Mask to check if the scrollbar style is inside or outside.
1108     * {@hide}
1109     */
1110    static final int SCROLLBARS_OUTSIDE_MASK = 0x02000000;
1111
1112    /**
1113     * Mask for scrollbar style.
1114     * {@hide}
1115     */
1116    static final int SCROLLBARS_STYLE_MASK = 0x03000000;
1117
1118    /**
1119     * View flag indicating that the screen should remain on while the
1120     * window containing this view is visible to the user.  This effectively
1121     * takes care of automatically setting the WindowManager's
1122     * {@link WindowManager.LayoutParams#FLAG_KEEP_SCREEN_ON}.
1123     */
1124    public static final int KEEP_SCREEN_ON = 0x04000000;
1125
1126    /**
1127     * View flag indicating whether this view should have sound effects enabled
1128     * for events such as clicking and touching.
1129     */
1130    public static final int SOUND_EFFECTS_ENABLED = 0x08000000;
1131
1132    /**
1133     * View flag indicating whether this view should have haptic feedback
1134     * enabled for events such as long presses.
1135     */
1136    public static final int HAPTIC_FEEDBACK_ENABLED = 0x10000000;
1137
1138    /**
1139     * <p>Indicates that the view hierarchy should stop saving state when
1140     * it reaches this view.  If state saving is initiated immediately at
1141     * the view, it will be allowed.
1142     * {@hide}
1143     */
1144    static final int PARENT_SAVE_DISABLED = 0x20000000;
1145
1146    /**
1147     * <p>Mask for use with setFlags indicating bits used for PARENT_SAVE_DISABLED.</p>
1148     * {@hide}
1149     */
1150    static final int PARENT_SAVE_DISABLED_MASK = 0x20000000;
1151
1152    /** @hide */
1153    @IntDef(flag = true,
1154            value = {
1155                FOCUSABLES_ALL,
1156                FOCUSABLES_TOUCH_MODE
1157            })
1158    @Retention(RetentionPolicy.SOURCE)
1159    public @interface FocusableMode {}
1160
1161    /**
1162     * View flag indicating whether {@link #addFocusables(ArrayList, int, int)}
1163     * should add all focusable Views regardless if they are focusable in touch mode.
1164     */
1165    public static final int FOCUSABLES_ALL = 0x00000000;
1166
1167    /**
1168     * View flag indicating whether {@link #addFocusables(ArrayList, int, int)}
1169     * should add only Views focusable in touch mode.
1170     */
1171    public static final int FOCUSABLES_TOUCH_MODE = 0x00000001;
1172
1173    /** @hide */
1174    @IntDef({
1175            FOCUS_BACKWARD,
1176            FOCUS_FORWARD,
1177            FOCUS_LEFT,
1178            FOCUS_UP,
1179            FOCUS_RIGHT,
1180            FOCUS_DOWN
1181    })
1182    @Retention(RetentionPolicy.SOURCE)
1183    public @interface FocusDirection {}
1184
1185    /** @hide */
1186    @IntDef({
1187            FOCUS_LEFT,
1188            FOCUS_UP,
1189            FOCUS_RIGHT,
1190            FOCUS_DOWN
1191    })
1192    @Retention(RetentionPolicy.SOURCE)
1193    public @interface FocusRealDirection {} // Like @FocusDirection, but without forward/backward
1194
1195    /**
1196     * Use with {@link #focusSearch(int)}. Move focus to the previous selectable
1197     * item.
1198     */
1199    public static final int FOCUS_BACKWARD = 0x00000001;
1200
1201    /**
1202     * Use with {@link #focusSearch(int)}. Move focus to the next selectable
1203     * item.
1204     */
1205    public static final int FOCUS_FORWARD = 0x00000002;
1206
1207    /**
1208     * Use with {@link #focusSearch(int)}. Move focus to the left.
1209     */
1210    public static final int FOCUS_LEFT = 0x00000011;
1211
1212    /**
1213     * Use with {@link #focusSearch(int)}. Move focus up.
1214     */
1215    public static final int FOCUS_UP = 0x00000021;
1216
1217    /**
1218     * Use with {@link #focusSearch(int)}. Move focus to the right.
1219     */
1220    public static final int FOCUS_RIGHT = 0x00000042;
1221
1222    /**
1223     * Use with {@link #focusSearch(int)}. Move focus down.
1224     */
1225    public static final int FOCUS_DOWN = 0x00000082;
1226
1227    /**
1228     * Bits of {@link #getMeasuredWidthAndState()} and
1229     * {@link #getMeasuredWidthAndState()} that provide the actual measured size.
1230     */
1231    public static final int MEASURED_SIZE_MASK = 0x00ffffff;
1232
1233    /**
1234     * Bits of {@link #getMeasuredWidthAndState()} and
1235     * {@link #getMeasuredWidthAndState()} that provide the additional state bits.
1236     */
1237    public static final int MEASURED_STATE_MASK = 0xff000000;
1238
1239    /**
1240     * Bit shift of {@link #MEASURED_STATE_MASK} to get to the height bits
1241     * for functions that combine both width and height into a single int,
1242     * such as {@link #getMeasuredState()} and the childState argument of
1243     * {@link #resolveSizeAndState(int, int, int)}.
1244     */
1245    public static final int MEASURED_HEIGHT_STATE_SHIFT = 16;
1246
1247    /**
1248     * Bit of {@link #getMeasuredWidthAndState()} and
1249     * {@link #getMeasuredWidthAndState()} that indicates the measured size
1250     * is smaller that the space the view would like to have.
1251     */
1252    public static final int MEASURED_STATE_TOO_SMALL = 0x01000000;
1253
1254    /**
1255     * Base View state sets
1256     */
1257    // Singles
1258    /**
1259     * Indicates the view has no states set. States are used with
1260     * {@link android.graphics.drawable.Drawable} to change the drawing of the
1261     * view depending on its state.
1262     *
1263     * @see android.graphics.drawable.Drawable
1264     * @see #getDrawableState()
1265     */
1266    protected static final int[] EMPTY_STATE_SET;
1267    /**
1268     * Indicates the view is enabled. States are used with
1269     * {@link android.graphics.drawable.Drawable} to change the drawing of the
1270     * view depending on its state.
1271     *
1272     * @see android.graphics.drawable.Drawable
1273     * @see #getDrawableState()
1274     */
1275    protected static final int[] ENABLED_STATE_SET;
1276    /**
1277     * Indicates the view is focused. States are used with
1278     * {@link android.graphics.drawable.Drawable} to change the drawing of the
1279     * view depending on its state.
1280     *
1281     * @see android.graphics.drawable.Drawable
1282     * @see #getDrawableState()
1283     */
1284    protected static final int[] FOCUSED_STATE_SET;
1285    /**
1286     * Indicates the view is selected. States are used with
1287     * {@link android.graphics.drawable.Drawable} to change the drawing of the
1288     * view depending on its state.
1289     *
1290     * @see android.graphics.drawable.Drawable
1291     * @see #getDrawableState()
1292     */
1293    protected static final int[] SELECTED_STATE_SET;
1294    /**
1295     * Indicates the view is pressed. States are used with
1296     * {@link android.graphics.drawable.Drawable} to change the drawing of the
1297     * view depending on its state.
1298     *
1299     * @see android.graphics.drawable.Drawable
1300     * @see #getDrawableState()
1301     */
1302    protected static final int[] PRESSED_STATE_SET;
1303    /**
1304     * Indicates the view's window has focus. States are used with
1305     * {@link android.graphics.drawable.Drawable} to change the drawing of the
1306     * view depending on its state.
1307     *
1308     * @see android.graphics.drawable.Drawable
1309     * @see #getDrawableState()
1310     */
1311    protected static final int[] WINDOW_FOCUSED_STATE_SET;
1312    // Doubles
1313    /**
1314     * Indicates the view is enabled and has the focus.
1315     *
1316     * @see #ENABLED_STATE_SET
1317     * @see #FOCUSED_STATE_SET
1318     */
1319    protected static final int[] ENABLED_FOCUSED_STATE_SET;
1320    /**
1321     * Indicates the view is enabled and selected.
1322     *
1323     * @see #ENABLED_STATE_SET
1324     * @see #SELECTED_STATE_SET
1325     */
1326    protected static final int[] ENABLED_SELECTED_STATE_SET;
1327    /**
1328     * Indicates the view is enabled and that its window has focus.
1329     *
1330     * @see #ENABLED_STATE_SET
1331     * @see #WINDOW_FOCUSED_STATE_SET
1332     */
1333    protected static final int[] ENABLED_WINDOW_FOCUSED_STATE_SET;
1334    /**
1335     * Indicates the view is focused and selected.
1336     *
1337     * @see #FOCUSED_STATE_SET
1338     * @see #SELECTED_STATE_SET
1339     */
1340    protected static final int[] FOCUSED_SELECTED_STATE_SET;
1341    /**
1342     * Indicates the view has the focus and that its window has the focus.
1343     *
1344     * @see #FOCUSED_STATE_SET
1345     * @see #WINDOW_FOCUSED_STATE_SET
1346     */
1347    protected static final int[] FOCUSED_WINDOW_FOCUSED_STATE_SET;
1348    /**
1349     * Indicates the view is selected and that its window has the focus.
1350     *
1351     * @see #SELECTED_STATE_SET
1352     * @see #WINDOW_FOCUSED_STATE_SET
1353     */
1354    protected static final int[] SELECTED_WINDOW_FOCUSED_STATE_SET;
1355    // Triples
1356    /**
1357     * Indicates the view is enabled, focused and selected.
1358     *
1359     * @see #ENABLED_STATE_SET
1360     * @see #FOCUSED_STATE_SET
1361     * @see #SELECTED_STATE_SET
1362     */
1363    protected static final int[] ENABLED_FOCUSED_SELECTED_STATE_SET;
1364    /**
1365     * Indicates the view is enabled, focused and its window has the focus.
1366     *
1367     * @see #ENABLED_STATE_SET
1368     * @see #FOCUSED_STATE_SET
1369     * @see #WINDOW_FOCUSED_STATE_SET
1370     */
1371    protected static final int[] ENABLED_FOCUSED_WINDOW_FOCUSED_STATE_SET;
1372    /**
1373     * Indicates the view is enabled, selected and its window has the focus.
1374     *
1375     * @see #ENABLED_STATE_SET
1376     * @see #SELECTED_STATE_SET
1377     * @see #WINDOW_FOCUSED_STATE_SET
1378     */
1379    protected static final int[] ENABLED_SELECTED_WINDOW_FOCUSED_STATE_SET;
1380    /**
1381     * Indicates the view is focused, selected and its window has the focus.
1382     *
1383     * @see #FOCUSED_STATE_SET
1384     * @see #SELECTED_STATE_SET
1385     * @see #WINDOW_FOCUSED_STATE_SET
1386     */
1387    protected static final int[] FOCUSED_SELECTED_WINDOW_FOCUSED_STATE_SET;
1388    /**
1389     * Indicates the view is enabled, focused, selected and its window
1390     * has the focus.
1391     *
1392     * @see #ENABLED_STATE_SET
1393     * @see #FOCUSED_STATE_SET
1394     * @see #SELECTED_STATE_SET
1395     * @see #WINDOW_FOCUSED_STATE_SET
1396     */
1397    protected static final int[] ENABLED_FOCUSED_SELECTED_WINDOW_FOCUSED_STATE_SET;
1398    /**
1399     * Indicates the view is pressed and its window has the focus.
1400     *
1401     * @see #PRESSED_STATE_SET
1402     * @see #WINDOW_FOCUSED_STATE_SET
1403     */
1404    protected static final int[] PRESSED_WINDOW_FOCUSED_STATE_SET;
1405    /**
1406     * Indicates the view is pressed and selected.
1407     *
1408     * @see #PRESSED_STATE_SET
1409     * @see #SELECTED_STATE_SET
1410     */
1411    protected static final int[] PRESSED_SELECTED_STATE_SET;
1412    /**
1413     * Indicates the view is pressed, selected and its window has the focus.
1414     *
1415     * @see #PRESSED_STATE_SET
1416     * @see #SELECTED_STATE_SET
1417     * @see #WINDOW_FOCUSED_STATE_SET
1418     */
1419    protected static final int[] PRESSED_SELECTED_WINDOW_FOCUSED_STATE_SET;
1420    /**
1421     * Indicates the view is pressed and focused.
1422     *
1423     * @see #PRESSED_STATE_SET
1424     * @see #FOCUSED_STATE_SET
1425     */
1426    protected static final int[] PRESSED_FOCUSED_STATE_SET;
1427    /**
1428     * Indicates the view is pressed, focused and its window has the focus.
1429     *
1430     * @see #PRESSED_STATE_SET
1431     * @see #FOCUSED_STATE_SET
1432     * @see #WINDOW_FOCUSED_STATE_SET
1433     */
1434    protected static final int[] PRESSED_FOCUSED_WINDOW_FOCUSED_STATE_SET;
1435    /**
1436     * Indicates the view is pressed, focused and selected.
1437     *
1438     * @see #PRESSED_STATE_SET
1439     * @see #SELECTED_STATE_SET
1440     * @see #FOCUSED_STATE_SET
1441     */
1442    protected static final int[] PRESSED_FOCUSED_SELECTED_STATE_SET;
1443    /**
1444     * Indicates the view is pressed, focused, selected and its window has the focus.
1445     *
1446     * @see #PRESSED_STATE_SET
1447     * @see #FOCUSED_STATE_SET
1448     * @see #SELECTED_STATE_SET
1449     * @see #WINDOW_FOCUSED_STATE_SET
1450     */
1451    protected static final int[] PRESSED_FOCUSED_SELECTED_WINDOW_FOCUSED_STATE_SET;
1452    /**
1453     * Indicates the view is pressed and enabled.
1454     *
1455     * @see #PRESSED_STATE_SET
1456     * @see #ENABLED_STATE_SET
1457     */
1458    protected static final int[] PRESSED_ENABLED_STATE_SET;
1459    /**
1460     * Indicates the view is pressed, enabled and its window has the focus.
1461     *
1462     * @see #PRESSED_STATE_SET
1463     * @see #ENABLED_STATE_SET
1464     * @see #WINDOW_FOCUSED_STATE_SET
1465     */
1466    protected static final int[] PRESSED_ENABLED_WINDOW_FOCUSED_STATE_SET;
1467    /**
1468     * Indicates the view is pressed, enabled and selected.
1469     *
1470     * @see #PRESSED_STATE_SET
1471     * @see #ENABLED_STATE_SET
1472     * @see #SELECTED_STATE_SET
1473     */
1474    protected static final int[] PRESSED_ENABLED_SELECTED_STATE_SET;
1475    /**
1476     * Indicates the view is pressed, enabled, selected and its window has the
1477     * focus.
1478     *
1479     * @see #PRESSED_STATE_SET
1480     * @see #ENABLED_STATE_SET
1481     * @see #SELECTED_STATE_SET
1482     * @see #WINDOW_FOCUSED_STATE_SET
1483     */
1484    protected static final int[] PRESSED_ENABLED_SELECTED_WINDOW_FOCUSED_STATE_SET;
1485    /**
1486     * Indicates the view is pressed, enabled and focused.
1487     *
1488     * @see #PRESSED_STATE_SET
1489     * @see #ENABLED_STATE_SET
1490     * @see #FOCUSED_STATE_SET
1491     */
1492    protected static final int[] PRESSED_ENABLED_FOCUSED_STATE_SET;
1493    /**
1494     * Indicates the view is pressed, enabled, focused and its window has the
1495     * focus.
1496     *
1497     * @see #PRESSED_STATE_SET
1498     * @see #ENABLED_STATE_SET
1499     * @see #FOCUSED_STATE_SET
1500     * @see #WINDOW_FOCUSED_STATE_SET
1501     */
1502    protected static final int[] PRESSED_ENABLED_FOCUSED_WINDOW_FOCUSED_STATE_SET;
1503    /**
1504     * Indicates the view is pressed, enabled, focused and selected.
1505     *
1506     * @see #PRESSED_STATE_SET
1507     * @see #ENABLED_STATE_SET
1508     * @see #SELECTED_STATE_SET
1509     * @see #FOCUSED_STATE_SET
1510     */
1511    protected static final int[] PRESSED_ENABLED_FOCUSED_SELECTED_STATE_SET;
1512    /**
1513     * Indicates the view is pressed, enabled, focused, selected and its window
1514     * has the focus.
1515     *
1516     * @see #PRESSED_STATE_SET
1517     * @see #ENABLED_STATE_SET
1518     * @see #SELECTED_STATE_SET
1519     * @see #FOCUSED_STATE_SET
1520     * @see #WINDOW_FOCUSED_STATE_SET
1521     */
1522    protected static final int[] PRESSED_ENABLED_FOCUSED_SELECTED_WINDOW_FOCUSED_STATE_SET;
1523
1524    static {
1525        EMPTY_STATE_SET = StateSet.get(0);
1526
1527        WINDOW_FOCUSED_STATE_SET = StateSet.get(StateSet.VIEW_STATE_WINDOW_FOCUSED);
1528
1529        SELECTED_STATE_SET = StateSet.get(StateSet.VIEW_STATE_SELECTED);
1530        SELECTED_WINDOW_FOCUSED_STATE_SET = StateSet.get(
1531                StateSet.VIEW_STATE_WINDOW_FOCUSED | StateSet.VIEW_STATE_SELECTED);
1532
1533        FOCUSED_STATE_SET = StateSet.get(StateSet.VIEW_STATE_FOCUSED);
1534        FOCUSED_WINDOW_FOCUSED_STATE_SET = StateSet.get(
1535                StateSet.VIEW_STATE_WINDOW_FOCUSED | StateSet.VIEW_STATE_FOCUSED);
1536        FOCUSED_SELECTED_STATE_SET = StateSet.get(
1537                StateSet.VIEW_STATE_SELECTED | StateSet.VIEW_STATE_FOCUSED);
1538        FOCUSED_SELECTED_WINDOW_FOCUSED_STATE_SET = StateSet.get(
1539                StateSet.VIEW_STATE_WINDOW_FOCUSED | StateSet.VIEW_STATE_SELECTED
1540                        | StateSet.VIEW_STATE_FOCUSED);
1541
1542        ENABLED_STATE_SET = StateSet.get(StateSet.VIEW_STATE_ENABLED);
1543        ENABLED_WINDOW_FOCUSED_STATE_SET = StateSet.get(
1544                StateSet.VIEW_STATE_WINDOW_FOCUSED | StateSet.VIEW_STATE_ENABLED);
1545        ENABLED_SELECTED_STATE_SET = StateSet.get(
1546                StateSet.VIEW_STATE_SELECTED | StateSet.VIEW_STATE_ENABLED);
1547        ENABLED_SELECTED_WINDOW_FOCUSED_STATE_SET = StateSet.get(
1548                StateSet.VIEW_STATE_WINDOW_FOCUSED | StateSet.VIEW_STATE_SELECTED
1549                        | StateSet.VIEW_STATE_ENABLED);
1550        ENABLED_FOCUSED_STATE_SET = StateSet.get(
1551                StateSet.VIEW_STATE_FOCUSED | StateSet.VIEW_STATE_ENABLED);
1552        ENABLED_FOCUSED_WINDOW_FOCUSED_STATE_SET = StateSet.get(
1553                StateSet.VIEW_STATE_WINDOW_FOCUSED | StateSet.VIEW_STATE_FOCUSED
1554                        | StateSet.VIEW_STATE_ENABLED);
1555        ENABLED_FOCUSED_SELECTED_STATE_SET = StateSet.get(
1556                StateSet.VIEW_STATE_SELECTED | StateSet.VIEW_STATE_FOCUSED
1557                        | StateSet.VIEW_STATE_ENABLED);
1558        ENABLED_FOCUSED_SELECTED_WINDOW_FOCUSED_STATE_SET = StateSet.get(
1559                StateSet.VIEW_STATE_WINDOW_FOCUSED | StateSet.VIEW_STATE_SELECTED
1560                        | StateSet.VIEW_STATE_FOCUSED| StateSet.VIEW_STATE_ENABLED);
1561
1562        PRESSED_STATE_SET = StateSet.get(StateSet.VIEW_STATE_PRESSED);
1563        PRESSED_WINDOW_FOCUSED_STATE_SET = StateSet.get(
1564                StateSet.VIEW_STATE_WINDOW_FOCUSED | StateSet.VIEW_STATE_PRESSED);
1565        PRESSED_SELECTED_STATE_SET = StateSet.get(
1566                StateSet.VIEW_STATE_SELECTED | StateSet.VIEW_STATE_PRESSED);
1567        PRESSED_SELECTED_WINDOW_FOCUSED_STATE_SET = StateSet.get(
1568                StateSet.VIEW_STATE_WINDOW_FOCUSED | StateSet.VIEW_STATE_SELECTED
1569                        | StateSet.VIEW_STATE_PRESSED);
1570        PRESSED_FOCUSED_STATE_SET = StateSet.get(
1571                StateSet.VIEW_STATE_FOCUSED | StateSet.VIEW_STATE_PRESSED);
1572        PRESSED_FOCUSED_WINDOW_FOCUSED_STATE_SET = StateSet.get(
1573                StateSet.VIEW_STATE_WINDOW_FOCUSED | StateSet.VIEW_STATE_FOCUSED
1574                        | StateSet.VIEW_STATE_PRESSED);
1575        PRESSED_FOCUSED_SELECTED_STATE_SET = StateSet.get(
1576                StateSet.VIEW_STATE_SELECTED | StateSet.VIEW_STATE_FOCUSED
1577                        | StateSet.VIEW_STATE_PRESSED);
1578        PRESSED_FOCUSED_SELECTED_WINDOW_FOCUSED_STATE_SET = StateSet.get(
1579                StateSet.VIEW_STATE_WINDOW_FOCUSED | StateSet.VIEW_STATE_SELECTED
1580                        | StateSet.VIEW_STATE_FOCUSED | StateSet.VIEW_STATE_PRESSED);
1581        PRESSED_ENABLED_STATE_SET = StateSet.get(
1582                StateSet.VIEW_STATE_ENABLED | StateSet.VIEW_STATE_PRESSED);
1583        PRESSED_ENABLED_WINDOW_FOCUSED_STATE_SET = StateSet.get(
1584                StateSet.VIEW_STATE_WINDOW_FOCUSED | StateSet.VIEW_STATE_ENABLED
1585                        | StateSet.VIEW_STATE_PRESSED);
1586        PRESSED_ENABLED_SELECTED_STATE_SET = StateSet.get(
1587                StateSet.VIEW_STATE_SELECTED | StateSet.VIEW_STATE_ENABLED
1588                        | StateSet.VIEW_STATE_PRESSED);
1589        PRESSED_ENABLED_SELECTED_WINDOW_FOCUSED_STATE_SET = StateSet.get(
1590                StateSet.VIEW_STATE_WINDOW_FOCUSED | StateSet.VIEW_STATE_SELECTED
1591                        | StateSet.VIEW_STATE_ENABLED | StateSet.VIEW_STATE_PRESSED);
1592        PRESSED_ENABLED_FOCUSED_STATE_SET = StateSet.get(
1593                StateSet.VIEW_STATE_FOCUSED | StateSet.VIEW_STATE_ENABLED
1594                        | StateSet.VIEW_STATE_PRESSED);
1595        PRESSED_ENABLED_FOCUSED_WINDOW_FOCUSED_STATE_SET = StateSet.get(
1596                StateSet.VIEW_STATE_WINDOW_FOCUSED | StateSet.VIEW_STATE_FOCUSED
1597                        | StateSet.VIEW_STATE_ENABLED | StateSet.VIEW_STATE_PRESSED);
1598        PRESSED_ENABLED_FOCUSED_SELECTED_STATE_SET = StateSet.get(
1599                StateSet.VIEW_STATE_SELECTED | StateSet.VIEW_STATE_FOCUSED
1600                        | StateSet.VIEW_STATE_ENABLED | StateSet.VIEW_STATE_PRESSED);
1601        PRESSED_ENABLED_FOCUSED_SELECTED_WINDOW_FOCUSED_STATE_SET = StateSet.get(
1602                StateSet.VIEW_STATE_WINDOW_FOCUSED | StateSet.VIEW_STATE_SELECTED
1603                        | StateSet.VIEW_STATE_FOCUSED| StateSet.VIEW_STATE_ENABLED
1604                        | StateSet.VIEW_STATE_PRESSED);
1605    }
1606
1607    /**
1608     * Accessibility event types that are dispatched for text population.
1609     */
1610    private static final int POPULATING_ACCESSIBILITY_EVENT_TYPES =
1611            AccessibilityEvent.TYPE_VIEW_CLICKED
1612            | AccessibilityEvent.TYPE_VIEW_LONG_CLICKED
1613            | AccessibilityEvent.TYPE_VIEW_SELECTED
1614            | AccessibilityEvent.TYPE_VIEW_FOCUSED
1615            | AccessibilityEvent.TYPE_WINDOW_STATE_CHANGED
1616            | AccessibilityEvent.TYPE_VIEW_HOVER_ENTER
1617            | AccessibilityEvent.TYPE_VIEW_HOVER_EXIT
1618            | AccessibilityEvent.TYPE_VIEW_TEXT_CHANGED
1619            | AccessibilityEvent.TYPE_VIEW_TEXT_SELECTION_CHANGED
1620            | AccessibilityEvent.TYPE_VIEW_ACCESSIBILITY_FOCUSED
1621            | AccessibilityEvent.TYPE_VIEW_TEXT_TRAVERSED_AT_MOVEMENT_GRANULARITY;
1622
1623    /**
1624     * Temporary Rect currently for use in setBackground().  This will probably
1625     * be extended in the future to hold our own class with more than just
1626     * a Rect. :)
1627     */
1628    static final ThreadLocal<Rect> sThreadLocal = new ThreadLocal<Rect>();
1629
1630    /**
1631     * Map used to store views' tags.
1632     */
1633    private SparseArray<Object> mKeyedTags;
1634
1635    /**
1636     * The next available accessibility id.
1637     */
1638    private static int sNextAccessibilityViewId;
1639
1640    /**
1641     * The animation currently associated with this view.
1642     * @hide
1643     */
1644    protected Animation mCurrentAnimation = null;
1645
1646    /**
1647     * Width as measured during measure pass.
1648     * {@hide}
1649     */
1650    @ViewDebug.ExportedProperty(category = "measurement")
1651    int mMeasuredWidth;
1652
1653    /**
1654     * Height as measured during measure pass.
1655     * {@hide}
1656     */
1657    @ViewDebug.ExportedProperty(category = "measurement")
1658    int mMeasuredHeight;
1659
1660    /**
1661     * Flag to indicate that this view was marked INVALIDATED, or had its display list
1662     * invalidated, prior to the current drawing iteration. If true, the view must re-draw
1663     * its display list. This flag, used only when hw accelerated, allows us to clear the
1664     * flag while retaining this information until it's needed (at getDisplayList() time and
1665     * in drawChild(), when we decide to draw a view's children's display lists into our own).
1666     *
1667     * {@hide}
1668     */
1669    boolean mRecreateDisplayList = false;
1670
1671    /**
1672     * The view's identifier.
1673     * {@hide}
1674     *
1675     * @see #setId(int)
1676     * @see #getId()
1677     */
1678    @IdRes
1679    @ViewDebug.ExportedProperty(resolveId = true)
1680    int mID = NO_ID;
1681
1682    /**
1683     * The stable ID of this view for accessibility purposes.
1684     */
1685    int mAccessibilityViewId = NO_ID;
1686
1687    private int mAccessibilityCursorPosition = ACCESSIBILITY_CURSOR_POSITION_UNDEFINED;
1688
1689    SendViewStateChangedAccessibilityEvent mSendViewStateChangedAccessibilityEvent;
1690
1691    /**
1692     * The view's tag.
1693     * {@hide}
1694     *
1695     * @see #setTag(Object)
1696     * @see #getTag()
1697     */
1698    protected Object mTag = null;
1699
1700    // for mPrivateFlags:
1701    /** {@hide} */
1702    static final int PFLAG_WANTS_FOCUS                 = 0x00000001;
1703    /** {@hide} */
1704    static final int PFLAG_FOCUSED                     = 0x00000002;
1705    /** {@hide} */
1706    static final int PFLAG_SELECTED                    = 0x00000004;
1707    /** {@hide} */
1708    static final int PFLAG_IS_ROOT_NAMESPACE           = 0x00000008;
1709    /** {@hide} */
1710    static final int PFLAG_HAS_BOUNDS                  = 0x00000010;
1711    /** {@hide} */
1712    static final int PFLAG_DRAWN                       = 0x00000020;
1713    /**
1714     * When this flag is set, this view is running an animation on behalf of its
1715     * children and should therefore not cancel invalidate requests, even if they
1716     * lie outside of this view's bounds.
1717     *
1718     * {@hide}
1719     */
1720    static final int PFLAG_DRAW_ANIMATION              = 0x00000040;
1721    /** {@hide} */
1722    static final int PFLAG_SKIP_DRAW                   = 0x00000080;
1723    /** {@hide} */
1724    static final int PFLAG_REQUEST_TRANSPARENT_REGIONS = 0x00000200;
1725    /** {@hide} */
1726    static final int PFLAG_DRAWABLE_STATE_DIRTY        = 0x00000400;
1727    /** {@hide} */
1728    static final int PFLAG_MEASURED_DIMENSION_SET      = 0x00000800;
1729    /** {@hide} */
1730    static final int PFLAG_FORCE_LAYOUT                = 0x00001000;
1731    /** {@hide} */
1732    static final int PFLAG_LAYOUT_REQUIRED             = 0x00002000;
1733
1734    private static final int PFLAG_PRESSED             = 0x00004000;
1735
1736    /** {@hide} */
1737    static final int PFLAG_DRAWING_CACHE_VALID         = 0x00008000;
1738    /**
1739     * Flag used to indicate that this view should be drawn once more (and only once
1740     * more) after its animation has completed.
1741     * {@hide}
1742     */
1743    static final int PFLAG_ANIMATION_STARTED           = 0x00010000;
1744
1745    private static final int PFLAG_SAVE_STATE_CALLED   = 0x00020000;
1746
1747    /**
1748     * Indicates that the View returned true when onSetAlpha() was called and that
1749     * the alpha must be restored.
1750     * {@hide}
1751     */
1752    static final int PFLAG_ALPHA_SET                   = 0x00040000;
1753
1754    /**
1755     * Set by {@link #setScrollContainer(boolean)}.
1756     */
1757    static final int PFLAG_SCROLL_CONTAINER            = 0x00080000;
1758
1759    /**
1760     * Set by {@link #setScrollContainer(boolean)}.
1761     */
1762    static final int PFLAG_SCROLL_CONTAINER_ADDED      = 0x00100000;
1763
1764    /**
1765     * View flag indicating whether this view was invalidated (fully or partially.)
1766     *
1767     * @hide
1768     */
1769    static final int PFLAG_DIRTY                       = 0x00200000;
1770
1771    /**
1772     * View flag indicating whether this view was invalidated by an opaque
1773     * invalidate request.
1774     *
1775     * @hide
1776     */
1777    static final int PFLAG_DIRTY_OPAQUE                = 0x00400000;
1778
1779    /**
1780     * Mask for {@link #PFLAG_DIRTY} and {@link #PFLAG_DIRTY_OPAQUE}.
1781     *
1782     * @hide
1783     */
1784    static final int PFLAG_DIRTY_MASK                  = 0x00600000;
1785
1786    /**
1787     * Indicates whether the background is opaque.
1788     *
1789     * @hide
1790     */
1791    static final int PFLAG_OPAQUE_BACKGROUND           = 0x00800000;
1792
1793    /**
1794     * Indicates whether the scrollbars are opaque.
1795     *
1796     * @hide
1797     */
1798    static final int PFLAG_OPAQUE_SCROLLBARS           = 0x01000000;
1799
1800    /**
1801     * Indicates whether the view is opaque.
1802     *
1803     * @hide
1804     */
1805    static final int PFLAG_OPAQUE_MASK                 = 0x01800000;
1806
1807    /**
1808     * Indicates a prepressed state;
1809     * the short time between ACTION_DOWN and recognizing
1810     * a 'real' press. Prepressed is used to recognize quick taps
1811     * even when they are shorter than ViewConfiguration.getTapTimeout().
1812     *
1813     * @hide
1814     */
1815    private static final int PFLAG_PREPRESSED          = 0x02000000;
1816
1817    /**
1818     * Indicates whether the view is temporarily detached.
1819     *
1820     * @hide
1821     */
1822    static final int PFLAG_CANCEL_NEXT_UP_EVENT        = 0x04000000;
1823
1824    /**
1825     * Indicates that we should awaken scroll bars once attached
1826     *
1827     * PLEASE NOTE: This flag is now unused as we now send onVisibilityChanged
1828     * during window attachment and it is no longer needed. Feel free to repurpose it.
1829     *
1830     * @hide
1831     */
1832    private static final int PFLAG_AWAKEN_SCROLL_BARS_ON_ATTACH = 0x08000000;
1833
1834    /**
1835     * Indicates that the view has received HOVER_ENTER.  Cleared on HOVER_EXIT.
1836     * @hide
1837     */
1838    private static final int PFLAG_HOVERED             = 0x10000000;
1839
1840    /**
1841     * no longer needed, should be reused
1842     */
1843    private static final int PFLAG_DOES_NOTHING_REUSE_PLEASE = 0x20000000;
1844
1845    /** {@hide} */
1846    static final int PFLAG_ACTIVATED                   = 0x40000000;
1847
1848    /**
1849     * Indicates that this view was specifically invalidated, not just dirtied because some
1850     * child view was invalidated. The flag is used to determine when we need to recreate
1851     * a view's display list (as opposed to just returning a reference to its existing
1852     * display list).
1853     *
1854     * @hide
1855     */
1856    static final int PFLAG_INVALIDATED                 = 0x80000000;
1857
1858    /**
1859     * Masks for mPrivateFlags2, as generated by dumpFlags():
1860     *
1861     * |-------|-------|-------|-------|
1862     *                                 1 PFLAG2_DRAG_CAN_ACCEPT
1863     *                                1  PFLAG2_DRAG_HOVERED
1864     *                              11   PFLAG2_LAYOUT_DIRECTION_MASK
1865     *                             1     PFLAG2_LAYOUT_DIRECTION_RESOLVED_RTL
1866     *                            1      PFLAG2_LAYOUT_DIRECTION_RESOLVED
1867     *                            11     PFLAG2_LAYOUT_DIRECTION_RESOLVED_MASK
1868     *                           1       PFLAG2_TEXT_DIRECTION_FLAGS[1]
1869     *                          1        PFLAG2_TEXT_DIRECTION_FLAGS[2]
1870     *                          11       PFLAG2_TEXT_DIRECTION_FLAGS[3]
1871     *                         1         PFLAG2_TEXT_DIRECTION_FLAGS[4]
1872     *                         1 1       PFLAG2_TEXT_DIRECTION_FLAGS[5]
1873     *                         11        PFLAG2_TEXT_DIRECTION_FLAGS[6]
1874     *                         111       PFLAG2_TEXT_DIRECTION_FLAGS[7]
1875     *                         111       PFLAG2_TEXT_DIRECTION_MASK
1876     *                        1          PFLAG2_TEXT_DIRECTION_RESOLVED
1877     *                       1           PFLAG2_TEXT_DIRECTION_RESOLVED_DEFAULT
1878     *                     111           PFLAG2_TEXT_DIRECTION_RESOLVED_MASK
1879     *                    1              PFLAG2_TEXT_ALIGNMENT_FLAGS[1]
1880     *                   1               PFLAG2_TEXT_ALIGNMENT_FLAGS[2]
1881     *                   11              PFLAG2_TEXT_ALIGNMENT_FLAGS[3]
1882     *                  1                PFLAG2_TEXT_ALIGNMENT_FLAGS[4]
1883     *                  1 1              PFLAG2_TEXT_ALIGNMENT_FLAGS[5]
1884     *                  11               PFLAG2_TEXT_ALIGNMENT_FLAGS[6]
1885     *                  111              PFLAG2_TEXT_ALIGNMENT_MASK
1886     *                 1                 PFLAG2_TEXT_ALIGNMENT_RESOLVED
1887     *                1                  PFLAG2_TEXT_ALIGNMENT_RESOLVED_DEFAULT
1888     *              111                  PFLAG2_TEXT_ALIGNMENT_RESOLVED_MASK
1889     *           111                     PFLAG2_IMPORTANT_FOR_ACCESSIBILITY_MASK
1890     *         11                        PFLAG2_ACCESSIBILITY_LIVE_REGION_MASK
1891     *       1                           PFLAG2_ACCESSIBILITY_FOCUSED
1892     *      1                            PFLAG2_SUBTREE_ACCESSIBILITY_STATE_CHANGED
1893     *     1                             PFLAG2_VIEW_QUICK_REJECTED
1894     *    1                              PFLAG2_PADDING_RESOLVED
1895     *   1                               PFLAG2_DRAWABLE_RESOLVED
1896     *  1                                PFLAG2_HAS_TRANSIENT_STATE
1897     * |-------|-------|-------|-------|
1898     */
1899
1900    /**
1901     * Indicates that this view has reported that it can accept the current drag's content.
1902     * Cleared when the drag operation concludes.
1903     * @hide
1904     */
1905    static final int PFLAG2_DRAG_CAN_ACCEPT            = 0x00000001;
1906
1907    /**
1908     * Indicates that this view is currently directly under the drag location in a
1909     * drag-and-drop operation involving content that it can accept.  Cleared when
1910     * the drag exits the view, or when the drag operation concludes.
1911     * @hide
1912     */
1913    static final int PFLAG2_DRAG_HOVERED               = 0x00000002;
1914
1915    /** @hide */
1916    @IntDef({
1917        LAYOUT_DIRECTION_LTR,
1918        LAYOUT_DIRECTION_RTL,
1919        LAYOUT_DIRECTION_INHERIT,
1920        LAYOUT_DIRECTION_LOCALE
1921    })
1922    @Retention(RetentionPolicy.SOURCE)
1923    // Not called LayoutDirection to avoid conflict with android.util.LayoutDirection
1924    public @interface LayoutDir {}
1925
1926    /** @hide */
1927    @IntDef({
1928        LAYOUT_DIRECTION_LTR,
1929        LAYOUT_DIRECTION_RTL
1930    })
1931    @Retention(RetentionPolicy.SOURCE)
1932    public @interface ResolvedLayoutDir {}
1933
1934    /**
1935     * A flag to indicate that the layout direction of this view has not been defined yet.
1936     * @hide
1937     */
1938    public static final int LAYOUT_DIRECTION_UNDEFINED = LayoutDirection.UNDEFINED;
1939
1940    /**
1941     * Horizontal layout direction of this view is from Left to Right.
1942     * Use with {@link #setLayoutDirection}.
1943     */
1944    public static final int LAYOUT_DIRECTION_LTR = LayoutDirection.LTR;
1945
1946    /**
1947     * Horizontal layout direction of this view is from Right to Left.
1948     * Use with {@link #setLayoutDirection}.
1949     */
1950    public static final int LAYOUT_DIRECTION_RTL = LayoutDirection.RTL;
1951
1952    /**
1953     * Horizontal layout direction of this view is inherited from its parent.
1954     * Use with {@link #setLayoutDirection}.
1955     */
1956    public static final int LAYOUT_DIRECTION_INHERIT = LayoutDirection.INHERIT;
1957
1958    /**
1959     * Horizontal layout direction of this view is from deduced from the default language
1960     * script for the locale. Use with {@link #setLayoutDirection}.
1961     */
1962    public static final int LAYOUT_DIRECTION_LOCALE = LayoutDirection.LOCALE;
1963
1964    /**
1965     * Bit shift to get the horizontal layout direction. (bits after DRAG_HOVERED)
1966     * @hide
1967     */
1968    static final int PFLAG2_LAYOUT_DIRECTION_MASK_SHIFT = 2;
1969
1970    /**
1971     * Mask for use with private flags indicating bits used for horizontal layout direction.
1972     * @hide
1973     */
1974    static final int PFLAG2_LAYOUT_DIRECTION_MASK = 0x00000003 << PFLAG2_LAYOUT_DIRECTION_MASK_SHIFT;
1975
1976    /**
1977     * Indicates whether the view horizontal layout direction has been resolved and drawn to the
1978     * right-to-left direction.
1979     * @hide
1980     */
1981    static final int PFLAG2_LAYOUT_DIRECTION_RESOLVED_RTL = 4 << PFLAG2_LAYOUT_DIRECTION_MASK_SHIFT;
1982
1983    /**
1984     * Indicates whether the view horizontal layout direction has been resolved.
1985     * @hide
1986     */
1987    static final int PFLAG2_LAYOUT_DIRECTION_RESOLVED = 8 << PFLAG2_LAYOUT_DIRECTION_MASK_SHIFT;
1988
1989    /**
1990     * Mask for use with private flags indicating bits used for resolved horizontal layout direction.
1991     * @hide
1992     */
1993    static final int PFLAG2_LAYOUT_DIRECTION_RESOLVED_MASK = 0x0000000C
1994            << PFLAG2_LAYOUT_DIRECTION_MASK_SHIFT;
1995
1996    /*
1997     * Array of horizontal layout direction flags for mapping attribute "layoutDirection" to correct
1998     * flag value.
1999     * @hide
2000     */
2001    private static final int[] LAYOUT_DIRECTION_FLAGS = {
2002            LAYOUT_DIRECTION_LTR,
2003            LAYOUT_DIRECTION_RTL,
2004            LAYOUT_DIRECTION_INHERIT,
2005            LAYOUT_DIRECTION_LOCALE
2006    };
2007
2008    /**
2009     * Default horizontal layout direction.
2010     */
2011    private static final int LAYOUT_DIRECTION_DEFAULT = LAYOUT_DIRECTION_INHERIT;
2012
2013    /**
2014     * Default horizontal layout direction.
2015     * @hide
2016     */
2017    static final int LAYOUT_DIRECTION_RESOLVED_DEFAULT = LAYOUT_DIRECTION_LTR;
2018
2019    /**
2020     * Text direction is inherited through {@link ViewGroup}
2021     */
2022    public static final int TEXT_DIRECTION_INHERIT = 0;
2023
2024    /**
2025     * Text direction is using "first strong algorithm". The first strong directional character
2026     * determines the paragraph direction. If there is no strong directional character, the
2027     * paragraph direction is the view's resolved layout direction.
2028     */
2029    public static final int TEXT_DIRECTION_FIRST_STRONG = 1;
2030
2031    /**
2032     * Text direction is using "any-RTL" algorithm. The paragraph direction is RTL if it contains
2033     * any strong RTL character, otherwise it is LTR if it contains any strong LTR characters.
2034     * If there are neither, the paragraph direction is the view's resolved layout direction.
2035     */
2036    public static final int TEXT_DIRECTION_ANY_RTL = 2;
2037
2038    /**
2039     * Text direction is forced to LTR.
2040     */
2041    public static final int TEXT_DIRECTION_LTR = 3;
2042
2043    /**
2044     * Text direction is forced to RTL.
2045     */
2046    public static final int TEXT_DIRECTION_RTL = 4;
2047
2048    /**
2049     * Text direction is coming from the system Locale.
2050     */
2051    public static final int TEXT_DIRECTION_LOCALE = 5;
2052
2053    /**
2054     * Text direction is using "first strong algorithm". The first strong directional character
2055     * determines the paragraph direction. If there is no strong directional character, the
2056     * paragraph direction is LTR.
2057     */
2058    public static final int TEXT_DIRECTION_FIRST_STRONG_LTR = 6;
2059
2060    /**
2061     * Text direction is using "first strong algorithm". The first strong directional character
2062     * determines the paragraph direction. If there is no strong directional character, the
2063     * paragraph direction is RTL.
2064     */
2065    public static final int TEXT_DIRECTION_FIRST_STRONG_RTL = 7;
2066
2067    /**
2068     * Default text direction is inherited
2069     */
2070    private static final int TEXT_DIRECTION_DEFAULT = TEXT_DIRECTION_INHERIT;
2071
2072    /**
2073     * Default resolved text direction
2074     * @hide
2075     */
2076    static final int TEXT_DIRECTION_RESOLVED_DEFAULT = TEXT_DIRECTION_FIRST_STRONG;
2077
2078    /**
2079     * Bit shift to get the horizontal layout direction. (bits after LAYOUT_DIRECTION_RESOLVED)
2080     * @hide
2081     */
2082    static final int PFLAG2_TEXT_DIRECTION_MASK_SHIFT = 6;
2083
2084    /**
2085     * Mask for use with private flags indicating bits used for text direction.
2086     * @hide
2087     */
2088    static final int PFLAG2_TEXT_DIRECTION_MASK = 0x00000007
2089            << PFLAG2_TEXT_DIRECTION_MASK_SHIFT;
2090
2091    /**
2092     * Array of text direction flags for mapping attribute "textDirection" to correct
2093     * flag value.
2094     * @hide
2095     */
2096    private static final int[] PFLAG2_TEXT_DIRECTION_FLAGS = {
2097            TEXT_DIRECTION_INHERIT << PFLAG2_TEXT_DIRECTION_MASK_SHIFT,
2098            TEXT_DIRECTION_FIRST_STRONG << PFLAG2_TEXT_DIRECTION_MASK_SHIFT,
2099            TEXT_DIRECTION_ANY_RTL << PFLAG2_TEXT_DIRECTION_MASK_SHIFT,
2100            TEXT_DIRECTION_LTR << PFLAG2_TEXT_DIRECTION_MASK_SHIFT,
2101            TEXT_DIRECTION_RTL << PFLAG2_TEXT_DIRECTION_MASK_SHIFT,
2102            TEXT_DIRECTION_LOCALE << PFLAG2_TEXT_DIRECTION_MASK_SHIFT,
2103            TEXT_DIRECTION_FIRST_STRONG_LTR << PFLAG2_TEXT_DIRECTION_MASK_SHIFT,
2104            TEXT_DIRECTION_FIRST_STRONG_RTL << PFLAG2_TEXT_DIRECTION_MASK_SHIFT
2105    };
2106
2107    /**
2108     * Indicates whether the view text direction has been resolved.
2109     * @hide
2110     */
2111    static final int PFLAG2_TEXT_DIRECTION_RESOLVED = 0x00000008
2112            << PFLAG2_TEXT_DIRECTION_MASK_SHIFT;
2113
2114    /**
2115     * Bit shift to get the horizontal layout direction. (bits after DRAG_HOVERED)
2116     * @hide
2117     */
2118    static final int PFLAG2_TEXT_DIRECTION_RESOLVED_MASK_SHIFT = 10;
2119
2120    /**
2121     * Mask for use with private flags indicating bits used for resolved text direction.
2122     * @hide
2123     */
2124    static final int PFLAG2_TEXT_DIRECTION_RESOLVED_MASK = 0x00000007
2125            << PFLAG2_TEXT_DIRECTION_RESOLVED_MASK_SHIFT;
2126
2127    /**
2128     * Indicates whether the view text direction has been resolved to the "first strong" heuristic.
2129     * @hide
2130     */
2131    static final int PFLAG2_TEXT_DIRECTION_RESOLVED_DEFAULT =
2132            TEXT_DIRECTION_RESOLVED_DEFAULT << PFLAG2_TEXT_DIRECTION_RESOLVED_MASK_SHIFT;
2133
2134    /** @hide */
2135    @IntDef({
2136        TEXT_ALIGNMENT_INHERIT,
2137        TEXT_ALIGNMENT_GRAVITY,
2138        TEXT_ALIGNMENT_CENTER,
2139        TEXT_ALIGNMENT_TEXT_START,
2140        TEXT_ALIGNMENT_TEXT_END,
2141        TEXT_ALIGNMENT_VIEW_START,
2142        TEXT_ALIGNMENT_VIEW_END
2143    })
2144    @Retention(RetentionPolicy.SOURCE)
2145    public @interface TextAlignment {}
2146
2147    /**
2148     * Default text alignment. The text alignment of this View is inherited from its parent.
2149     * Use with {@link #setTextAlignment(int)}
2150     */
2151    public static final int TEXT_ALIGNMENT_INHERIT = 0;
2152
2153    /**
2154     * Default for the root view. The gravity determines the text alignment, ALIGN_NORMAL,
2155     * ALIGN_CENTER, or ALIGN_OPPOSITE, which are relative to each paragraph’s text direction.
2156     *
2157     * Use with {@link #setTextAlignment(int)}
2158     */
2159    public static final int TEXT_ALIGNMENT_GRAVITY = 1;
2160
2161    /**
2162     * Align to the start of the paragraph, e.g. ALIGN_NORMAL.
2163     *
2164     * Use with {@link #setTextAlignment(int)}
2165     */
2166    public static final int TEXT_ALIGNMENT_TEXT_START = 2;
2167
2168    /**
2169     * Align to the end of the paragraph, e.g. ALIGN_OPPOSITE.
2170     *
2171     * Use with {@link #setTextAlignment(int)}
2172     */
2173    public static final int TEXT_ALIGNMENT_TEXT_END = 3;
2174
2175    /**
2176     * Center the paragraph, e.g. ALIGN_CENTER.
2177     *
2178     * Use with {@link #setTextAlignment(int)}
2179     */
2180    public static final int TEXT_ALIGNMENT_CENTER = 4;
2181
2182    /**
2183     * Align to the start of the view, which is ALIGN_LEFT if the view’s resolved
2184     * layoutDirection is LTR, and ALIGN_RIGHT otherwise.
2185     *
2186     * Use with {@link #setTextAlignment(int)}
2187     */
2188    public static final int TEXT_ALIGNMENT_VIEW_START = 5;
2189
2190    /**
2191     * Align to the end of the view, which is ALIGN_RIGHT if the view’s resolved
2192     * layoutDirection is LTR, and ALIGN_LEFT otherwise.
2193     *
2194     * Use with {@link #setTextAlignment(int)}
2195     */
2196    public static final int TEXT_ALIGNMENT_VIEW_END = 6;
2197
2198    /**
2199     * Default text alignment is inherited
2200     */
2201    private static final int TEXT_ALIGNMENT_DEFAULT = TEXT_ALIGNMENT_GRAVITY;
2202
2203    /**
2204     * Default resolved text alignment
2205     * @hide
2206     */
2207    static final int TEXT_ALIGNMENT_RESOLVED_DEFAULT = TEXT_ALIGNMENT_GRAVITY;
2208
2209    /**
2210      * Bit shift to get the horizontal layout direction. (bits after DRAG_HOVERED)
2211      * @hide
2212      */
2213    static final int PFLAG2_TEXT_ALIGNMENT_MASK_SHIFT = 13;
2214
2215    /**
2216      * Mask for use with private flags indicating bits used for text alignment.
2217      * @hide
2218      */
2219    static final int PFLAG2_TEXT_ALIGNMENT_MASK = 0x00000007 << PFLAG2_TEXT_ALIGNMENT_MASK_SHIFT;
2220
2221    /**
2222     * Array of text direction flags for mapping attribute "textAlignment" to correct
2223     * flag value.
2224     * @hide
2225     */
2226    private static final int[] PFLAG2_TEXT_ALIGNMENT_FLAGS = {
2227            TEXT_ALIGNMENT_INHERIT << PFLAG2_TEXT_ALIGNMENT_MASK_SHIFT,
2228            TEXT_ALIGNMENT_GRAVITY << PFLAG2_TEXT_ALIGNMENT_MASK_SHIFT,
2229            TEXT_ALIGNMENT_TEXT_START << PFLAG2_TEXT_ALIGNMENT_MASK_SHIFT,
2230            TEXT_ALIGNMENT_TEXT_END << PFLAG2_TEXT_ALIGNMENT_MASK_SHIFT,
2231            TEXT_ALIGNMENT_CENTER << PFLAG2_TEXT_ALIGNMENT_MASK_SHIFT,
2232            TEXT_ALIGNMENT_VIEW_START << PFLAG2_TEXT_ALIGNMENT_MASK_SHIFT,
2233            TEXT_ALIGNMENT_VIEW_END << PFLAG2_TEXT_ALIGNMENT_MASK_SHIFT
2234    };
2235
2236    /**
2237     * Indicates whether the view text alignment has been resolved.
2238     * @hide
2239     */
2240    static final int PFLAG2_TEXT_ALIGNMENT_RESOLVED = 0x00000008 << PFLAG2_TEXT_ALIGNMENT_MASK_SHIFT;
2241
2242    /**
2243     * Bit shift to get the resolved text alignment.
2244     * @hide
2245     */
2246    static final int PFLAG2_TEXT_ALIGNMENT_RESOLVED_MASK_SHIFT = 17;
2247
2248    /**
2249     * Mask for use with private flags indicating bits used for text alignment.
2250     * @hide
2251     */
2252    static final int PFLAG2_TEXT_ALIGNMENT_RESOLVED_MASK = 0x00000007
2253            << PFLAG2_TEXT_ALIGNMENT_RESOLVED_MASK_SHIFT;
2254
2255    /**
2256     * Indicates whether if the view text alignment has been resolved to gravity
2257     */
2258    private static final int PFLAG2_TEXT_ALIGNMENT_RESOLVED_DEFAULT =
2259            TEXT_ALIGNMENT_RESOLVED_DEFAULT << PFLAG2_TEXT_ALIGNMENT_RESOLVED_MASK_SHIFT;
2260
2261    // Accessiblity constants for mPrivateFlags2
2262
2263    /**
2264     * Shift for the bits in {@link #mPrivateFlags2} related to the
2265     * "importantForAccessibility" attribute.
2266     */
2267    static final int PFLAG2_IMPORTANT_FOR_ACCESSIBILITY_SHIFT = 20;
2268
2269    /**
2270     * Automatically determine whether a view is important for accessibility.
2271     */
2272    public static final int IMPORTANT_FOR_ACCESSIBILITY_AUTO = 0x00000000;
2273
2274    /**
2275     * The view is important for accessibility.
2276     */
2277    public static final int IMPORTANT_FOR_ACCESSIBILITY_YES = 0x00000001;
2278
2279    /**
2280     * The view is not important for accessibility.
2281     */
2282    public static final int IMPORTANT_FOR_ACCESSIBILITY_NO = 0x00000002;
2283
2284    /**
2285     * The view is not important for accessibility, nor are any of its
2286     * descendant views.
2287     */
2288    public static final int IMPORTANT_FOR_ACCESSIBILITY_NO_HIDE_DESCENDANTS = 0x00000004;
2289
2290    /**
2291     * The default whether the view is important for accessibility.
2292     */
2293    static final int IMPORTANT_FOR_ACCESSIBILITY_DEFAULT = IMPORTANT_FOR_ACCESSIBILITY_AUTO;
2294
2295    /**
2296     * Mask for obtainig the bits which specify how to determine
2297     * whether a view is important for accessibility.
2298     */
2299    static final int PFLAG2_IMPORTANT_FOR_ACCESSIBILITY_MASK = (IMPORTANT_FOR_ACCESSIBILITY_AUTO
2300        | IMPORTANT_FOR_ACCESSIBILITY_YES | IMPORTANT_FOR_ACCESSIBILITY_NO
2301        | IMPORTANT_FOR_ACCESSIBILITY_NO_HIDE_DESCENDANTS)
2302        << PFLAG2_IMPORTANT_FOR_ACCESSIBILITY_SHIFT;
2303
2304    /**
2305     * Shift for the bits in {@link #mPrivateFlags2} related to the
2306     * "accessibilityLiveRegion" attribute.
2307     */
2308    static final int PFLAG2_ACCESSIBILITY_LIVE_REGION_SHIFT = 23;
2309
2310    /**
2311     * Live region mode specifying that accessibility services should not
2312     * automatically announce changes to this view. This is the default live
2313     * region mode for most views.
2314     * <p>
2315     * Use with {@link #setAccessibilityLiveRegion(int)}.
2316     */
2317    public static final int ACCESSIBILITY_LIVE_REGION_NONE = 0x00000000;
2318
2319    /**
2320     * Live region mode specifying that accessibility services should announce
2321     * changes to this view.
2322     * <p>
2323     * Use with {@link #setAccessibilityLiveRegion(int)}.
2324     */
2325    public static final int ACCESSIBILITY_LIVE_REGION_POLITE = 0x00000001;
2326
2327    /**
2328     * Live region mode specifying that accessibility services should interrupt
2329     * ongoing speech to immediately announce changes to this view.
2330     * <p>
2331     * Use with {@link #setAccessibilityLiveRegion(int)}.
2332     */
2333    public static final int ACCESSIBILITY_LIVE_REGION_ASSERTIVE = 0x00000002;
2334
2335    /**
2336     * The default whether the view is important for accessibility.
2337     */
2338    static final int ACCESSIBILITY_LIVE_REGION_DEFAULT = ACCESSIBILITY_LIVE_REGION_NONE;
2339
2340    /**
2341     * Mask for obtaining the bits which specify a view's accessibility live
2342     * region mode.
2343     */
2344    static final int PFLAG2_ACCESSIBILITY_LIVE_REGION_MASK = (ACCESSIBILITY_LIVE_REGION_NONE
2345            | ACCESSIBILITY_LIVE_REGION_POLITE | ACCESSIBILITY_LIVE_REGION_ASSERTIVE)
2346            << PFLAG2_ACCESSIBILITY_LIVE_REGION_SHIFT;
2347
2348    /**
2349     * Flag indicating whether a view has accessibility focus.
2350     */
2351    static final int PFLAG2_ACCESSIBILITY_FOCUSED = 0x04000000;
2352
2353    /**
2354     * Flag whether the accessibility state of the subtree rooted at this view changed.
2355     */
2356    static final int PFLAG2_SUBTREE_ACCESSIBILITY_STATE_CHANGED = 0x08000000;
2357
2358    /**
2359     * Flag indicating whether a view failed the quickReject() check in draw(). This condition
2360     * is used to check whether later changes to the view's transform should invalidate the
2361     * view to force the quickReject test to run again.
2362     */
2363    static final int PFLAG2_VIEW_QUICK_REJECTED = 0x10000000;
2364
2365    /**
2366     * Flag indicating that start/end padding has been resolved into left/right padding
2367     * for use in measurement, layout, drawing, etc. This is set by {@link #resolvePadding()}
2368     * and checked by {@link #measure(int, int)} to determine if padding needs to be resolved
2369     * during measurement. In some special cases this is required such as when an adapter-based
2370     * view measures prospective children without attaching them to a window.
2371     */
2372    static final int PFLAG2_PADDING_RESOLVED = 0x20000000;
2373
2374    /**
2375     * Flag indicating that the start/end drawables has been resolved into left/right ones.
2376     */
2377    static final int PFLAG2_DRAWABLE_RESOLVED = 0x40000000;
2378
2379    /**
2380     * Indicates that the view is tracking some sort of transient state
2381     * that the app should not need to be aware of, but that the framework
2382     * should take special care to preserve.
2383     */
2384    static final int PFLAG2_HAS_TRANSIENT_STATE = 0x80000000;
2385
2386    /**
2387     * Group of bits indicating that RTL properties resolution is done.
2388     */
2389    static final int ALL_RTL_PROPERTIES_RESOLVED = PFLAG2_LAYOUT_DIRECTION_RESOLVED |
2390            PFLAG2_TEXT_DIRECTION_RESOLVED |
2391            PFLAG2_TEXT_ALIGNMENT_RESOLVED |
2392            PFLAG2_PADDING_RESOLVED |
2393            PFLAG2_DRAWABLE_RESOLVED;
2394
2395    // There are a couple of flags left in mPrivateFlags2
2396
2397    /* End of masks for mPrivateFlags2 */
2398
2399    /**
2400     * Masks for mPrivateFlags3, as generated by dumpFlags():
2401     *
2402     * |-------|-------|-------|-------|
2403     *                                 1 PFLAG3_VIEW_IS_ANIMATING_TRANSFORM
2404     *                                1  PFLAG3_VIEW_IS_ANIMATING_ALPHA
2405     *                               1   PFLAG3_IS_LAID_OUT
2406     *                              1    PFLAG3_MEASURE_NEEDED_BEFORE_LAYOUT
2407     *                             1     PFLAG3_CALLED_SUPER
2408     *                            1      PFLAG3_APPLYING_INSETS
2409     *                           1       PFLAG3_FITTING_SYSTEM_WINDOWS
2410     *                          1        PFLAG3_NESTED_SCROLLING_ENABLED
2411     *                         1         PFLAG3_SCROLL_INDICATOR_TOP
2412     *                        1          PFLAG3_SCROLL_INDICATOR_BOTTOM
2413     *                       1           PFLAG3_SCROLL_INDICATOR_LEFT
2414     *                      1            PFLAG3_SCROLL_INDICATOR_RIGHT
2415     *                     1             PFLAG3_SCROLL_INDICATOR_START
2416     *                    1              PFLAG3_SCROLL_INDICATOR_END
2417     *                   1               PFLAG3_ASSIST_BLOCKED
2418     *            1111111                PFLAG3_POINTER_ICON_MASK
2419     * |-------|-------|-------|-------|
2420     */
2421
2422    /**
2423     * Flag indicating that view has a transform animation set on it. This is used to track whether
2424     * an animation is cleared between successive frames, in order to tell the associated
2425     * DisplayList to clear its animation matrix.
2426     */
2427    static final int PFLAG3_VIEW_IS_ANIMATING_TRANSFORM = 0x1;
2428
2429    /**
2430     * Flag indicating that view has an alpha animation set on it. This is used to track whether an
2431     * animation is cleared between successive frames, in order to tell the associated
2432     * DisplayList to restore its alpha value.
2433     */
2434    static final int PFLAG3_VIEW_IS_ANIMATING_ALPHA = 0x2;
2435
2436    /**
2437     * Flag indicating that the view has been through at least one layout since it
2438     * was last attached to a window.
2439     */
2440    static final int PFLAG3_IS_LAID_OUT = 0x4;
2441
2442    /**
2443     * Flag indicating that a call to measure() was skipped and should be done
2444     * instead when layout() is invoked.
2445     */
2446    static final int PFLAG3_MEASURE_NEEDED_BEFORE_LAYOUT = 0x8;
2447
2448    /**
2449     * Flag indicating that an overridden method correctly called down to
2450     * the superclass implementation as required by the API spec.
2451     */
2452    static final int PFLAG3_CALLED_SUPER = 0x10;
2453
2454    /**
2455     * Flag indicating that we're in the process of applying window insets.
2456     */
2457    static final int PFLAG3_APPLYING_INSETS = 0x20;
2458
2459    /**
2460     * Flag indicating that we're in the process of fitting system windows using the old method.
2461     */
2462    static final int PFLAG3_FITTING_SYSTEM_WINDOWS = 0x40;
2463
2464    /**
2465     * Flag indicating that nested scrolling is enabled for this view.
2466     * The view will optionally cooperate with views up its parent chain to allow for
2467     * integrated nested scrolling along the same axis.
2468     */
2469    static final int PFLAG3_NESTED_SCROLLING_ENABLED = 0x80;
2470
2471    /**
2472     * Flag indicating that the bottom scroll indicator should be displayed
2473     * when this view can scroll up.
2474     */
2475    static final int PFLAG3_SCROLL_INDICATOR_TOP = 0x0100;
2476
2477    /**
2478     * Flag indicating that the bottom scroll indicator should be displayed
2479     * when this view can scroll down.
2480     */
2481    static final int PFLAG3_SCROLL_INDICATOR_BOTTOM = 0x0200;
2482
2483    /**
2484     * Flag indicating that the left scroll indicator should be displayed
2485     * when this view can scroll left.
2486     */
2487    static final int PFLAG3_SCROLL_INDICATOR_LEFT = 0x0400;
2488
2489    /**
2490     * Flag indicating that the right scroll indicator should be displayed
2491     * when this view can scroll right.
2492     */
2493    static final int PFLAG3_SCROLL_INDICATOR_RIGHT = 0x0800;
2494
2495    /**
2496     * Flag indicating that the start scroll indicator should be displayed
2497     * when this view can scroll in the start direction.
2498     */
2499    static final int PFLAG3_SCROLL_INDICATOR_START = 0x1000;
2500
2501    /**
2502     * Flag indicating that the end scroll indicator should be displayed
2503     * when this view can scroll in the end direction.
2504     */
2505    static final int PFLAG3_SCROLL_INDICATOR_END = 0x2000;
2506
2507    /* End of masks for mPrivateFlags3 */
2508
2509    static final int DRAG_MASK = PFLAG2_DRAG_CAN_ACCEPT | PFLAG2_DRAG_HOVERED;
2510
2511    static final int SCROLL_INDICATORS_NONE = 0x0000;
2512
2513    /**
2514     * Mask for use with setFlags indicating bits used for indicating which
2515     * scroll indicators are enabled.
2516     */
2517    static final int SCROLL_INDICATORS_PFLAG3_MASK = PFLAG3_SCROLL_INDICATOR_TOP
2518            | PFLAG3_SCROLL_INDICATOR_BOTTOM | PFLAG3_SCROLL_INDICATOR_LEFT
2519            | PFLAG3_SCROLL_INDICATOR_RIGHT | PFLAG3_SCROLL_INDICATOR_START
2520            | PFLAG3_SCROLL_INDICATOR_END;
2521
2522    /**
2523     * Left-shift required to translate between public scroll indicator flags
2524     * and internal PFLAGS3 flags. When used as a right-shift, translates
2525     * PFLAGS3 flags to public flags.
2526     */
2527    static final int SCROLL_INDICATORS_TO_PFLAGS3_LSHIFT = 8;
2528
2529    /** @hide */
2530    @Retention(RetentionPolicy.SOURCE)
2531    @IntDef(flag = true,
2532            value = {
2533                    SCROLL_INDICATOR_TOP,
2534                    SCROLL_INDICATOR_BOTTOM,
2535                    SCROLL_INDICATOR_LEFT,
2536                    SCROLL_INDICATOR_RIGHT,
2537                    SCROLL_INDICATOR_START,
2538                    SCROLL_INDICATOR_END,
2539            })
2540    public @interface ScrollIndicators {}
2541
2542    /**
2543     * Scroll indicator direction for the top edge of the view.
2544     *
2545     * @see #setScrollIndicators(int)
2546     * @see #setScrollIndicators(int, int)
2547     * @see #getScrollIndicators()
2548     */
2549    public static final int SCROLL_INDICATOR_TOP =
2550            PFLAG3_SCROLL_INDICATOR_TOP >> SCROLL_INDICATORS_TO_PFLAGS3_LSHIFT;
2551
2552    /**
2553     * Scroll indicator direction for the bottom edge of the view.
2554     *
2555     * @see #setScrollIndicators(int)
2556     * @see #setScrollIndicators(int, int)
2557     * @see #getScrollIndicators()
2558     */
2559    public static final int SCROLL_INDICATOR_BOTTOM =
2560            PFLAG3_SCROLL_INDICATOR_BOTTOM >> SCROLL_INDICATORS_TO_PFLAGS3_LSHIFT;
2561
2562    /**
2563     * Scroll indicator direction for the left edge of the view.
2564     *
2565     * @see #setScrollIndicators(int)
2566     * @see #setScrollIndicators(int, int)
2567     * @see #getScrollIndicators()
2568     */
2569    public static final int SCROLL_INDICATOR_LEFT =
2570            PFLAG3_SCROLL_INDICATOR_LEFT >> SCROLL_INDICATORS_TO_PFLAGS3_LSHIFT;
2571
2572    /**
2573     * Scroll indicator direction for the right edge of the view.
2574     *
2575     * @see #setScrollIndicators(int)
2576     * @see #setScrollIndicators(int, int)
2577     * @see #getScrollIndicators()
2578     */
2579    public static final int SCROLL_INDICATOR_RIGHT =
2580            PFLAG3_SCROLL_INDICATOR_RIGHT >> SCROLL_INDICATORS_TO_PFLAGS3_LSHIFT;
2581
2582    /**
2583     * Scroll indicator direction for the starting edge of the view.
2584     * <p>
2585     * Resolved according to the view's layout direction, see
2586     * {@link #getLayoutDirection()} for more information.
2587     *
2588     * @see #setScrollIndicators(int)
2589     * @see #setScrollIndicators(int, int)
2590     * @see #getScrollIndicators()
2591     */
2592    public static final int SCROLL_INDICATOR_START =
2593            PFLAG3_SCROLL_INDICATOR_START >> SCROLL_INDICATORS_TO_PFLAGS3_LSHIFT;
2594
2595    /**
2596     * Scroll indicator direction for the ending edge of the view.
2597     * <p>
2598     * Resolved according to the view's layout direction, see
2599     * {@link #getLayoutDirection()} for more information.
2600     *
2601     * @see #setScrollIndicators(int)
2602     * @see #setScrollIndicators(int, int)
2603     * @see #getScrollIndicators()
2604     */
2605    public static final int SCROLL_INDICATOR_END =
2606            PFLAG3_SCROLL_INDICATOR_END >> SCROLL_INDICATORS_TO_PFLAGS3_LSHIFT;
2607
2608    /**
2609     * <p>Indicates that we are allowing {@link ViewStructure} to traverse
2610     * into this view.<p>
2611     */
2612    static final int PFLAG3_ASSIST_BLOCKED = 0x4000;
2613
2614    /**
2615     * The mask for use with private flags indicating bits used for pointer icon shapes.
2616     */
2617    static final int PFLAG3_POINTER_ICON_MASK = 0x7f8000;
2618
2619    /**
2620     * Left-shift used for pointer icon shape values in private flags.
2621     */
2622    static final int PFLAG3_POINTER_ICON_LSHIFT = 15;
2623
2624    /**
2625     * Value indicating {@link PointerIcon.STYLE_NOT_SPECIFIED}.
2626     */
2627    private static final int PFLAG3_POINTER_ICON_NOT_SPECIFIED = 0 << PFLAG3_POINTER_ICON_LSHIFT;
2628
2629    /**
2630     * Value indicating {@link PointerIcon.STYLE_NULL}.
2631     */
2632    private static final int PFLAG3_POINTER_ICON_NULL = 1 << PFLAG3_POINTER_ICON_LSHIFT;
2633
2634    /**
2635     * Value incicating {@link PointerIcon.STYLE_CUSTOM}.
2636     */
2637    private static final int PFLAG3_POINTER_ICON_CUSTOM = 2 << PFLAG3_POINTER_ICON_LSHIFT;
2638
2639    /**
2640     * The base value for other pointer icon shapes.
2641     */
2642    private static final int PFLAG3_POINTER_ICON_VALUE_START = 3 << PFLAG3_POINTER_ICON_LSHIFT;
2643
2644    /**
2645     * Always allow a user to over-scroll this view, provided it is a
2646     * view that can scroll.
2647     *
2648     * @see #getOverScrollMode()
2649     * @see #setOverScrollMode(int)
2650     */
2651    public static final int OVER_SCROLL_ALWAYS = 0;
2652
2653    /**
2654     * Allow a user to over-scroll this view only if the content is large
2655     * enough to meaningfully scroll, provided it is a view that can scroll.
2656     *
2657     * @see #getOverScrollMode()
2658     * @see #setOverScrollMode(int)
2659     */
2660    public static final int OVER_SCROLL_IF_CONTENT_SCROLLS = 1;
2661
2662    /**
2663     * Never allow a user to over-scroll this view.
2664     *
2665     * @see #getOverScrollMode()
2666     * @see #setOverScrollMode(int)
2667     */
2668    public static final int OVER_SCROLL_NEVER = 2;
2669
2670    /**
2671     * Special constant for {@link #setSystemUiVisibility(int)}: View has
2672     * requested the system UI (status bar) to be visible (the default).
2673     *
2674     * @see #setSystemUiVisibility(int)
2675     */
2676    public static final int SYSTEM_UI_FLAG_VISIBLE = 0;
2677
2678    /**
2679     * Flag for {@link #setSystemUiVisibility(int)}: View has requested the
2680     * system UI to enter an unobtrusive "low profile" mode.
2681     *
2682     * <p>This is for use in games, book readers, video players, or any other
2683     * "immersive" application where the usual system chrome is deemed too distracting.
2684     *
2685     * <p>In low profile mode, the status bar and/or navigation icons may dim.
2686     *
2687     * @see #setSystemUiVisibility(int)
2688     */
2689    public static final int SYSTEM_UI_FLAG_LOW_PROFILE = 0x00000001;
2690
2691    /**
2692     * Flag for {@link #setSystemUiVisibility(int)}: View has requested that the
2693     * system navigation be temporarily hidden.
2694     *
2695     * <p>This is an even less obtrusive state than that called for by
2696     * {@link #SYSTEM_UI_FLAG_LOW_PROFILE}; on devices that draw essential navigation controls
2697     * (Home, Back, and the like) on screen, <code>SYSTEM_UI_FLAG_HIDE_NAVIGATION</code> will cause
2698     * those to disappear. This is useful (in conjunction with the
2699     * {@link android.view.WindowManager.LayoutParams#FLAG_FULLSCREEN FLAG_FULLSCREEN} and
2700     * {@link android.view.WindowManager.LayoutParams#FLAG_LAYOUT_IN_SCREEN FLAG_LAYOUT_IN_SCREEN}
2701     * window flags) for displaying content using every last pixel on the display.
2702     *
2703     * <p>There is a limitation: because navigation controls are so important, the least user
2704     * interaction will cause them to reappear immediately.  When this happens, both
2705     * this flag and {@link #SYSTEM_UI_FLAG_FULLSCREEN} will be cleared automatically,
2706     * so that both elements reappear at the same time.
2707     *
2708     * @see #setSystemUiVisibility(int)
2709     */
2710    public static final int SYSTEM_UI_FLAG_HIDE_NAVIGATION = 0x00000002;
2711
2712    /**
2713     * Flag for {@link #setSystemUiVisibility(int)}: View has requested to go
2714     * into the normal fullscreen mode so that its content can take over the screen
2715     * while still allowing the user to interact with the application.
2716     *
2717     * <p>This has the same visual effect as
2718     * {@link android.view.WindowManager.LayoutParams#FLAG_FULLSCREEN
2719     * WindowManager.LayoutParams.FLAG_FULLSCREEN},
2720     * meaning that non-critical screen decorations (such as the status bar) will be
2721     * hidden while the user is in the View's window, focusing the experience on
2722     * that content.  Unlike the window flag, if you are using ActionBar in
2723     * overlay mode with {@link Window#FEATURE_ACTION_BAR_OVERLAY
2724     * Window.FEATURE_ACTION_BAR_OVERLAY}, then enabling this flag will also
2725     * hide the action bar.
2726     *
2727     * <p>This approach to going fullscreen is best used over the window flag when
2728     * it is a transient state -- that is, the application does this at certain
2729     * points in its user interaction where it wants to allow the user to focus
2730     * on content, but not as a continuous state.  For situations where the application
2731     * would like to simply stay full screen the entire time (such as a game that
2732     * wants to take over the screen), the
2733     * {@link android.view.WindowManager.LayoutParams#FLAG_FULLSCREEN window flag}
2734     * is usually a better approach.  The state set here will be removed by the system
2735     * in various situations (such as the user moving to another application) like
2736     * the other system UI states.
2737     *
2738     * <p>When using this flag, the application should provide some easy facility
2739     * for the user to go out of it.  A common example would be in an e-book
2740     * reader, where tapping on the screen brings back whatever screen and UI
2741     * decorations that had been hidden while the user was immersed in reading
2742     * the book.
2743     *
2744     * @see #setSystemUiVisibility(int)
2745     */
2746    public static final int SYSTEM_UI_FLAG_FULLSCREEN = 0x00000004;
2747
2748    /**
2749     * Flag for {@link #setSystemUiVisibility(int)}: When using other layout
2750     * flags, we would like a stable view of the content insets given to
2751     * {@link #fitSystemWindows(Rect)}.  This means that the insets seen there
2752     * will always represent the worst case that the application can expect
2753     * as a continuous state.  In the stock Android UI this is the space for
2754     * the system bar, nav bar, and status bar, but not more transient elements
2755     * such as an input method.
2756     *
2757     * The stable layout your UI sees is based on the system UI modes you can
2758     * switch to.  That is, if you specify {@link #SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN}
2759     * then you will get a stable layout for changes of the
2760     * {@link #SYSTEM_UI_FLAG_FULLSCREEN} mode; if you specify
2761     * {@link #SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN} and
2762     * {@link #SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION}, then you can transition
2763     * to {@link #SYSTEM_UI_FLAG_FULLSCREEN} and {@link #SYSTEM_UI_FLAG_HIDE_NAVIGATION}
2764     * with a stable layout.  (Note that you should avoid using
2765     * {@link #SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION} by itself.)
2766     *
2767     * If you have set the window flag {@link WindowManager.LayoutParams#FLAG_FULLSCREEN}
2768     * to hide the status bar (instead of using {@link #SYSTEM_UI_FLAG_FULLSCREEN}),
2769     * then a hidden status bar will be considered a "stable" state for purposes
2770     * here.  This allows your UI to continually hide the status bar, while still
2771     * using the system UI flags to hide the action bar while still retaining
2772     * a stable layout.  Note that changing the window fullscreen flag will never
2773     * provide a stable layout for a clean transition.
2774     *
2775     * <p>If you are using ActionBar in
2776     * overlay mode with {@link Window#FEATURE_ACTION_BAR_OVERLAY
2777     * Window.FEATURE_ACTION_BAR_OVERLAY}, this flag will also impact the
2778     * insets it adds to those given to the application.
2779     */
2780    public static final int SYSTEM_UI_FLAG_LAYOUT_STABLE = 0x00000100;
2781
2782    /**
2783     * Flag for {@link #setSystemUiVisibility(int)}: View would like its window
2784     * to be laid out as if it has requested
2785     * {@link #SYSTEM_UI_FLAG_HIDE_NAVIGATION}, even if it currently hasn't.  This
2786     * allows it to avoid artifacts when switching in and out of that mode, at
2787     * the expense that some of its user interface may be covered by screen
2788     * decorations when they are shown.  You can perform layout of your inner
2789     * UI elements to account for the navigation system UI through the
2790     * {@link #fitSystemWindows(Rect)} method.
2791     */
2792    public static final int SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION = 0x00000200;
2793
2794    /**
2795     * Flag for {@link #setSystemUiVisibility(int)}: View would like its window
2796     * to be laid out as if it has requested
2797     * {@link #SYSTEM_UI_FLAG_FULLSCREEN}, even if it currently hasn't.  This
2798     * allows it to avoid artifacts when switching in and out of that mode, at
2799     * the expense that some of its user interface may be covered by screen
2800     * decorations when they are shown.  You can perform layout of your inner
2801     * UI elements to account for non-fullscreen system UI through the
2802     * {@link #fitSystemWindows(Rect)} method.
2803     */
2804    public static final int SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN = 0x00000400;
2805
2806    /**
2807     * Flag for {@link #setSystemUiVisibility(int)}: View would like to remain interactive when
2808     * hiding the navigation bar with {@link #SYSTEM_UI_FLAG_HIDE_NAVIGATION}.  If this flag is
2809     * not set, {@link #SYSTEM_UI_FLAG_HIDE_NAVIGATION} will be force cleared by the system on any
2810     * user interaction.
2811     * <p>Since this flag is a modifier for {@link #SYSTEM_UI_FLAG_HIDE_NAVIGATION}, it only
2812     * has an effect when used in combination with that flag.</p>
2813     */
2814    public static final int SYSTEM_UI_FLAG_IMMERSIVE = 0x00000800;
2815
2816    /**
2817     * Flag for {@link #setSystemUiVisibility(int)}: View would like to remain interactive when
2818     * hiding the status bar with {@link #SYSTEM_UI_FLAG_FULLSCREEN} and/or hiding the navigation
2819     * bar with {@link #SYSTEM_UI_FLAG_HIDE_NAVIGATION}.  Use this flag to create an immersive
2820     * experience while also hiding the system bars.  If this flag is not set,
2821     * {@link #SYSTEM_UI_FLAG_HIDE_NAVIGATION} will be force cleared by the system on any user
2822     * interaction, and {@link #SYSTEM_UI_FLAG_FULLSCREEN} will be force-cleared by the system
2823     * if the user swipes from the top of the screen.
2824     * <p>When system bars are hidden in immersive mode, they can be revealed temporarily with
2825     * system gestures, such as swiping from the top of the screen.  These transient system bars
2826     * will overlay app’s content, may have some degree of transparency, and will automatically
2827     * hide after a short timeout.
2828     * </p><p>Since this flag is a modifier for {@link #SYSTEM_UI_FLAG_FULLSCREEN} and
2829     * {@link #SYSTEM_UI_FLAG_HIDE_NAVIGATION}, it only has an effect when used in combination
2830     * with one or both of those flags.</p>
2831     */
2832    public static final int SYSTEM_UI_FLAG_IMMERSIVE_STICKY = 0x00001000;
2833
2834    /**
2835     * Flag for {@link #setSystemUiVisibility(int)}: Requests the status bar to draw in a mode that
2836     * is compatible with light status bar backgrounds.
2837     *
2838     * <p>For this to take effect, the window must request
2839     * {@link android.view.WindowManager.LayoutParams#FLAG_DRAWS_SYSTEM_BAR_BACKGROUNDS
2840     *         FLAG_DRAWS_SYSTEM_BAR_BACKGROUNDS} but not
2841     * {@link android.view.WindowManager.LayoutParams#FLAG_TRANSLUCENT_STATUS
2842     *         FLAG_TRANSLUCENT_STATUS}.
2843     *
2844     * @see android.R.attr#windowLightStatusBar
2845     */
2846    public static final int SYSTEM_UI_FLAG_LIGHT_STATUS_BAR = 0x00002000;
2847
2848    /**
2849     * @deprecated Use {@link #SYSTEM_UI_FLAG_LOW_PROFILE} instead.
2850     */
2851    public static final int STATUS_BAR_HIDDEN = SYSTEM_UI_FLAG_LOW_PROFILE;
2852
2853    /**
2854     * @deprecated Use {@link #SYSTEM_UI_FLAG_VISIBLE} instead.
2855     */
2856    public static final int STATUS_BAR_VISIBLE = SYSTEM_UI_FLAG_VISIBLE;
2857
2858    /**
2859     * @hide
2860     *
2861     * NOTE: This flag may only be used in subtreeSystemUiVisibility. It is masked
2862     * out of the public fields to keep the undefined bits out of the developer's way.
2863     *
2864     * Flag to make the status bar not expandable.  Unless you also
2865     * set {@link #STATUS_BAR_DISABLE_NOTIFICATION_ICONS}, new notifications will continue to show.
2866     */
2867    public static final int STATUS_BAR_DISABLE_EXPAND = 0x00010000;
2868
2869    /**
2870     * @hide
2871     *
2872     * NOTE: This flag may only be used in subtreeSystemUiVisibility. It is masked
2873     * out of the public fields to keep the undefined bits out of the developer's way.
2874     *
2875     * Flag to hide notification icons and scrolling ticker text.
2876     */
2877    public static final int STATUS_BAR_DISABLE_NOTIFICATION_ICONS = 0x00020000;
2878
2879    /**
2880     * @hide
2881     *
2882     * NOTE: This flag may only be used in subtreeSystemUiVisibility. It is masked
2883     * out of the public fields to keep the undefined bits out of the developer's way.
2884     *
2885     * Flag to disable incoming notification alerts.  This will not block
2886     * icons, but it will block sound, vibrating and other visual or aural notifications.
2887     */
2888    public static final int STATUS_BAR_DISABLE_NOTIFICATION_ALERTS = 0x00040000;
2889
2890    /**
2891     * @hide
2892     *
2893     * NOTE: This flag may only be used in subtreeSystemUiVisibility. It is masked
2894     * out of the public fields to keep the undefined bits out of the developer's way.
2895     *
2896     * Flag to hide only the scrolling ticker.  Note that
2897     * {@link #STATUS_BAR_DISABLE_NOTIFICATION_ICONS} implies
2898     * {@link #STATUS_BAR_DISABLE_NOTIFICATION_TICKER}.
2899     */
2900    public static final int STATUS_BAR_DISABLE_NOTIFICATION_TICKER = 0x00080000;
2901
2902    /**
2903     * @hide
2904     *
2905     * NOTE: This flag may only be used in subtreeSystemUiVisibility. It is masked
2906     * out of the public fields to keep the undefined bits out of the developer's way.
2907     *
2908     * Flag to hide the center system info area.
2909     */
2910    public static final int STATUS_BAR_DISABLE_SYSTEM_INFO = 0x00100000;
2911
2912    /**
2913     * @hide
2914     *
2915     * NOTE: This flag may only be used in subtreeSystemUiVisibility. It is masked
2916     * out of the public fields to keep the undefined bits out of the developer's way.
2917     *
2918     * Flag to hide only the home button.  Don't use this
2919     * unless you're a special part of the system UI (i.e., setup wizard, keyguard).
2920     */
2921    public static final int STATUS_BAR_DISABLE_HOME = 0x00200000;
2922
2923    /**
2924     * @hide
2925     *
2926     * NOTE: This flag may only be used in subtreeSystemUiVisibility. It is masked
2927     * out of the public fields to keep the undefined bits out of the developer's way.
2928     *
2929     * Flag to hide only the back button. Don't use this
2930     * unless you're a special part of the system UI (i.e., setup wizard, keyguard).
2931     */
2932    public static final int STATUS_BAR_DISABLE_BACK = 0x00400000;
2933
2934    /**
2935     * @hide
2936     *
2937     * NOTE: This flag may only be used in subtreeSystemUiVisibility. It is masked
2938     * out of the public fields to keep the undefined bits out of the developer's way.
2939     *
2940     * Flag to hide only the clock.  You might use this if your activity has
2941     * its own clock making the status bar's clock redundant.
2942     */
2943    public static final int STATUS_BAR_DISABLE_CLOCK = 0x00800000;
2944
2945    /**
2946     * @hide
2947     *
2948     * NOTE: This flag may only be used in subtreeSystemUiVisibility. It is masked
2949     * out of the public fields to keep the undefined bits out of the developer's way.
2950     *
2951     * Flag to hide only the recent apps button. Don't use this
2952     * unless you're a special part of the system UI (i.e., setup wizard, keyguard).
2953     */
2954    public static final int STATUS_BAR_DISABLE_RECENT = 0x01000000;
2955
2956    /**
2957     * @hide
2958     *
2959     * NOTE: This flag may only be used in subtreeSystemUiVisibility. It is masked
2960     * out of the public fields to keep the undefined bits out of the developer's way.
2961     *
2962     * Flag to disable the global search gesture. Don't use this
2963     * unless you're a special part of the system UI (i.e., setup wizard, keyguard).
2964     */
2965    public static final int STATUS_BAR_DISABLE_SEARCH = 0x02000000;
2966
2967    /**
2968     * @hide
2969     *
2970     * NOTE: This flag may only be used in subtreeSystemUiVisibility. It is masked
2971     * out of the public fields to keep the undefined bits out of the developer's way.
2972     *
2973     * Flag to specify that the status bar is displayed in transient mode.
2974     */
2975    public static final int STATUS_BAR_TRANSIENT = 0x04000000;
2976
2977    /**
2978     * @hide
2979     *
2980     * NOTE: This flag may only be used in subtreeSystemUiVisibility. It is masked
2981     * out of the public fields to keep the undefined bits out of the developer's way.
2982     *
2983     * Flag to specify that the navigation bar is displayed in transient mode.
2984     */
2985    public static final int NAVIGATION_BAR_TRANSIENT = 0x08000000;
2986
2987    /**
2988     * @hide
2989     *
2990     * NOTE: This flag may only be used in subtreeSystemUiVisibility. It is masked
2991     * out of the public fields to keep the undefined bits out of the developer's way.
2992     *
2993     * Flag to specify that the hidden status bar would like to be shown.
2994     */
2995    public static final int STATUS_BAR_UNHIDE = 0x10000000;
2996
2997    /**
2998     * @hide
2999     *
3000     * NOTE: This flag may only be used in subtreeSystemUiVisibility. It is masked
3001     * out of the public fields to keep the undefined bits out of the developer's way.
3002     *
3003     * Flag to specify that the hidden navigation bar would like to be shown.
3004     */
3005    public static final int NAVIGATION_BAR_UNHIDE = 0x20000000;
3006
3007    /**
3008     * @hide
3009     *
3010     * NOTE: This flag may only be used in subtreeSystemUiVisibility. It is masked
3011     * out of the public fields to keep the undefined bits out of the developer's way.
3012     *
3013     * Flag to specify that the status bar is displayed in translucent mode.
3014     */
3015    public static final int STATUS_BAR_TRANSLUCENT = 0x40000000;
3016
3017    /**
3018     * @hide
3019     *
3020     * NOTE: This flag may only be used in subtreeSystemUiVisibility. It is masked
3021     * out of the public fields to keep the undefined bits out of the developer's way.
3022     *
3023     * Flag to specify that the navigation bar is displayed in translucent mode.
3024     */
3025    public static final int NAVIGATION_BAR_TRANSLUCENT = 0x80000000;
3026
3027    /**
3028     * @hide
3029     *
3030     * Whether Recents is visible or not.
3031     */
3032    public static final int RECENT_APPS_VISIBLE = 0x00004000;
3033
3034    /**
3035     * @hide
3036     *
3037     * Makes system ui transparent.
3038     */
3039    public static final int SYSTEM_UI_TRANSPARENT = 0x00008000;
3040
3041    /**
3042     * @hide
3043     */
3044    public static final int PUBLIC_STATUS_BAR_VISIBILITY_MASK = 0x00003FFF;
3045
3046    /**
3047     * These are the system UI flags that can be cleared by events outside
3048     * of an application.  Currently this is just the ability to tap on the
3049     * screen while hiding the navigation bar to have it return.
3050     * @hide
3051     */
3052    public static final int SYSTEM_UI_CLEARABLE_FLAGS =
3053            SYSTEM_UI_FLAG_LOW_PROFILE | SYSTEM_UI_FLAG_HIDE_NAVIGATION
3054            | SYSTEM_UI_FLAG_FULLSCREEN;
3055
3056    /**
3057     * Flags that can impact the layout in relation to system UI.
3058     */
3059    public static final int SYSTEM_UI_LAYOUT_FLAGS =
3060            SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION
3061            | SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN;
3062
3063    /** @hide */
3064    @IntDef(flag = true,
3065            value = { FIND_VIEWS_WITH_TEXT, FIND_VIEWS_WITH_CONTENT_DESCRIPTION })
3066    @Retention(RetentionPolicy.SOURCE)
3067    public @interface FindViewFlags {}
3068
3069    /**
3070     * Find views that render the specified text.
3071     *
3072     * @see #findViewsWithText(ArrayList, CharSequence, int)
3073     */
3074    public static final int FIND_VIEWS_WITH_TEXT = 0x00000001;
3075
3076    /**
3077     * Find find views that contain the specified content description.
3078     *
3079     * @see #findViewsWithText(ArrayList, CharSequence, int)
3080     */
3081    public static final int FIND_VIEWS_WITH_CONTENT_DESCRIPTION = 0x00000002;
3082
3083    /**
3084     * Find views that contain {@link AccessibilityNodeProvider}. Such
3085     * a View is a root of virtual view hierarchy and may contain the searched
3086     * text. If this flag is set Views with providers are automatically
3087     * added and it is a responsibility of the client to call the APIs of
3088     * the provider to determine whether the virtual tree rooted at this View
3089     * contains the text, i.e. getting the list of {@link AccessibilityNodeInfo}s
3090     * representing the virtual views with this text.
3091     *
3092     * @see #findViewsWithText(ArrayList, CharSequence, int)
3093     *
3094     * @hide
3095     */
3096    public static final int FIND_VIEWS_WITH_ACCESSIBILITY_NODE_PROVIDERS = 0x00000004;
3097
3098    /**
3099     * The undefined cursor position.
3100     *
3101     * @hide
3102     */
3103    public static final int ACCESSIBILITY_CURSOR_POSITION_UNDEFINED = -1;
3104
3105    /**
3106     * Indicates that the screen has changed state and is now off.
3107     *
3108     * @see #onScreenStateChanged(int)
3109     */
3110    public static final int SCREEN_STATE_OFF = 0x0;
3111
3112    /**
3113     * Indicates that the screen has changed state and is now on.
3114     *
3115     * @see #onScreenStateChanged(int)
3116     */
3117    public static final int SCREEN_STATE_ON = 0x1;
3118
3119    /**
3120     * Indicates no axis of view scrolling.
3121     */
3122    public static final int SCROLL_AXIS_NONE = 0;
3123
3124    /**
3125     * Indicates scrolling along the horizontal axis.
3126     */
3127    public static final int SCROLL_AXIS_HORIZONTAL = 1 << 0;
3128
3129    /**
3130     * Indicates scrolling along the vertical axis.
3131     */
3132    public static final int SCROLL_AXIS_VERTICAL = 1 << 1;
3133
3134    /**
3135     * Controls the over-scroll mode for this view.
3136     * See {@link #overScrollBy(int, int, int, int, int, int, int, int, boolean)},
3137     * {@link #OVER_SCROLL_ALWAYS}, {@link #OVER_SCROLL_IF_CONTENT_SCROLLS},
3138     * and {@link #OVER_SCROLL_NEVER}.
3139     */
3140    private int mOverScrollMode;
3141
3142    /**
3143     * The parent this view is attached to.
3144     * {@hide}
3145     *
3146     * @see #getParent()
3147     */
3148    protected ViewParent mParent;
3149
3150    /**
3151     * {@hide}
3152     */
3153    AttachInfo mAttachInfo;
3154
3155    /**
3156     * {@hide}
3157     */
3158    @ViewDebug.ExportedProperty(flagMapping = {
3159        @ViewDebug.FlagToString(mask = PFLAG_FORCE_LAYOUT, equals = PFLAG_FORCE_LAYOUT,
3160                name = "FORCE_LAYOUT"),
3161        @ViewDebug.FlagToString(mask = PFLAG_LAYOUT_REQUIRED, equals = PFLAG_LAYOUT_REQUIRED,
3162                name = "LAYOUT_REQUIRED"),
3163        @ViewDebug.FlagToString(mask = PFLAG_DRAWING_CACHE_VALID, equals = PFLAG_DRAWING_CACHE_VALID,
3164            name = "DRAWING_CACHE_INVALID", outputIf = false),
3165        @ViewDebug.FlagToString(mask = PFLAG_DRAWN, equals = PFLAG_DRAWN, name = "DRAWN", outputIf = true),
3166        @ViewDebug.FlagToString(mask = PFLAG_DRAWN, equals = PFLAG_DRAWN, name = "NOT_DRAWN", outputIf = false),
3167        @ViewDebug.FlagToString(mask = PFLAG_DIRTY_MASK, equals = PFLAG_DIRTY_OPAQUE, name = "DIRTY_OPAQUE"),
3168        @ViewDebug.FlagToString(mask = PFLAG_DIRTY_MASK, equals = PFLAG_DIRTY, name = "DIRTY")
3169    }, formatToHexString = true)
3170    int mPrivateFlags;
3171    int mPrivateFlags2;
3172    int mPrivateFlags3;
3173
3174    /**
3175     * This view's request for the visibility of the status bar.
3176     * @hide
3177     */
3178    @ViewDebug.ExportedProperty(flagMapping = {
3179        @ViewDebug.FlagToString(mask = SYSTEM_UI_FLAG_LOW_PROFILE,
3180                                equals = SYSTEM_UI_FLAG_LOW_PROFILE,
3181                                name = "SYSTEM_UI_FLAG_LOW_PROFILE", outputIf = true),
3182        @ViewDebug.FlagToString(mask = SYSTEM_UI_FLAG_HIDE_NAVIGATION,
3183                                equals = SYSTEM_UI_FLAG_HIDE_NAVIGATION,
3184                                name = "SYSTEM_UI_FLAG_HIDE_NAVIGATION", outputIf = true),
3185        @ViewDebug.FlagToString(mask = PUBLIC_STATUS_BAR_VISIBILITY_MASK,
3186                                equals = SYSTEM_UI_FLAG_VISIBLE,
3187                                name = "SYSTEM_UI_FLAG_VISIBLE", outputIf = true)
3188    }, formatToHexString = true)
3189    int mSystemUiVisibility;
3190
3191    /**
3192     * Reference count for transient state.
3193     * @see #setHasTransientState(boolean)
3194     */
3195    int mTransientStateCount = 0;
3196
3197    /**
3198     * Count of how many windows this view has been attached to.
3199     */
3200    int mWindowAttachCount;
3201
3202    /**
3203     * The layout parameters associated with this view and used by the parent
3204     * {@link android.view.ViewGroup} to determine how this view should be
3205     * laid out.
3206     * {@hide}
3207     */
3208    protected ViewGroup.LayoutParams mLayoutParams;
3209
3210    /**
3211     * The view flags hold various views states.
3212     * {@hide}
3213     */
3214    @ViewDebug.ExportedProperty(formatToHexString = true)
3215    int mViewFlags;
3216
3217    static class TransformationInfo {
3218        /**
3219         * The transform matrix for the View. This transform is calculated internally
3220         * based on the translation, rotation, and scale properties.
3221         *
3222         * Do *not* use this variable directly; instead call getMatrix(), which will
3223         * load the value from the View's RenderNode.
3224         */
3225        private final Matrix mMatrix = new Matrix();
3226
3227        /**
3228         * The inverse transform matrix for the View. This transform is calculated
3229         * internally based on the translation, rotation, and scale properties.
3230         *
3231         * Do *not* use this variable directly; instead call getInverseMatrix(),
3232         * which will load the value from the View's RenderNode.
3233         */
3234        private Matrix mInverseMatrix;
3235
3236        /**
3237         * The opacity of the View. This is a value from 0 to 1, where 0 means
3238         * completely transparent and 1 means completely opaque.
3239         */
3240        @ViewDebug.ExportedProperty
3241        float mAlpha = 1f;
3242
3243        /**
3244         * The opacity of the view as manipulated by the Fade transition. This is a hidden
3245         * property only used by transitions, which is composited with the other alpha
3246         * values to calculate the final visual alpha value.
3247         */
3248        float mTransitionAlpha = 1f;
3249    }
3250
3251    TransformationInfo mTransformationInfo;
3252
3253    /**
3254     * Current clip bounds. to which all drawing of this view are constrained.
3255     */
3256    Rect mClipBounds = null;
3257
3258    private boolean mLastIsOpaque;
3259
3260    /**
3261     * The distance in pixels from the left edge of this view's parent
3262     * to the left edge of this view.
3263     * {@hide}
3264     */
3265    @ViewDebug.ExportedProperty(category = "layout")
3266    protected int mLeft;
3267    /**
3268     * The distance in pixels from the left edge of this view's parent
3269     * to the right edge of this view.
3270     * {@hide}
3271     */
3272    @ViewDebug.ExportedProperty(category = "layout")
3273    protected int mRight;
3274    /**
3275     * The distance in pixels from the top edge of this view's parent
3276     * to the top edge of this view.
3277     * {@hide}
3278     */
3279    @ViewDebug.ExportedProperty(category = "layout")
3280    protected int mTop;
3281    /**
3282     * The distance in pixels from the top edge of this view's parent
3283     * to the bottom edge of this view.
3284     * {@hide}
3285     */
3286    @ViewDebug.ExportedProperty(category = "layout")
3287    protected int mBottom;
3288
3289    /**
3290     * The offset, in pixels, by which the content of this view is scrolled
3291     * horizontally.
3292     * {@hide}
3293     */
3294    @ViewDebug.ExportedProperty(category = "scrolling")
3295    protected int mScrollX;
3296    /**
3297     * The offset, in pixels, by which the content of this view is scrolled
3298     * vertically.
3299     * {@hide}
3300     */
3301    @ViewDebug.ExportedProperty(category = "scrolling")
3302    protected int mScrollY;
3303
3304    /**
3305     * The left padding in pixels, that is the distance in pixels between the
3306     * left edge of this view and the left edge of its content.
3307     * {@hide}
3308     */
3309    @ViewDebug.ExportedProperty(category = "padding")
3310    protected int mPaddingLeft = 0;
3311    /**
3312     * The right padding in pixels, that is the distance in pixels between the
3313     * right edge of this view and the right edge of its content.
3314     * {@hide}
3315     */
3316    @ViewDebug.ExportedProperty(category = "padding")
3317    protected int mPaddingRight = 0;
3318    /**
3319     * The top padding in pixels, that is the distance in pixels between the
3320     * top edge of this view and the top edge of its content.
3321     * {@hide}
3322     */
3323    @ViewDebug.ExportedProperty(category = "padding")
3324    protected int mPaddingTop;
3325    /**
3326     * The bottom padding in pixels, that is the distance in pixels between the
3327     * bottom edge of this view and the bottom edge of its content.
3328     * {@hide}
3329     */
3330    @ViewDebug.ExportedProperty(category = "padding")
3331    protected int mPaddingBottom;
3332
3333    /**
3334     * The layout insets in pixels, that is the distance in pixels between the
3335     * visible edges of this view its bounds.
3336     */
3337    private Insets mLayoutInsets;
3338
3339    /**
3340     * Briefly describes the view and is primarily used for accessibility support.
3341     */
3342    private CharSequence mContentDescription;
3343
3344    /**
3345     * Specifies the id of a view for which this view serves as a label for
3346     * accessibility purposes.
3347     */
3348    private int mLabelForId = View.NO_ID;
3349
3350    /**
3351     * Predicate for matching labeled view id with its label for
3352     * accessibility purposes.
3353     */
3354    private MatchLabelForPredicate mMatchLabelForPredicate;
3355
3356    /**
3357     * Specifies a view before which this one is visited in accessibility traversal.
3358     */
3359    private int mAccessibilityTraversalBeforeId = NO_ID;
3360
3361    /**
3362     * Specifies a view after which this one is visited in accessibility traversal.
3363     */
3364    private int mAccessibilityTraversalAfterId = NO_ID;
3365
3366    /**
3367     * Predicate for matching a view by its id.
3368     */
3369    private MatchIdPredicate mMatchIdPredicate;
3370
3371    /**
3372     * Cache the paddingRight set by the user to append to the scrollbar's size.
3373     *
3374     * @hide
3375     */
3376    @ViewDebug.ExportedProperty(category = "padding")
3377    protected int mUserPaddingRight;
3378
3379    /**
3380     * Cache the paddingBottom set by the user to append to the scrollbar's size.
3381     *
3382     * @hide
3383     */
3384    @ViewDebug.ExportedProperty(category = "padding")
3385    protected int mUserPaddingBottom;
3386
3387    /**
3388     * Cache the paddingLeft set by the user to append to the scrollbar's size.
3389     *
3390     * @hide
3391     */
3392    @ViewDebug.ExportedProperty(category = "padding")
3393    protected int mUserPaddingLeft;
3394
3395    /**
3396     * Cache the paddingStart set by the user to append to the scrollbar's size.
3397     *
3398     */
3399    @ViewDebug.ExportedProperty(category = "padding")
3400    int mUserPaddingStart;
3401
3402    /**
3403     * Cache the paddingEnd set by the user to append to the scrollbar's size.
3404     *
3405     */
3406    @ViewDebug.ExportedProperty(category = "padding")
3407    int mUserPaddingEnd;
3408
3409    /**
3410     * Cache initial left padding.
3411     *
3412     * @hide
3413     */
3414    int mUserPaddingLeftInitial;
3415
3416    /**
3417     * Cache initial right padding.
3418     *
3419     * @hide
3420     */
3421    int mUserPaddingRightInitial;
3422
3423    /**
3424     * Default undefined padding
3425     */
3426    private static final int UNDEFINED_PADDING = Integer.MIN_VALUE;
3427
3428    /**
3429     * Cache if a left padding has been defined
3430     */
3431    private boolean mLeftPaddingDefined = false;
3432
3433    /**
3434     * Cache if a right padding has been defined
3435     */
3436    private boolean mRightPaddingDefined = false;
3437
3438    /**
3439     * @hide
3440     */
3441    int mOldWidthMeasureSpec = Integer.MIN_VALUE;
3442    /**
3443     * @hide
3444     */
3445    int mOldHeightMeasureSpec = Integer.MIN_VALUE;
3446
3447    private LongSparseLongArray mMeasureCache;
3448
3449    @ViewDebug.ExportedProperty(deepExport = true, prefix = "bg_")
3450    private Drawable mBackground;
3451    private TintInfo mBackgroundTint;
3452
3453    @ViewDebug.ExportedProperty(deepExport = true, prefix = "fg_")
3454    private ForegroundInfo mForegroundInfo;
3455
3456    private Drawable mScrollIndicatorDrawable;
3457
3458    /**
3459     * RenderNode used for backgrounds.
3460     * <p>
3461     * When non-null and valid, this is expected to contain an up-to-date copy
3462     * of the background drawable. It is cleared on temporary detach, and reset
3463     * on cleanup.
3464     */
3465    private RenderNode mBackgroundRenderNode;
3466
3467    private int mBackgroundResource;
3468    private boolean mBackgroundSizeChanged;
3469
3470    private String mTransitionName;
3471
3472    static class TintInfo {
3473        ColorStateList mTintList;
3474        PorterDuff.Mode mTintMode;
3475        boolean mHasTintMode;
3476        boolean mHasTintList;
3477    }
3478
3479    private static class ForegroundInfo {
3480        private Drawable mDrawable;
3481        private TintInfo mTintInfo;
3482        private int mGravity = Gravity.FILL;
3483        private boolean mInsidePadding = true;
3484        private boolean mBoundsChanged = true;
3485        private final Rect mSelfBounds = new Rect();
3486        private final Rect mOverlayBounds = new Rect();
3487    }
3488
3489    static class ListenerInfo {
3490        /**
3491         * Listener used to dispatch focus change events.
3492         * This field should be made private, so it is hidden from the SDK.
3493         * {@hide}
3494         */
3495        protected OnFocusChangeListener mOnFocusChangeListener;
3496
3497        /**
3498         * Listeners for layout change events.
3499         */
3500        private ArrayList<OnLayoutChangeListener> mOnLayoutChangeListeners;
3501
3502        protected OnScrollChangeListener mOnScrollChangeListener;
3503
3504        /**
3505         * Listeners for attach events.
3506         */
3507        private CopyOnWriteArrayList<OnAttachStateChangeListener> mOnAttachStateChangeListeners;
3508
3509        /**
3510         * Listener used to dispatch click events.
3511         * This field should be made private, so it is hidden from the SDK.
3512         * {@hide}
3513         */
3514        public OnClickListener mOnClickListener;
3515
3516        /**
3517         * Listener used to dispatch long click events.
3518         * This field should be made private, so it is hidden from the SDK.
3519         * {@hide}
3520         */
3521        protected OnLongClickListener mOnLongClickListener;
3522
3523        /**
3524         * Listener used to dispatch context click events. This field should be made private, so it
3525         * is hidden from the SDK.
3526         * {@hide}
3527         */
3528        protected OnContextClickListener mOnContextClickListener;
3529
3530        /**
3531         * Listener used to build the context menu.
3532         * This field should be made private, so it is hidden from the SDK.
3533         * {@hide}
3534         */
3535        protected OnCreateContextMenuListener mOnCreateContextMenuListener;
3536
3537        private OnKeyListener mOnKeyListener;
3538
3539        private OnTouchListener mOnTouchListener;
3540
3541        private OnHoverListener mOnHoverListener;
3542
3543        private OnGenericMotionListener mOnGenericMotionListener;
3544
3545        private OnDragListener mOnDragListener;
3546
3547        private OnSystemUiVisibilityChangeListener mOnSystemUiVisibilityChangeListener;
3548
3549        OnApplyWindowInsetsListener mOnApplyWindowInsetsListener;
3550    }
3551
3552    ListenerInfo mListenerInfo;
3553
3554    /**
3555     * The application environment this view lives in.
3556     * This field should be made private, so it is hidden from the SDK.
3557     * {@hide}
3558     */
3559    @ViewDebug.ExportedProperty(deepExport = true)
3560    protected Context mContext;
3561
3562    private final Resources mResources;
3563
3564    private ScrollabilityCache mScrollCache;
3565
3566    private int[] mDrawableState = null;
3567
3568    ViewOutlineProvider mOutlineProvider = ViewOutlineProvider.BACKGROUND;
3569
3570    /**
3571     * Animator that automatically runs based on state changes.
3572     */
3573    private StateListAnimator mStateListAnimator;
3574
3575    /**
3576     * When this view has focus and the next focus is {@link #FOCUS_LEFT},
3577     * the user may specify which view to go to next.
3578     */
3579    private int mNextFocusLeftId = View.NO_ID;
3580
3581    /**
3582     * When this view has focus and the next focus is {@link #FOCUS_RIGHT},
3583     * the user may specify which view to go to next.
3584     */
3585    private int mNextFocusRightId = View.NO_ID;
3586
3587    /**
3588     * When this view has focus and the next focus is {@link #FOCUS_UP},
3589     * the user may specify which view to go to next.
3590     */
3591    private int mNextFocusUpId = View.NO_ID;
3592
3593    /**
3594     * When this view has focus and the next focus is {@link #FOCUS_DOWN},
3595     * the user may specify which view to go to next.
3596     */
3597    private int mNextFocusDownId = View.NO_ID;
3598
3599    /**
3600     * When this view has focus and the next focus is {@link #FOCUS_FORWARD},
3601     * the user may specify which view to go to next.
3602     */
3603    int mNextFocusForwardId = View.NO_ID;
3604
3605    private CheckForLongPress mPendingCheckForLongPress;
3606    private CheckForTap mPendingCheckForTap = null;
3607    private PerformClick mPerformClick;
3608    private SendViewScrolledAccessibilityEvent mSendViewScrolledAccessibilityEvent;
3609
3610    private UnsetPressedState mUnsetPressedState;
3611
3612    /**
3613     * Whether the long press's action has been invoked.  The tap's action is invoked on the
3614     * up event while a long press is invoked as soon as the long press duration is reached, so
3615     * a long press could be performed before the tap is checked, in which case the tap's action
3616     * should not be invoked.
3617     */
3618    private boolean mHasPerformedLongPress;
3619
3620    /**
3621     * Whether a context click button is currently pressed down. This is true when the stylus is
3622     * touching the screen and the primary button has been pressed, or if a mouse's right button is
3623     * pressed. This is false once the button is released or if the stylus has been lifted.
3624     */
3625    private boolean mInContextButtonPress;
3626
3627    /**
3628     * Whether the next up event should be ignored for the purposes of gesture recognition. This is
3629     * true after a stylus button press has occured, when the next up event should not be recognized
3630     * as a tap.
3631     */
3632    private boolean mIgnoreNextUpEvent;
3633
3634    /**
3635     * The minimum height of the view. We'll try our best to have the height
3636     * of this view to at least this amount.
3637     */
3638    @ViewDebug.ExportedProperty(category = "measurement")
3639    private int mMinHeight;
3640
3641    /**
3642     * The minimum width of the view. We'll try our best to have the width
3643     * of this view to at least this amount.
3644     */
3645    @ViewDebug.ExportedProperty(category = "measurement")
3646    private int mMinWidth;
3647
3648    /**
3649     * The delegate to handle touch events that are physically in this view
3650     * but should be handled by another view.
3651     */
3652    private TouchDelegate mTouchDelegate = null;
3653
3654    /**
3655     * Solid color to use as a background when creating the drawing cache. Enables
3656     * the cache to use 16 bit bitmaps instead of 32 bit.
3657     */
3658    private int mDrawingCacheBackgroundColor = 0;
3659
3660    /**
3661     * Special tree observer used when mAttachInfo is null.
3662     */
3663    private ViewTreeObserver mFloatingTreeObserver;
3664
3665    /**
3666     * Cache the touch slop from the context that created the view.
3667     */
3668    private int mTouchSlop;
3669
3670    /**
3671     * Object that handles automatic animation of view properties.
3672     */
3673    private ViewPropertyAnimator mAnimator = null;
3674
3675    /**
3676     * Flag indicating that a drag can cross window boundaries.  When
3677     * {@link #startDrag(ClipData, DragShadowBuilder, Object, int)} is called
3678     * with this flag set, all visible applications will be able to participate
3679     * in the drag operation and receive the dragged content.
3680     *
3681     * If this is the only flag set, then the drag recipient will only have access to text data
3682     * and intents contained in the {@link ClipData} object. Access to URIs contained in the
3683     * {@link ClipData} is determined by other DRAG_FLAG_GLOBAL_* flags.
3684     */
3685    public static final int DRAG_FLAG_GLOBAL = 1 << 8;  // 256
3686
3687    /**
3688     * When this flag is used with {@link #DRAG_FLAG_GLOBAL}, the drag recipient will be able to
3689     * request read access to the content URI(s) contained in the {@link ClipData} object.
3690     * @see android.content.Intent.FLAG_GRANT_READ_URI_PERMISSION
3691     */
3692    public static final int DRAG_FLAG_GLOBAL_URI_READ = Intent.FLAG_GRANT_READ_URI_PERMISSION;
3693
3694    /**
3695     * When this flag is used with {@link #DRAG_FLAG_GLOBAL}, the drag recipient will be able to
3696     * request write access to the content URI(s) contained in the {@link ClipData} object.
3697     * @see android.content.Intent.FLAG_GRANT_WRITE_URI_PERMISSION
3698     */
3699    public static final int DRAG_FLAG_GLOBAL_URI_WRITE = Intent.FLAG_GRANT_WRITE_URI_PERMISSION;
3700
3701    /**
3702     * When this flag is used with {@link #DRAG_FLAG_GLOBAL_URI_READ} and/or {@link
3703     * #DRAG_FLAG_GLOBAL_URI_WRITE}, the URI permission grant can be persisted across device
3704     * reboots until explicitly revoked with
3705     * {@link android.content.Context#revokeUriPermission(Uri,int) Context.revokeUriPermission}.
3706     * @see android.content.Intent.FLAG_GRANT_PERSISTABLE_URI_PERMISSION
3707     */
3708    public static final int DRAG_FLAG_GLOBAL_PERSISTABLE_URI_PERMISSION =
3709            Intent.FLAG_GRANT_PERSISTABLE_URI_PERMISSION;
3710
3711    /**
3712     * When this flag is used with {@link #DRAG_FLAG_GLOBAL_URI_READ} and/or {@link
3713     * #DRAG_FLAG_GLOBAL_URI_WRITE}, the URI permission grant applies to any URI that is a prefix
3714     * match against the original granted URI.
3715     * @see android.content.Intent.FLAG_GRANT_PREFIX_URI_PERMISSION
3716     */
3717    public static final int DRAG_FLAG_GLOBAL_PREFIX_URI_PERMISSION =
3718            Intent.FLAG_GRANT_PREFIX_URI_PERMISSION;
3719
3720    /**
3721     * Flag indicating that the drag shadow will be opaque.  When
3722     * {@link #startDrag(ClipData, DragShadowBuilder, Object, int)} is called
3723     * with this flag set, the drag shadow will be opaque, otherwise, it will be semitransparent.
3724     */
3725    public static final int DRAG_FLAG_OPAQUE = 1 << 9;
3726
3727    /**
3728     * Vertical scroll factor cached by {@link #getVerticalScrollFactor}.
3729     */
3730    private float mVerticalScrollFactor;
3731
3732    /**
3733     * Position of the vertical scroll bar.
3734     */
3735    private int mVerticalScrollbarPosition;
3736
3737    /**
3738     * Position the scroll bar at the default position as determined by the system.
3739     */
3740    public static final int SCROLLBAR_POSITION_DEFAULT = 0;
3741
3742    /**
3743     * Position the scroll bar along the left edge.
3744     */
3745    public static final int SCROLLBAR_POSITION_LEFT = 1;
3746
3747    /**
3748     * Position the scroll bar along the right edge.
3749     */
3750    public static final int SCROLLBAR_POSITION_RIGHT = 2;
3751
3752    /**
3753     * Indicates that the view does not have a layer.
3754     *
3755     * @see #getLayerType()
3756     * @see #setLayerType(int, android.graphics.Paint)
3757     * @see #LAYER_TYPE_SOFTWARE
3758     * @see #LAYER_TYPE_HARDWARE
3759     */
3760    public static final int LAYER_TYPE_NONE = 0;
3761
3762    /**
3763     * <p>Indicates that the view has a software layer. A software layer is backed
3764     * by a bitmap and causes the view to be rendered using Android's software
3765     * rendering pipeline, even if hardware acceleration is enabled.</p>
3766     *
3767     * <p>Software layers have various usages:</p>
3768     * <p>When the application is not using hardware acceleration, a software layer
3769     * is useful to apply a specific color filter and/or blending mode and/or
3770     * translucency to a view and all its children.</p>
3771     * <p>When the application is using hardware acceleration, a software layer
3772     * is useful to render drawing primitives not supported by the hardware
3773     * accelerated pipeline. It can also be used to cache a complex view tree
3774     * into a texture and reduce the complexity of drawing operations. For instance,
3775     * when animating a complex view tree with a translation, a software layer can
3776     * be used to render the view tree only once.</p>
3777     * <p>Software layers should be avoided when the affected view tree updates
3778     * often. Every update will require to re-render the software layer, which can
3779     * potentially be slow (particularly when hardware acceleration is turned on
3780     * since the layer will have to be uploaded into a hardware texture after every
3781     * update.)</p>
3782     *
3783     * @see #getLayerType()
3784     * @see #setLayerType(int, android.graphics.Paint)
3785     * @see #LAYER_TYPE_NONE
3786     * @see #LAYER_TYPE_HARDWARE
3787     */
3788    public static final int LAYER_TYPE_SOFTWARE = 1;
3789
3790    /**
3791     * <p>Indicates that the view has a hardware layer. A hardware layer is backed
3792     * by a hardware specific texture (generally Frame Buffer Objects or FBO on
3793     * OpenGL hardware) and causes the view to be rendered using Android's hardware
3794     * rendering pipeline, but only if hardware acceleration is turned on for the
3795     * view hierarchy. When hardware acceleration is turned off, hardware layers
3796     * behave exactly as {@link #LAYER_TYPE_SOFTWARE software layers}.</p>
3797     *
3798     * <p>A hardware layer is useful to apply a specific color filter and/or
3799     * blending mode and/or translucency to a view and all its children.</p>
3800     * <p>A hardware layer can be used to cache a complex view tree into a
3801     * texture and reduce the complexity of drawing operations. For instance,
3802     * when animating a complex view tree with a translation, a hardware layer can
3803     * be used to render the view tree only once.</p>
3804     * <p>A hardware layer can also be used to increase the rendering quality when
3805     * rotation transformations are applied on a view. It can also be used to
3806     * prevent potential clipping issues when applying 3D transforms on a view.</p>
3807     *
3808     * @see #getLayerType()
3809     * @see #setLayerType(int, android.graphics.Paint)
3810     * @see #LAYER_TYPE_NONE
3811     * @see #LAYER_TYPE_SOFTWARE
3812     */
3813    public static final int LAYER_TYPE_HARDWARE = 2;
3814
3815    @ViewDebug.ExportedProperty(category = "drawing", mapping = {
3816            @ViewDebug.IntToString(from = LAYER_TYPE_NONE, to = "NONE"),
3817            @ViewDebug.IntToString(from = LAYER_TYPE_SOFTWARE, to = "SOFTWARE"),
3818            @ViewDebug.IntToString(from = LAYER_TYPE_HARDWARE, to = "HARDWARE")
3819    })
3820    int mLayerType = LAYER_TYPE_NONE;
3821    Paint mLayerPaint;
3822
3823    /**
3824     * Set to true when drawing cache is enabled and cannot be created.
3825     *
3826     * @hide
3827     */
3828    public boolean mCachingFailed;
3829    private Bitmap mDrawingCache;
3830    private Bitmap mUnscaledDrawingCache;
3831
3832    /**
3833     * RenderNode holding View properties, potentially holding a DisplayList of View content.
3834     * <p>
3835     * When non-null and valid, this is expected to contain an up-to-date copy
3836     * of the View content. Its DisplayList content is cleared on temporary detach and reset on
3837     * cleanup.
3838     */
3839    final RenderNode mRenderNode;
3840
3841    /**
3842     * Set to true when the view is sending hover accessibility events because it
3843     * is the innermost hovered view.
3844     */
3845    private boolean mSendingHoverAccessibilityEvents;
3846
3847    /**
3848     * Delegate for injecting accessibility functionality.
3849     */
3850    AccessibilityDelegate mAccessibilityDelegate;
3851
3852    /**
3853     * The view's overlay layer. Developers get a reference to the overlay via getOverlay()
3854     * and add/remove objects to/from the overlay directly through the Overlay methods.
3855     */
3856    ViewOverlay mOverlay;
3857
3858    /**
3859     * The currently active parent view for receiving delegated nested scrolling events.
3860     * This is set by {@link #startNestedScroll(int)} during a touch interaction and cleared
3861     * by {@link #stopNestedScroll()} at the same point where we clear
3862     * requestDisallowInterceptTouchEvent.
3863     */
3864    private ViewParent mNestedScrollingParent;
3865
3866    /**
3867     * Consistency verifier for debugging purposes.
3868     * @hide
3869     */
3870    protected final InputEventConsistencyVerifier mInputEventConsistencyVerifier =
3871            InputEventConsistencyVerifier.isInstrumentationEnabled() ?
3872                    new InputEventConsistencyVerifier(this, 0) : null;
3873
3874    private static final AtomicInteger sNextGeneratedId = new AtomicInteger(1);
3875
3876    private int[] mTempNestedScrollConsumed;
3877
3878    /**
3879     * An overlay is going to draw this View instead of being drawn as part of this
3880     * View's parent. mGhostView is the View in the Overlay that must be invalidated
3881     * when this view is invalidated.
3882     */
3883    GhostView mGhostView;
3884
3885    /**
3886     * Holds pairs of adjacent attribute data: attribute name followed by its value.
3887     * @hide
3888     */
3889    @ViewDebug.ExportedProperty(category = "attributes", hasAdjacentMapping = true)
3890    public String[] mAttributes;
3891
3892    /**
3893     * Maps a Resource id to its name.
3894     */
3895    private static SparseArray<String> mAttributeMap;
3896
3897    /**
3898     * Queue of pending runnables. Used to postpone calls to post() until this
3899     * view is attached and has a handler.
3900     */
3901    private HandlerActionQueue mRunQueue;
3902
3903    /**
3904     * @hide
3905     */
3906    String mStartActivityRequestWho;
3907
3908    /**
3909     * Simple constructor to use when creating a view from code.
3910     *
3911     * @param context The Context the view is running in, through which it can
3912     *        access the current theme, resources, etc.
3913     */
3914    public View(Context context) {
3915        mContext = context;
3916        mResources = context != null ? context.getResources() : null;
3917        mViewFlags = SOUND_EFFECTS_ENABLED | HAPTIC_FEEDBACK_ENABLED;
3918        // Set some flags defaults
3919        mPrivateFlags2 =
3920                (LAYOUT_DIRECTION_DEFAULT << PFLAG2_LAYOUT_DIRECTION_MASK_SHIFT) |
3921                (TEXT_DIRECTION_DEFAULT << PFLAG2_TEXT_DIRECTION_MASK_SHIFT) |
3922                (PFLAG2_TEXT_DIRECTION_RESOLVED_DEFAULT) |
3923                (TEXT_ALIGNMENT_DEFAULT << PFLAG2_TEXT_ALIGNMENT_MASK_SHIFT) |
3924                (PFLAG2_TEXT_ALIGNMENT_RESOLVED_DEFAULT) |
3925                (IMPORTANT_FOR_ACCESSIBILITY_DEFAULT << PFLAG2_IMPORTANT_FOR_ACCESSIBILITY_SHIFT);
3926        mTouchSlop = ViewConfiguration.get(context).getScaledTouchSlop();
3927        setOverScrollMode(OVER_SCROLL_IF_CONTENT_SCROLLS);
3928        mUserPaddingStart = UNDEFINED_PADDING;
3929        mUserPaddingEnd = UNDEFINED_PADDING;
3930        mRenderNode = RenderNode.create(getClass().getName(), this);
3931
3932        if (!sCompatibilityDone && context != null) {
3933            final int targetSdkVersion = context.getApplicationInfo().targetSdkVersion;
3934
3935            // Older apps may need this compatibility hack for measurement.
3936            sUseBrokenMakeMeasureSpec = targetSdkVersion <= JELLY_BEAN_MR1;
3937
3938            // Older apps expect onMeasure() to always be called on a layout pass, regardless
3939            // of whether a layout was requested on that View.
3940            sIgnoreMeasureCache = targetSdkVersion < KITKAT;
3941
3942            Canvas.sCompatibilityRestore = targetSdkVersion < M;
3943
3944            // In M and newer, our widgets can pass a "hint" value in the size
3945            // for UNSPECIFIED MeasureSpecs. This lets child views of scrolling containers
3946            // know what the expected parent size is going to be, so e.g. list items can size
3947            // themselves at 1/3 the size of their container. It breaks older apps though,
3948            // specifically apps that use some popular open source libraries.
3949            sUseZeroUnspecifiedMeasureSpec = targetSdkVersion < M;
3950
3951            // Old versions of the platform would give different results from
3952            // LinearLayout measurement passes using EXACTLY and non-EXACTLY
3953            // modes, so we always need to run an additional EXACTLY pass.
3954            sAlwaysRemeasureExactly = targetSdkVersion <= M;
3955
3956            sCompatibilityDone = true;
3957        }
3958    }
3959
3960    /**
3961     * Constructor that is called when inflating a view from XML. This is called
3962     * when a view is being constructed from an XML file, supplying attributes
3963     * that were specified in the XML file. This version uses a default style of
3964     * 0, so the only attribute values applied are those in the Context's Theme
3965     * and the given AttributeSet.
3966     *
3967     * <p>
3968     * The method onFinishInflate() will be called after all children have been
3969     * added.
3970     *
3971     * @param context The Context the view is running in, through which it can
3972     *        access the current theme, resources, etc.
3973     * @param attrs The attributes of the XML tag that is inflating the view.
3974     * @see #View(Context, AttributeSet, int)
3975     */
3976    public View(Context context, @Nullable AttributeSet attrs) {
3977        this(context, attrs, 0);
3978    }
3979
3980    /**
3981     * Perform inflation from XML and apply a class-specific base style from a
3982     * theme attribute. This constructor of View allows subclasses to use their
3983     * own base style when they are inflating. For example, a Button class's
3984     * constructor would call this version of the super class constructor and
3985     * supply <code>R.attr.buttonStyle</code> for <var>defStyleAttr</var>; this
3986     * allows the theme's button style to modify all of the base view attributes
3987     * (in particular its background) as well as the Button class's attributes.
3988     *
3989     * @param context The Context the view is running in, through which it can
3990     *        access the current theme, resources, etc.
3991     * @param attrs The attributes of the XML tag that is inflating the view.
3992     * @param defStyleAttr An attribute in the current theme that contains a
3993     *        reference to a style resource that supplies default values for
3994     *        the view. Can be 0 to not look for defaults.
3995     * @see #View(Context, AttributeSet)
3996     */
3997    public View(Context context, @Nullable AttributeSet attrs, int defStyleAttr) {
3998        this(context, attrs, defStyleAttr, 0);
3999    }
4000
4001    /**
4002     * Perform inflation from XML and apply a class-specific base style from a
4003     * theme attribute or style resource. This constructor of View allows
4004     * subclasses to use their own base style when they are inflating.
4005     * <p>
4006     * When determining the final value of a particular attribute, there are
4007     * four inputs that come into play:
4008     * <ol>
4009     * <li>Any attribute values in the given AttributeSet.
4010     * <li>The style resource specified in the AttributeSet (named "style").
4011     * <li>The default style specified by <var>defStyleAttr</var>.
4012     * <li>The default style specified by <var>defStyleRes</var>.
4013     * <li>The base values in this theme.
4014     * </ol>
4015     * <p>
4016     * Each of these inputs is considered in-order, with the first listed taking
4017     * precedence over the following ones. In other words, if in the
4018     * AttributeSet you have supplied <code>&lt;Button * textColor="#ff000000"&gt;</code>
4019     * , then the button's text will <em>always</em> be black, regardless of
4020     * what is specified in any of the styles.
4021     *
4022     * @param context The Context the view is running in, through which it can
4023     *        access the current theme, resources, etc.
4024     * @param attrs The attributes of the XML tag that is inflating the view.
4025     * @param defStyleAttr An attribute in the current theme that contains a
4026     *        reference to a style resource that supplies default values for
4027     *        the view. Can be 0 to not look for defaults.
4028     * @param defStyleRes A resource identifier of a style resource that
4029     *        supplies default values for the view, used only if
4030     *        defStyleAttr is 0 or can not be found in the theme. Can be 0
4031     *        to not look for defaults.
4032     * @see #View(Context, AttributeSet, int)
4033     */
4034    public View(Context context, @Nullable AttributeSet attrs, int defStyleAttr, int defStyleRes) {
4035        this(context);
4036
4037        final TypedArray a = context.obtainStyledAttributes(
4038                attrs, com.android.internal.R.styleable.View, defStyleAttr, defStyleRes);
4039
4040        if (mDebugViewAttributes) {
4041            saveAttributeData(attrs, a);
4042        }
4043
4044        Drawable background = null;
4045
4046        int leftPadding = -1;
4047        int topPadding = -1;
4048        int rightPadding = -1;
4049        int bottomPadding = -1;
4050        int startPadding = UNDEFINED_PADDING;
4051        int endPadding = UNDEFINED_PADDING;
4052
4053        int padding = -1;
4054
4055        int viewFlagValues = 0;
4056        int viewFlagMasks = 0;
4057
4058        boolean setScrollContainer = false;
4059
4060        int x = 0;
4061        int y = 0;
4062
4063        float tx = 0;
4064        float ty = 0;
4065        float tz = 0;
4066        float elevation = 0;
4067        float rotation = 0;
4068        float rotationX = 0;
4069        float rotationY = 0;
4070        float sx = 1f;
4071        float sy = 1f;
4072        boolean transformSet = false;
4073
4074        int scrollbarStyle = SCROLLBARS_INSIDE_OVERLAY;
4075        int overScrollMode = mOverScrollMode;
4076        boolean initializeScrollbars = false;
4077        boolean initializeScrollIndicators = false;
4078
4079        boolean startPaddingDefined = false;
4080        boolean endPaddingDefined = false;
4081        boolean leftPaddingDefined = false;
4082        boolean rightPaddingDefined = false;
4083
4084        final int targetSdkVersion = context.getApplicationInfo().targetSdkVersion;
4085
4086        final int N = a.getIndexCount();
4087        for (int i = 0; i < N; i++) {
4088            int attr = a.getIndex(i);
4089            switch (attr) {
4090                case com.android.internal.R.styleable.View_background:
4091                    background = a.getDrawable(attr);
4092                    break;
4093                case com.android.internal.R.styleable.View_padding:
4094                    padding = a.getDimensionPixelSize(attr, -1);
4095                    mUserPaddingLeftInitial = padding;
4096                    mUserPaddingRightInitial = padding;
4097                    leftPaddingDefined = true;
4098                    rightPaddingDefined = true;
4099                    break;
4100                 case com.android.internal.R.styleable.View_paddingLeft:
4101                    leftPadding = a.getDimensionPixelSize(attr, -1);
4102                    mUserPaddingLeftInitial = leftPadding;
4103                    leftPaddingDefined = true;
4104                    break;
4105                case com.android.internal.R.styleable.View_paddingTop:
4106                    topPadding = a.getDimensionPixelSize(attr, -1);
4107                    break;
4108                case com.android.internal.R.styleable.View_paddingRight:
4109                    rightPadding = a.getDimensionPixelSize(attr, -1);
4110                    mUserPaddingRightInitial = rightPadding;
4111                    rightPaddingDefined = true;
4112                    break;
4113                case com.android.internal.R.styleable.View_paddingBottom:
4114                    bottomPadding = a.getDimensionPixelSize(attr, -1);
4115                    break;
4116                case com.android.internal.R.styleable.View_paddingStart:
4117                    startPadding = a.getDimensionPixelSize(attr, UNDEFINED_PADDING);
4118                    startPaddingDefined = (startPadding != UNDEFINED_PADDING);
4119                    break;
4120                case com.android.internal.R.styleable.View_paddingEnd:
4121                    endPadding = a.getDimensionPixelSize(attr, UNDEFINED_PADDING);
4122                    endPaddingDefined = (endPadding != UNDEFINED_PADDING);
4123                    break;
4124                case com.android.internal.R.styleable.View_scrollX:
4125                    x = a.getDimensionPixelOffset(attr, 0);
4126                    break;
4127                case com.android.internal.R.styleable.View_scrollY:
4128                    y = a.getDimensionPixelOffset(attr, 0);
4129                    break;
4130                case com.android.internal.R.styleable.View_alpha:
4131                    setAlpha(a.getFloat(attr, 1f));
4132                    break;
4133                case com.android.internal.R.styleable.View_transformPivotX:
4134                    setPivotX(a.getDimensionPixelOffset(attr, 0));
4135                    break;
4136                case com.android.internal.R.styleable.View_transformPivotY:
4137                    setPivotY(a.getDimensionPixelOffset(attr, 0));
4138                    break;
4139                case com.android.internal.R.styleable.View_translationX:
4140                    tx = a.getDimensionPixelOffset(attr, 0);
4141                    transformSet = true;
4142                    break;
4143                case com.android.internal.R.styleable.View_translationY:
4144                    ty = a.getDimensionPixelOffset(attr, 0);
4145                    transformSet = true;
4146                    break;
4147                case com.android.internal.R.styleable.View_translationZ:
4148                    tz = a.getDimensionPixelOffset(attr, 0);
4149                    transformSet = true;
4150                    break;
4151                case com.android.internal.R.styleable.View_elevation:
4152                    elevation = a.getDimensionPixelOffset(attr, 0);
4153                    transformSet = true;
4154                    break;
4155                case com.android.internal.R.styleable.View_rotation:
4156                    rotation = a.getFloat(attr, 0);
4157                    transformSet = true;
4158                    break;
4159                case com.android.internal.R.styleable.View_rotationX:
4160                    rotationX = a.getFloat(attr, 0);
4161                    transformSet = true;
4162                    break;
4163                case com.android.internal.R.styleable.View_rotationY:
4164                    rotationY = a.getFloat(attr, 0);
4165                    transformSet = true;
4166                    break;
4167                case com.android.internal.R.styleable.View_scaleX:
4168                    sx = a.getFloat(attr, 1f);
4169                    transformSet = true;
4170                    break;
4171                case com.android.internal.R.styleable.View_scaleY:
4172                    sy = a.getFloat(attr, 1f);
4173                    transformSet = true;
4174                    break;
4175                case com.android.internal.R.styleable.View_id:
4176                    mID = a.getResourceId(attr, NO_ID);
4177                    break;
4178                case com.android.internal.R.styleable.View_tag:
4179                    mTag = a.getText(attr);
4180                    break;
4181                case com.android.internal.R.styleable.View_fitsSystemWindows:
4182                    if (a.getBoolean(attr, false)) {
4183                        viewFlagValues |= FITS_SYSTEM_WINDOWS;
4184                        viewFlagMasks |= FITS_SYSTEM_WINDOWS;
4185                    }
4186                    break;
4187                case com.android.internal.R.styleable.View_focusable:
4188                    if (a.getBoolean(attr, false)) {
4189                        viewFlagValues |= FOCUSABLE;
4190                        viewFlagMasks |= FOCUSABLE_MASK;
4191                    }
4192                    break;
4193                case com.android.internal.R.styleable.View_focusableInTouchMode:
4194                    if (a.getBoolean(attr, false)) {
4195                        viewFlagValues |= FOCUSABLE_IN_TOUCH_MODE | FOCUSABLE;
4196                        viewFlagMasks |= FOCUSABLE_IN_TOUCH_MODE | FOCUSABLE_MASK;
4197                    }
4198                    break;
4199                case com.android.internal.R.styleable.View_clickable:
4200                    if (a.getBoolean(attr, false)) {
4201                        viewFlagValues |= CLICKABLE;
4202                        viewFlagMasks |= CLICKABLE;
4203                    }
4204                    break;
4205                case com.android.internal.R.styleable.View_longClickable:
4206                    if (a.getBoolean(attr, false)) {
4207                        viewFlagValues |= LONG_CLICKABLE;
4208                        viewFlagMasks |= LONG_CLICKABLE;
4209                    }
4210                    break;
4211                case com.android.internal.R.styleable.View_contextClickable:
4212                    if (a.getBoolean(attr, false)) {
4213                        viewFlagValues |= CONTEXT_CLICKABLE;
4214                        viewFlagMasks |= CONTEXT_CLICKABLE;
4215                    }
4216                    break;
4217                case com.android.internal.R.styleable.View_saveEnabled:
4218                    if (!a.getBoolean(attr, true)) {
4219                        viewFlagValues |= SAVE_DISABLED;
4220                        viewFlagMasks |= SAVE_DISABLED_MASK;
4221                    }
4222                    break;
4223                case com.android.internal.R.styleable.View_duplicateParentState:
4224                    if (a.getBoolean(attr, false)) {
4225                        viewFlagValues |= DUPLICATE_PARENT_STATE;
4226                        viewFlagMasks |= DUPLICATE_PARENT_STATE;
4227                    }
4228                    break;
4229                case com.android.internal.R.styleable.View_visibility:
4230                    final int visibility = a.getInt(attr, 0);
4231                    if (visibility != 0) {
4232                        viewFlagValues |= VISIBILITY_FLAGS[visibility];
4233                        viewFlagMasks |= VISIBILITY_MASK;
4234                    }
4235                    break;
4236                case com.android.internal.R.styleable.View_layoutDirection:
4237                    // Clear any layout direction flags (included resolved bits) already set
4238                    mPrivateFlags2 &=
4239                            ~(PFLAG2_LAYOUT_DIRECTION_MASK | PFLAG2_LAYOUT_DIRECTION_RESOLVED_MASK);
4240                    // Set the layout direction flags depending on the value of the attribute
4241                    final int layoutDirection = a.getInt(attr, -1);
4242                    final int value = (layoutDirection != -1) ?
4243                            LAYOUT_DIRECTION_FLAGS[layoutDirection] : LAYOUT_DIRECTION_DEFAULT;
4244                    mPrivateFlags2 |= (value << PFLAG2_LAYOUT_DIRECTION_MASK_SHIFT);
4245                    break;
4246                case com.android.internal.R.styleable.View_drawingCacheQuality:
4247                    final int cacheQuality = a.getInt(attr, 0);
4248                    if (cacheQuality != 0) {
4249                        viewFlagValues |= DRAWING_CACHE_QUALITY_FLAGS[cacheQuality];
4250                        viewFlagMasks |= DRAWING_CACHE_QUALITY_MASK;
4251                    }
4252                    break;
4253                case com.android.internal.R.styleable.View_contentDescription:
4254                    setContentDescription(a.getString(attr));
4255                    break;
4256                case com.android.internal.R.styleable.View_accessibilityTraversalBefore:
4257                    setAccessibilityTraversalBefore(a.getResourceId(attr, NO_ID));
4258                    break;
4259                case com.android.internal.R.styleable.View_accessibilityTraversalAfter:
4260                    setAccessibilityTraversalAfter(a.getResourceId(attr, NO_ID));
4261                    break;
4262                case com.android.internal.R.styleable.View_labelFor:
4263                    setLabelFor(a.getResourceId(attr, NO_ID));
4264                    break;
4265                case com.android.internal.R.styleable.View_soundEffectsEnabled:
4266                    if (!a.getBoolean(attr, true)) {
4267                        viewFlagValues &= ~SOUND_EFFECTS_ENABLED;
4268                        viewFlagMasks |= SOUND_EFFECTS_ENABLED;
4269                    }
4270                    break;
4271                case com.android.internal.R.styleable.View_hapticFeedbackEnabled:
4272                    if (!a.getBoolean(attr, true)) {
4273                        viewFlagValues &= ~HAPTIC_FEEDBACK_ENABLED;
4274                        viewFlagMasks |= HAPTIC_FEEDBACK_ENABLED;
4275                    }
4276                    break;
4277                case R.styleable.View_scrollbars:
4278                    final int scrollbars = a.getInt(attr, SCROLLBARS_NONE);
4279                    if (scrollbars != SCROLLBARS_NONE) {
4280                        viewFlagValues |= scrollbars;
4281                        viewFlagMasks |= SCROLLBARS_MASK;
4282                        initializeScrollbars = true;
4283                    }
4284                    break;
4285                //noinspection deprecation
4286                case R.styleable.View_fadingEdge:
4287                    if (targetSdkVersion >= ICE_CREAM_SANDWICH) {
4288                        // Ignore the attribute starting with ICS
4289                        break;
4290                    }
4291                    // With builds < ICS, fall through and apply fading edges
4292                case R.styleable.View_requiresFadingEdge:
4293                    final int fadingEdge = a.getInt(attr, FADING_EDGE_NONE);
4294                    if (fadingEdge != FADING_EDGE_NONE) {
4295                        viewFlagValues |= fadingEdge;
4296                        viewFlagMasks |= FADING_EDGE_MASK;
4297                        initializeFadingEdgeInternal(a);
4298                    }
4299                    break;
4300                case R.styleable.View_scrollbarStyle:
4301                    scrollbarStyle = a.getInt(attr, SCROLLBARS_INSIDE_OVERLAY);
4302                    if (scrollbarStyle != SCROLLBARS_INSIDE_OVERLAY) {
4303                        viewFlagValues |= scrollbarStyle & SCROLLBARS_STYLE_MASK;
4304                        viewFlagMasks |= SCROLLBARS_STYLE_MASK;
4305                    }
4306                    break;
4307                case R.styleable.View_isScrollContainer:
4308                    setScrollContainer = true;
4309                    if (a.getBoolean(attr, false)) {
4310                        setScrollContainer(true);
4311                    }
4312                    break;
4313                case com.android.internal.R.styleable.View_keepScreenOn:
4314                    if (a.getBoolean(attr, false)) {
4315                        viewFlagValues |= KEEP_SCREEN_ON;
4316                        viewFlagMasks |= KEEP_SCREEN_ON;
4317                    }
4318                    break;
4319                case R.styleable.View_filterTouchesWhenObscured:
4320                    if (a.getBoolean(attr, false)) {
4321                        viewFlagValues |= FILTER_TOUCHES_WHEN_OBSCURED;
4322                        viewFlagMasks |= FILTER_TOUCHES_WHEN_OBSCURED;
4323                    }
4324                    break;
4325                case R.styleable.View_nextFocusLeft:
4326                    mNextFocusLeftId = a.getResourceId(attr, View.NO_ID);
4327                    break;
4328                case R.styleable.View_nextFocusRight:
4329                    mNextFocusRightId = a.getResourceId(attr, View.NO_ID);
4330                    break;
4331                case R.styleable.View_nextFocusUp:
4332                    mNextFocusUpId = a.getResourceId(attr, View.NO_ID);
4333                    break;
4334                case R.styleable.View_nextFocusDown:
4335                    mNextFocusDownId = a.getResourceId(attr, View.NO_ID);
4336                    break;
4337                case R.styleable.View_nextFocusForward:
4338                    mNextFocusForwardId = a.getResourceId(attr, View.NO_ID);
4339                    break;
4340                case R.styleable.View_minWidth:
4341                    mMinWidth = a.getDimensionPixelSize(attr, 0);
4342                    break;
4343                case R.styleable.View_minHeight:
4344                    mMinHeight = a.getDimensionPixelSize(attr, 0);
4345                    break;
4346                case R.styleable.View_onClick:
4347                    if (context.isRestricted()) {
4348                        throw new IllegalStateException("The android:onClick attribute cannot "
4349                                + "be used within a restricted context");
4350                    }
4351
4352                    final String handlerName = a.getString(attr);
4353                    if (handlerName != null) {
4354                        setOnClickListener(new DeclaredOnClickListener(this, handlerName));
4355                    }
4356                    break;
4357                case R.styleable.View_overScrollMode:
4358                    overScrollMode = a.getInt(attr, OVER_SCROLL_IF_CONTENT_SCROLLS);
4359                    break;
4360                case R.styleable.View_verticalScrollbarPosition:
4361                    mVerticalScrollbarPosition = a.getInt(attr, SCROLLBAR_POSITION_DEFAULT);
4362                    break;
4363                case R.styleable.View_layerType:
4364                    setLayerType(a.getInt(attr, LAYER_TYPE_NONE), null);
4365                    break;
4366                case R.styleable.View_textDirection:
4367                    // Clear any text direction flag already set
4368                    mPrivateFlags2 &= ~PFLAG2_TEXT_DIRECTION_MASK;
4369                    // Set the text direction flags depending on the value of the attribute
4370                    final int textDirection = a.getInt(attr, -1);
4371                    if (textDirection != -1) {
4372                        mPrivateFlags2 |= PFLAG2_TEXT_DIRECTION_FLAGS[textDirection];
4373                    }
4374                    break;
4375                case R.styleable.View_textAlignment:
4376                    // Clear any text alignment flag already set
4377                    mPrivateFlags2 &= ~PFLAG2_TEXT_ALIGNMENT_MASK;
4378                    // Set the text alignment flag depending on the value of the attribute
4379                    final int textAlignment = a.getInt(attr, TEXT_ALIGNMENT_DEFAULT);
4380                    mPrivateFlags2 |= PFLAG2_TEXT_ALIGNMENT_FLAGS[textAlignment];
4381                    break;
4382                case R.styleable.View_importantForAccessibility:
4383                    setImportantForAccessibility(a.getInt(attr,
4384                            IMPORTANT_FOR_ACCESSIBILITY_DEFAULT));
4385                    break;
4386                case R.styleable.View_accessibilityLiveRegion:
4387                    setAccessibilityLiveRegion(a.getInt(attr, ACCESSIBILITY_LIVE_REGION_DEFAULT));
4388                    break;
4389                case R.styleable.View_transitionName:
4390                    setTransitionName(a.getString(attr));
4391                    break;
4392                case R.styleable.View_nestedScrollingEnabled:
4393                    setNestedScrollingEnabled(a.getBoolean(attr, false));
4394                    break;
4395                case R.styleable.View_stateListAnimator:
4396                    setStateListAnimator(AnimatorInflater.loadStateListAnimator(context,
4397                            a.getResourceId(attr, 0)));
4398                    break;
4399                case R.styleable.View_backgroundTint:
4400                    // This will get applied later during setBackground().
4401                    if (mBackgroundTint == null) {
4402                        mBackgroundTint = new TintInfo();
4403                    }
4404                    mBackgroundTint.mTintList = a.getColorStateList(
4405                            R.styleable.View_backgroundTint);
4406                    mBackgroundTint.mHasTintList = true;
4407                    break;
4408                case R.styleable.View_backgroundTintMode:
4409                    // This will get applied later during setBackground().
4410                    if (mBackgroundTint == null) {
4411                        mBackgroundTint = new TintInfo();
4412                    }
4413                    mBackgroundTint.mTintMode = Drawable.parseTintMode(a.getInt(
4414                            R.styleable.View_backgroundTintMode, -1), null);
4415                    mBackgroundTint.mHasTintMode = true;
4416                    break;
4417                case R.styleable.View_outlineProvider:
4418                    setOutlineProviderFromAttribute(a.getInt(R.styleable.View_outlineProvider,
4419                            PROVIDER_BACKGROUND));
4420                    break;
4421                case R.styleable.View_foreground:
4422                    if (targetSdkVersion >= VERSION_CODES.M || this instanceof FrameLayout) {
4423                        setForeground(a.getDrawable(attr));
4424                    }
4425                    break;
4426                case R.styleable.View_foregroundGravity:
4427                    if (targetSdkVersion >= VERSION_CODES.M || this instanceof FrameLayout) {
4428                        setForegroundGravity(a.getInt(attr, Gravity.NO_GRAVITY));
4429                    }
4430                    break;
4431                case R.styleable.View_foregroundTintMode:
4432                    if (targetSdkVersion >= VERSION_CODES.M || this instanceof FrameLayout) {
4433                        setForegroundTintMode(Drawable.parseTintMode(a.getInt(attr, -1), null));
4434                    }
4435                    break;
4436                case R.styleable.View_foregroundTint:
4437                    if (targetSdkVersion >= VERSION_CODES.M || this instanceof FrameLayout) {
4438                        setForegroundTintList(a.getColorStateList(attr));
4439                    }
4440                    break;
4441                case R.styleable.View_foregroundInsidePadding:
4442                    if (targetSdkVersion >= VERSION_CODES.M || this instanceof FrameLayout) {
4443                        if (mForegroundInfo == null) {
4444                            mForegroundInfo = new ForegroundInfo();
4445                        }
4446                        mForegroundInfo.mInsidePadding = a.getBoolean(attr,
4447                                mForegroundInfo.mInsidePadding);
4448                    }
4449                    break;
4450                case R.styleable.View_scrollIndicators:
4451                    final int scrollIndicators =
4452                            (a.getInt(attr, 0) << SCROLL_INDICATORS_TO_PFLAGS3_LSHIFT)
4453                                    & SCROLL_INDICATORS_PFLAG3_MASK;
4454                    if (scrollIndicators != 0) {
4455                        mPrivateFlags3 |= scrollIndicators;
4456                        initializeScrollIndicators = true;
4457                    }
4458                    break;
4459            }
4460        }
4461
4462        setOverScrollMode(overScrollMode);
4463
4464        // Cache start/end user padding as we cannot fully resolve padding here (we dont have yet
4465        // the resolved layout direction). Those cached values will be used later during padding
4466        // resolution.
4467        mUserPaddingStart = startPadding;
4468        mUserPaddingEnd = endPadding;
4469
4470        if (background != null) {
4471            setBackground(background);
4472        }
4473
4474        // setBackground above will record that padding is currently provided by the background.
4475        // If we have padding specified via xml, record that here instead and use it.
4476        mLeftPaddingDefined = leftPaddingDefined;
4477        mRightPaddingDefined = rightPaddingDefined;
4478
4479        if (padding >= 0) {
4480            leftPadding = padding;
4481            topPadding = padding;
4482            rightPadding = padding;
4483            bottomPadding = padding;
4484            mUserPaddingLeftInitial = padding;
4485            mUserPaddingRightInitial = padding;
4486        }
4487
4488        if (isRtlCompatibilityMode()) {
4489            // RTL compatibility mode: pre Jelly Bean MR1 case OR no RTL support case.
4490            // left / right padding are used if defined (meaning here nothing to do). If they are not
4491            // defined and start / end padding are defined (e.g. in Frameworks resources), then we use
4492            // start / end and resolve them as left / right (layout direction is not taken into account).
4493            // Padding from the background drawable is stored at this point in mUserPaddingLeftInitial
4494            // and mUserPaddingRightInitial) so drawable padding will be used as ultimate default if
4495            // defined.
4496            if (!mLeftPaddingDefined && startPaddingDefined) {
4497                leftPadding = startPadding;
4498            }
4499            mUserPaddingLeftInitial = (leftPadding >= 0) ? leftPadding : mUserPaddingLeftInitial;
4500            if (!mRightPaddingDefined && endPaddingDefined) {
4501                rightPadding = endPadding;
4502            }
4503            mUserPaddingRightInitial = (rightPadding >= 0) ? rightPadding : mUserPaddingRightInitial;
4504        } else {
4505            // Jelly Bean MR1 and after case: if start/end defined, they will override any left/right
4506            // values defined. Otherwise, left /right values are used.
4507            // Padding from the background drawable is stored at this point in mUserPaddingLeftInitial
4508            // and mUserPaddingRightInitial) so drawable padding will be used as ultimate default if
4509            // defined.
4510            final boolean hasRelativePadding = startPaddingDefined || endPaddingDefined;
4511
4512            if (mLeftPaddingDefined && !hasRelativePadding) {
4513                mUserPaddingLeftInitial = leftPadding;
4514            }
4515            if (mRightPaddingDefined && !hasRelativePadding) {
4516                mUserPaddingRightInitial = rightPadding;
4517            }
4518        }
4519
4520        internalSetPadding(
4521                mUserPaddingLeftInitial,
4522                topPadding >= 0 ? topPadding : mPaddingTop,
4523                mUserPaddingRightInitial,
4524                bottomPadding >= 0 ? bottomPadding : mPaddingBottom);
4525
4526        if (viewFlagMasks != 0) {
4527            setFlags(viewFlagValues, viewFlagMasks);
4528        }
4529
4530        if (initializeScrollbars) {
4531            initializeScrollbarsInternal(a);
4532        }
4533
4534        if (initializeScrollIndicators) {
4535            initializeScrollIndicatorsInternal();
4536        }
4537
4538        a.recycle();
4539
4540        // Needs to be called after mViewFlags is set
4541        if (scrollbarStyle != SCROLLBARS_INSIDE_OVERLAY) {
4542            recomputePadding();
4543        }
4544
4545        if (x != 0 || y != 0) {
4546            scrollTo(x, y);
4547        }
4548
4549        if (transformSet) {
4550            setTranslationX(tx);
4551            setTranslationY(ty);
4552            setTranslationZ(tz);
4553            setElevation(elevation);
4554            setRotation(rotation);
4555            setRotationX(rotationX);
4556            setRotationY(rotationY);
4557            setScaleX(sx);
4558            setScaleY(sy);
4559        }
4560
4561        if (!setScrollContainer && (viewFlagValues&SCROLLBARS_VERTICAL) != 0) {
4562            setScrollContainer(true);
4563        }
4564
4565        computeOpaqueFlags();
4566    }
4567
4568    /**
4569     * An implementation of OnClickListener that attempts to lazily load a
4570     * named click handling method from a parent or ancestor context.
4571     */
4572    private static class DeclaredOnClickListener implements OnClickListener {
4573        private final View mHostView;
4574        private final String mMethodName;
4575
4576        private Method mResolvedMethod;
4577        private Context mResolvedContext;
4578
4579        public DeclaredOnClickListener(@NonNull View hostView, @NonNull String methodName) {
4580            mHostView = hostView;
4581            mMethodName = methodName;
4582        }
4583
4584        @Override
4585        public void onClick(@NonNull View v) {
4586            if (mResolvedMethod == null) {
4587                resolveMethod(mHostView.getContext(), mMethodName);
4588            }
4589
4590            try {
4591                mResolvedMethod.invoke(mResolvedContext, v);
4592            } catch (IllegalAccessException e) {
4593                throw new IllegalStateException(
4594                        "Could not execute non-public method for android:onClick", e);
4595            } catch (InvocationTargetException e) {
4596                throw new IllegalStateException(
4597                        "Could not execute method for android:onClick", e);
4598            }
4599        }
4600
4601        @NonNull
4602        private void resolveMethod(@Nullable Context context, @NonNull String name) {
4603            while (context != null) {
4604                try {
4605                    if (!context.isRestricted()) {
4606                        final Method method = context.getClass().getMethod(mMethodName, View.class);
4607                        if (method != null) {
4608                            mResolvedMethod = method;
4609                            mResolvedContext = context;
4610                            return;
4611                        }
4612                    }
4613                } catch (NoSuchMethodException e) {
4614                    // Failed to find method, keep searching up the hierarchy.
4615                }
4616
4617                if (context instanceof ContextWrapper) {
4618                    context = ((ContextWrapper) context).getBaseContext();
4619                } else {
4620                    // Can't search up the hierarchy, null out and fail.
4621                    context = null;
4622                }
4623            }
4624
4625            final int id = mHostView.getId();
4626            final String idText = id == NO_ID ? "" : " with id '"
4627                    + mHostView.getContext().getResources().getResourceEntryName(id) + "'";
4628            throw new IllegalStateException("Could not find method " + mMethodName
4629                    + "(View) in a parent or ancestor Context for android:onClick "
4630                    + "attribute defined on view " + mHostView.getClass() + idText);
4631        }
4632    }
4633
4634    /**
4635     * Non-public constructor for use in testing
4636     */
4637    View() {
4638        mResources = null;
4639        mRenderNode = RenderNode.create(getClass().getName(), this);
4640    }
4641
4642    private static SparseArray<String> getAttributeMap() {
4643        if (mAttributeMap == null) {
4644            mAttributeMap = new SparseArray<>();
4645        }
4646        return mAttributeMap;
4647    }
4648
4649    private void saveAttributeData(@Nullable AttributeSet attrs, @NonNull TypedArray t) {
4650        final int attrsCount = attrs == null ? 0 : attrs.getAttributeCount();
4651        final int indexCount = t.getIndexCount();
4652        final String[] attributes = new String[(attrsCount + indexCount) * 2];
4653
4654        int i = 0;
4655
4656        // Store raw XML attributes.
4657        for (int j = 0; j < attrsCount; ++j) {
4658            attributes[i] = attrs.getAttributeName(j);
4659            attributes[i + 1] = attrs.getAttributeValue(j);
4660            i += 2;
4661        }
4662
4663        // Store resolved styleable attributes.
4664        final Resources res = t.getResources();
4665        final SparseArray<String> attributeMap = getAttributeMap();
4666        for (int j = 0; j < indexCount; ++j) {
4667            final int index = t.getIndex(j);
4668            if (!t.hasValueOrEmpty(index)) {
4669                // Value is undefined. Skip it.
4670                continue;
4671            }
4672
4673            final int resourceId = t.getResourceId(index, 0);
4674            if (resourceId == 0) {
4675                // Value is not a reference. Skip it.
4676                continue;
4677            }
4678
4679            String resourceName = attributeMap.get(resourceId);
4680            if (resourceName == null) {
4681                try {
4682                    resourceName = res.getResourceName(resourceId);
4683                } catch (Resources.NotFoundException e) {
4684                    resourceName = "0x" + Integer.toHexString(resourceId);
4685                }
4686                attributeMap.put(resourceId, resourceName);
4687            }
4688
4689            attributes[i] = resourceName;
4690            attributes[i + 1] = t.getString(index);
4691            i += 2;
4692        }
4693
4694        // Trim to fit contents.
4695        final String[] trimmed = new String[i];
4696        System.arraycopy(attributes, 0, trimmed, 0, i);
4697        mAttributes = trimmed;
4698    }
4699
4700    public String toString() {
4701        StringBuilder out = new StringBuilder(128);
4702        out.append(getClass().getName());
4703        out.append('{');
4704        out.append(Integer.toHexString(System.identityHashCode(this)));
4705        out.append(' ');
4706        switch (mViewFlags&VISIBILITY_MASK) {
4707            case VISIBLE: out.append('V'); break;
4708            case INVISIBLE: out.append('I'); break;
4709            case GONE: out.append('G'); break;
4710            default: out.append('.'); break;
4711        }
4712        out.append((mViewFlags&FOCUSABLE_MASK) == FOCUSABLE ? 'F' : '.');
4713        out.append((mViewFlags&ENABLED_MASK) == ENABLED ? 'E' : '.');
4714        out.append((mViewFlags&DRAW_MASK) == WILL_NOT_DRAW ? '.' : 'D');
4715        out.append((mViewFlags&SCROLLBARS_HORIZONTAL) != 0 ? 'H' : '.');
4716        out.append((mViewFlags&SCROLLBARS_VERTICAL) != 0 ? 'V' : '.');
4717        out.append((mViewFlags&CLICKABLE) != 0 ? 'C' : '.');
4718        out.append((mViewFlags&LONG_CLICKABLE) != 0 ? 'L' : '.');
4719        out.append((mViewFlags&CONTEXT_CLICKABLE) != 0 ? 'X' : '.');
4720        out.append(' ');
4721        out.append((mPrivateFlags&PFLAG_IS_ROOT_NAMESPACE) != 0 ? 'R' : '.');
4722        out.append((mPrivateFlags&PFLAG_FOCUSED) != 0 ? 'F' : '.');
4723        out.append((mPrivateFlags&PFLAG_SELECTED) != 0 ? 'S' : '.');
4724        if ((mPrivateFlags&PFLAG_PREPRESSED) != 0) {
4725            out.append('p');
4726        } else {
4727            out.append((mPrivateFlags&PFLAG_PRESSED) != 0 ? 'P' : '.');
4728        }
4729        out.append((mPrivateFlags&PFLAG_HOVERED) != 0 ? 'H' : '.');
4730        out.append((mPrivateFlags&PFLAG_ACTIVATED) != 0 ? 'A' : '.');
4731        out.append((mPrivateFlags&PFLAG_INVALIDATED) != 0 ? 'I' : '.');
4732        out.append((mPrivateFlags&PFLAG_DIRTY_MASK) != 0 ? 'D' : '.');
4733        out.append(' ');
4734        out.append(mLeft);
4735        out.append(',');
4736        out.append(mTop);
4737        out.append('-');
4738        out.append(mRight);
4739        out.append(',');
4740        out.append(mBottom);
4741        final int id = getId();
4742        if (id != NO_ID) {
4743            out.append(" #");
4744            out.append(Integer.toHexString(id));
4745            final Resources r = mResources;
4746            if (id > 0 && Resources.resourceHasPackage(id) && r != null) {
4747                try {
4748                    String pkgname;
4749                    switch (id&0xff000000) {
4750                        case 0x7f000000:
4751                            pkgname="app";
4752                            break;
4753                        case 0x01000000:
4754                            pkgname="android";
4755                            break;
4756                        default:
4757                            pkgname = r.getResourcePackageName(id);
4758                            break;
4759                    }
4760                    String typename = r.getResourceTypeName(id);
4761                    String entryname = r.getResourceEntryName(id);
4762                    out.append(" ");
4763                    out.append(pkgname);
4764                    out.append(":");
4765                    out.append(typename);
4766                    out.append("/");
4767                    out.append(entryname);
4768                } catch (Resources.NotFoundException e) {
4769                }
4770            }
4771        }
4772        out.append("}");
4773        return out.toString();
4774    }
4775
4776    /**
4777     * <p>
4778     * Initializes the fading edges from a given set of styled attributes. This
4779     * method should be called by subclasses that need fading edges and when an
4780     * instance of these subclasses is created programmatically rather than
4781     * being inflated from XML. This method is automatically called when the XML
4782     * is inflated.
4783     * </p>
4784     *
4785     * @param a the styled attributes set to initialize the fading edges from
4786     *
4787     * @removed
4788     */
4789    protected void initializeFadingEdge(TypedArray a) {
4790        // This method probably shouldn't have been included in the SDK to begin with.
4791        // It relies on 'a' having been initialized using an attribute filter array that is
4792        // not publicly available to the SDK. The old method has been renamed
4793        // to initializeFadingEdgeInternal and hidden for framework use only;
4794        // this one initializes using defaults to make it safe to call for apps.
4795
4796        TypedArray arr = mContext.obtainStyledAttributes(com.android.internal.R.styleable.View);
4797
4798        initializeFadingEdgeInternal(arr);
4799
4800        arr.recycle();
4801    }
4802
4803    /**
4804     * <p>
4805     * Initializes the fading edges from a given set of styled attributes. This
4806     * method should be called by subclasses that need fading edges and when an
4807     * instance of these subclasses is created programmatically rather than
4808     * being inflated from XML. This method is automatically called when the XML
4809     * is inflated.
4810     * </p>
4811     *
4812     * @param a the styled attributes set to initialize the fading edges from
4813     * @hide This is the real method; the public one is shimmed to be safe to call from apps.
4814     */
4815    protected void initializeFadingEdgeInternal(TypedArray a) {
4816        initScrollCache();
4817
4818        mScrollCache.fadingEdgeLength = a.getDimensionPixelSize(
4819                R.styleable.View_fadingEdgeLength,
4820                ViewConfiguration.get(mContext).getScaledFadingEdgeLength());
4821    }
4822
4823    /**
4824     * Returns the size of the vertical faded edges used to indicate that more
4825     * content in this view is visible.
4826     *
4827     * @return The size in pixels of the vertical faded edge or 0 if vertical
4828     *         faded edges are not enabled for this view.
4829     * @attr ref android.R.styleable#View_fadingEdgeLength
4830     */
4831    public int getVerticalFadingEdgeLength() {
4832        if (isVerticalFadingEdgeEnabled()) {
4833            ScrollabilityCache cache = mScrollCache;
4834            if (cache != null) {
4835                return cache.fadingEdgeLength;
4836            }
4837        }
4838        return 0;
4839    }
4840
4841    /**
4842     * Set the size of the faded edge used to indicate that more content in this
4843     * view is available.  Will not change whether the fading edge is enabled; use
4844     * {@link #setVerticalFadingEdgeEnabled(boolean)} or
4845     * {@link #setHorizontalFadingEdgeEnabled(boolean)} to enable the fading edge
4846     * for the vertical or horizontal fading edges.
4847     *
4848     * @param length The size in pixels of the faded edge used to indicate that more
4849     *        content in this view is visible.
4850     */
4851    public void setFadingEdgeLength(int length) {
4852        initScrollCache();
4853        mScrollCache.fadingEdgeLength = length;
4854    }
4855
4856    /**
4857     * Returns the size of the horizontal faded edges used to indicate that more
4858     * content in this view is visible.
4859     *
4860     * @return The size in pixels of the horizontal faded edge or 0 if horizontal
4861     *         faded edges are not enabled for this view.
4862     * @attr ref android.R.styleable#View_fadingEdgeLength
4863     */
4864    public int getHorizontalFadingEdgeLength() {
4865        if (isHorizontalFadingEdgeEnabled()) {
4866            ScrollabilityCache cache = mScrollCache;
4867            if (cache != null) {
4868                return cache.fadingEdgeLength;
4869            }
4870        }
4871        return 0;
4872    }
4873
4874    /**
4875     * Returns the width of the vertical scrollbar.
4876     *
4877     * @return The width in pixels of the vertical scrollbar or 0 if there
4878     *         is no vertical scrollbar.
4879     */
4880    public int getVerticalScrollbarWidth() {
4881        ScrollabilityCache cache = mScrollCache;
4882        if (cache != null) {
4883            ScrollBarDrawable scrollBar = cache.scrollBar;
4884            if (scrollBar != null) {
4885                int size = scrollBar.getSize(true);
4886                if (size <= 0) {
4887                    size = cache.scrollBarSize;
4888                }
4889                return size;
4890            }
4891            return 0;
4892        }
4893        return 0;
4894    }
4895
4896    /**
4897     * Returns the height of the horizontal scrollbar.
4898     *
4899     * @return The height in pixels of the horizontal scrollbar or 0 if
4900     *         there is no horizontal scrollbar.
4901     */
4902    protected int getHorizontalScrollbarHeight() {
4903        ScrollabilityCache cache = mScrollCache;
4904        if (cache != null) {
4905            ScrollBarDrawable scrollBar = cache.scrollBar;
4906            if (scrollBar != null) {
4907                int size = scrollBar.getSize(false);
4908                if (size <= 0) {
4909                    size = cache.scrollBarSize;
4910                }
4911                return size;
4912            }
4913            return 0;
4914        }
4915        return 0;
4916    }
4917
4918    /**
4919     * <p>
4920     * Initializes the scrollbars from a given set of styled attributes. This
4921     * method should be called by subclasses that need scrollbars and when an
4922     * instance of these subclasses is created programmatically rather than
4923     * being inflated from XML. This method is automatically called when the XML
4924     * is inflated.
4925     * </p>
4926     *
4927     * @param a the styled attributes set to initialize the scrollbars from
4928     *
4929     * @removed
4930     */
4931    protected void initializeScrollbars(TypedArray a) {
4932        // It's not safe to use this method from apps. The parameter 'a' must have been obtained
4933        // using the View filter array which is not available to the SDK. As such, internal
4934        // framework usage now uses initializeScrollbarsInternal and we grab a default
4935        // TypedArray with the right filter instead here.
4936        TypedArray arr = mContext.obtainStyledAttributes(com.android.internal.R.styleable.View);
4937
4938        initializeScrollbarsInternal(arr);
4939
4940        // We ignored the method parameter. Recycle the one we actually did use.
4941        arr.recycle();
4942    }
4943
4944    /**
4945     * <p>
4946     * Initializes the scrollbars from a given set of styled attributes. This
4947     * method should be called by subclasses that need scrollbars and when an
4948     * instance of these subclasses is created programmatically rather than
4949     * being inflated from XML. This method is automatically called when the XML
4950     * is inflated.
4951     * </p>
4952     *
4953     * @param a the styled attributes set to initialize the scrollbars from
4954     * @hide
4955     */
4956    protected void initializeScrollbarsInternal(TypedArray a) {
4957        initScrollCache();
4958
4959        final ScrollabilityCache scrollabilityCache = mScrollCache;
4960
4961        if (scrollabilityCache.scrollBar == null) {
4962            scrollabilityCache.scrollBar = new ScrollBarDrawable();
4963            scrollabilityCache.scrollBar.setCallback(this);
4964            scrollabilityCache.scrollBar.setState(getDrawableState());
4965        }
4966
4967        final boolean fadeScrollbars = a.getBoolean(R.styleable.View_fadeScrollbars, true);
4968
4969        if (!fadeScrollbars) {
4970            scrollabilityCache.state = ScrollabilityCache.ON;
4971        }
4972        scrollabilityCache.fadeScrollBars = fadeScrollbars;
4973
4974
4975        scrollabilityCache.scrollBarFadeDuration = a.getInt(
4976                R.styleable.View_scrollbarFadeDuration, ViewConfiguration
4977                        .getScrollBarFadeDuration());
4978        scrollabilityCache.scrollBarDefaultDelayBeforeFade = a.getInt(
4979                R.styleable.View_scrollbarDefaultDelayBeforeFade,
4980                ViewConfiguration.getScrollDefaultDelay());
4981
4982
4983        scrollabilityCache.scrollBarSize = a.getDimensionPixelSize(
4984                com.android.internal.R.styleable.View_scrollbarSize,
4985                ViewConfiguration.get(mContext).getScaledScrollBarSize());
4986
4987        Drawable track = a.getDrawable(R.styleable.View_scrollbarTrackHorizontal);
4988        scrollabilityCache.scrollBar.setHorizontalTrackDrawable(track);
4989
4990        Drawable thumb = a.getDrawable(R.styleable.View_scrollbarThumbHorizontal);
4991        if (thumb != null) {
4992            scrollabilityCache.scrollBar.setHorizontalThumbDrawable(thumb);
4993        }
4994
4995        boolean alwaysDraw = a.getBoolean(R.styleable.View_scrollbarAlwaysDrawHorizontalTrack,
4996                false);
4997        if (alwaysDraw) {
4998            scrollabilityCache.scrollBar.setAlwaysDrawHorizontalTrack(true);
4999        }
5000
5001        track = a.getDrawable(R.styleable.View_scrollbarTrackVertical);
5002        scrollabilityCache.scrollBar.setVerticalTrackDrawable(track);
5003
5004        thumb = a.getDrawable(R.styleable.View_scrollbarThumbVertical);
5005        if (thumb != null) {
5006            scrollabilityCache.scrollBar.setVerticalThumbDrawable(thumb);
5007        }
5008
5009        alwaysDraw = a.getBoolean(R.styleable.View_scrollbarAlwaysDrawVerticalTrack,
5010                false);
5011        if (alwaysDraw) {
5012            scrollabilityCache.scrollBar.setAlwaysDrawVerticalTrack(true);
5013        }
5014
5015        // Apply layout direction to the new Drawables if needed
5016        final int layoutDirection = getLayoutDirection();
5017        if (track != null) {
5018            track.setLayoutDirection(layoutDirection);
5019        }
5020        if (thumb != null) {
5021            thumb.setLayoutDirection(layoutDirection);
5022        }
5023
5024        // Re-apply user/background padding so that scrollbar(s) get added
5025        resolvePadding();
5026    }
5027
5028    private void initializeScrollIndicatorsInternal() {
5029        // Some day maybe we'll break this into top/left/start/etc. and let the
5030        // client control it. Until then, you can have any scroll indicator you
5031        // want as long as it's a 1dp foreground-colored rectangle.
5032        if (mScrollIndicatorDrawable == null) {
5033            mScrollIndicatorDrawable = mContext.getDrawable(R.drawable.scroll_indicator_material);
5034        }
5035    }
5036
5037    /**
5038     * <p>
5039     * Initalizes the scrollability cache if necessary.
5040     * </p>
5041     */
5042    private void initScrollCache() {
5043        if (mScrollCache == null) {
5044            mScrollCache = new ScrollabilityCache(ViewConfiguration.get(mContext), this);
5045        }
5046    }
5047
5048    private ScrollabilityCache getScrollCache() {
5049        initScrollCache();
5050        return mScrollCache;
5051    }
5052
5053    /**
5054     * Set the position of the vertical scroll bar. Should be one of
5055     * {@link #SCROLLBAR_POSITION_DEFAULT}, {@link #SCROLLBAR_POSITION_LEFT} or
5056     * {@link #SCROLLBAR_POSITION_RIGHT}.
5057     *
5058     * @param position Where the vertical scroll bar should be positioned.
5059     */
5060    public void setVerticalScrollbarPosition(int position) {
5061        if (mVerticalScrollbarPosition != position) {
5062            mVerticalScrollbarPosition = position;
5063            computeOpaqueFlags();
5064            resolvePadding();
5065        }
5066    }
5067
5068    /**
5069     * @return The position where the vertical scroll bar will show, if applicable.
5070     * @see #setVerticalScrollbarPosition(int)
5071     */
5072    public int getVerticalScrollbarPosition() {
5073        return mVerticalScrollbarPosition;
5074    }
5075
5076    /**
5077     * Sets the state of all scroll indicators.
5078     * <p>
5079     * See {@link #setScrollIndicators(int, int)} for usage information.
5080     *
5081     * @param indicators a bitmask of indicators that should be enabled, or
5082     *                   {@code 0} to disable all indicators
5083     * @see #setScrollIndicators(int, int)
5084     * @see #getScrollIndicators()
5085     * @attr ref android.R.styleable#View_scrollIndicators
5086     */
5087    public void setScrollIndicators(@ScrollIndicators int indicators) {
5088        setScrollIndicators(indicators,
5089                SCROLL_INDICATORS_PFLAG3_MASK >>> SCROLL_INDICATORS_TO_PFLAGS3_LSHIFT);
5090    }
5091
5092    /**
5093     * Sets the state of the scroll indicators specified by the mask. To change
5094     * all scroll indicators at once, see {@link #setScrollIndicators(int)}.
5095     * <p>
5096     * When a scroll indicator is enabled, it will be displayed if the view
5097     * can scroll in the direction of the indicator.
5098     * <p>
5099     * Multiple indicator types may be enabled or disabled by passing the
5100     * logical OR of the desired types. If multiple types are specified, they
5101     * will all be set to the same enabled state.
5102     * <p>
5103     * For example, to enable the top scroll indicatorExample: {@code setScrollIndicators
5104     *
5105     * @param indicators the indicator direction, or the logical OR of multiple
5106     *             indicator directions. One or more of:
5107     *             <ul>
5108     *               <li>{@link #SCROLL_INDICATOR_TOP}</li>
5109     *               <li>{@link #SCROLL_INDICATOR_BOTTOM}</li>
5110     *               <li>{@link #SCROLL_INDICATOR_LEFT}</li>
5111     *               <li>{@link #SCROLL_INDICATOR_RIGHT}</li>
5112     *               <li>{@link #SCROLL_INDICATOR_START}</li>
5113     *               <li>{@link #SCROLL_INDICATOR_END}</li>
5114     *             </ul>
5115     * @see #setScrollIndicators(int)
5116     * @see #getScrollIndicators()
5117     * @attr ref android.R.styleable#View_scrollIndicators
5118     */
5119    public void setScrollIndicators(@ScrollIndicators int indicators, @ScrollIndicators int mask) {
5120        // Shift and sanitize mask.
5121        mask <<= SCROLL_INDICATORS_TO_PFLAGS3_LSHIFT;
5122        mask &= SCROLL_INDICATORS_PFLAG3_MASK;
5123
5124        // Shift and mask indicators.
5125        indicators <<= SCROLL_INDICATORS_TO_PFLAGS3_LSHIFT;
5126        indicators &= mask;
5127
5128        // Merge with non-masked flags.
5129        final int updatedFlags = indicators | (mPrivateFlags3 & ~mask);
5130
5131        if (mPrivateFlags3 != updatedFlags) {
5132            mPrivateFlags3 = updatedFlags;
5133
5134            if (indicators != 0) {
5135                initializeScrollIndicatorsInternal();
5136            }
5137            invalidate();
5138        }
5139    }
5140
5141    /**
5142     * Returns a bitmask representing the enabled scroll indicators.
5143     * <p>
5144     * For example, if the top and left scroll indicators are enabled and all
5145     * other indicators are disabled, the return value will be
5146     * {@code View.SCROLL_INDICATOR_TOP | View.SCROLL_INDICATOR_LEFT}.
5147     * <p>
5148     * To check whether the bottom scroll indicator is enabled, use the value
5149     * of {@code (getScrollIndicators() & View.SCROLL_INDICATOR_BOTTOM) != 0}.
5150     *
5151     * @return a bitmask representing the enabled scroll indicators
5152     */
5153    @ScrollIndicators
5154    public int getScrollIndicators() {
5155        return (mPrivateFlags3 & SCROLL_INDICATORS_PFLAG3_MASK)
5156                >>> SCROLL_INDICATORS_TO_PFLAGS3_LSHIFT;
5157    }
5158
5159    ListenerInfo getListenerInfo() {
5160        if (mListenerInfo != null) {
5161            return mListenerInfo;
5162        }
5163        mListenerInfo = new ListenerInfo();
5164        return mListenerInfo;
5165    }
5166
5167    /**
5168     * Register a callback to be invoked when the scroll X or Y positions of
5169     * this view change.
5170     * <p>
5171     * <b>Note:</b> Some views handle scrolling independently from View and may
5172     * have their own separate listeners for scroll-type events. For example,
5173     * {@link android.widget.ListView ListView} allows clients to register an
5174     * {@link android.widget.ListView#setOnScrollListener(android.widget.AbsListView.OnScrollListener) AbsListView.OnScrollListener}
5175     * to listen for changes in list scroll position.
5176     *
5177     * @param l The listener to notify when the scroll X or Y position changes.
5178     * @see android.view.View#getScrollX()
5179     * @see android.view.View#getScrollY()
5180     */
5181    public void setOnScrollChangeListener(OnScrollChangeListener l) {
5182        getListenerInfo().mOnScrollChangeListener = l;
5183    }
5184
5185    /**
5186     * Register a callback to be invoked when focus of this view changed.
5187     *
5188     * @param l The callback that will run.
5189     */
5190    public void setOnFocusChangeListener(OnFocusChangeListener l) {
5191        getListenerInfo().mOnFocusChangeListener = l;
5192    }
5193
5194    /**
5195     * Add a listener that will be called when the bounds of the view change due to
5196     * layout processing.
5197     *
5198     * @param listener The listener that will be called when layout bounds change.
5199     */
5200    public void addOnLayoutChangeListener(OnLayoutChangeListener listener) {
5201        ListenerInfo li = getListenerInfo();
5202        if (li.mOnLayoutChangeListeners == null) {
5203            li.mOnLayoutChangeListeners = new ArrayList<OnLayoutChangeListener>();
5204        }
5205        if (!li.mOnLayoutChangeListeners.contains(listener)) {
5206            li.mOnLayoutChangeListeners.add(listener);
5207        }
5208    }
5209
5210    /**
5211     * Remove a listener for layout changes.
5212     *
5213     * @param listener The listener for layout bounds change.
5214     */
5215    public void removeOnLayoutChangeListener(OnLayoutChangeListener listener) {
5216        ListenerInfo li = mListenerInfo;
5217        if (li == null || li.mOnLayoutChangeListeners == null) {
5218            return;
5219        }
5220        li.mOnLayoutChangeListeners.remove(listener);
5221    }
5222
5223    /**
5224     * Add a listener for attach state changes.
5225     *
5226     * This listener will be called whenever this view is attached or detached
5227     * from a window. Remove the listener using
5228     * {@link #removeOnAttachStateChangeListener(OnAttachStateChangeListener)}.
5229     *
5230     * @param listener Listener to attach
5231     * @see #removeOnAttachStateChangeListener(OnAttachStateChangeListener)
5232     */
5233    public void addOnAttachStateChangeListener(OnAttachStateChangeListener listener) {
5234        ListenerInfo li = getListenerInfo();
5235        if (li.mOnAttachStateChangeListeners == null) {
5236            li.mOnAttachStateChangeListeners
5237                    = new CopyOnWriteArrayList<OnAttachStateChangeListener>();
5238        }
5239        li.mOnAttachStateChangeListeners.add(listener);
5240    }
5241
5242    /**
5243     * Remove a listener for attach state changes. The listener will receive no further
5244     * notification of window attach/detach events.
5245     *
5246     * @param listener Listener to remove
5247     * @see #addOnAttachStateChangeListener(OnAttachStateChangeListener)
5248     */
5249    public void removeOnAttachStateChangeListener(OnAttachStateChangeListener listener) {
5250        ListenerInfo li = mListenerInfo;
5251        if (li == null || li.mOnAttachStateChangeListeners == null) {
5252            return;
5253        }
5254        li.mOnAttachStateChangeListeners.remove(listener);
5255    }
5256
5257    /**
5258     * Returns the focus-change callback registered for this view.
5259     *
5260     * @return The callback, or null if one is not registered.
5261     */
5262    public OnFocusChangeListener getOnFocusChangeListener() {
5263        ListenerInfo li = mListenerInfo;
5264        return li != null ? li.mOnFocusChangeListener : null;
5265    }
5266
5267    /**
5268     * Register a callback to be invoked when this view is clicked. If this view is not
5269     * clickable, it becomes clickable.
5270     *
5271     * @param l The callback that will run
5272     *
5273     * @see #setClickable(boolean)
5274     */
5275    public void setOnClickListener(@Nullable OnClickListener l) {
5276        if (!isClickable()) {
5277            setClickable(true);
5278        }
5279        getListenerInfo().mOnClickListener = l;
5280    }
5281
5282    /**
5283     * Return whether this view has an attached OnClickListener.  Returns
5284     * true if there is a listener, false if there is none.
5285     */
5286    public boolean hasOnClickListeners() {
5287        ListenerInfo li = mListenerInfo;
5288        return (li != null && li.mOnClickListener != null);
5289    }
5290
5291    /**
5292     * Register a callback to be invoked when this view is clicked and held. If this view is not
5293     * long clickable, it becomes long clickable.
5294     *
5295     * @param l The callback that will run
5296     *
5297     * @see #setLongClickable(boolean)
5298     */
5299    public void setOnLongClickListener(@Nullable OnLongClickListener l) {
5300        if (!isLongClickable()) {
5301            setLongClickable(true);
5302        }
5303        getListenerInfo().mOnLongClickListener = l;
5304    }
5305
5306    /**
5307     * Register a callback to be invoked when this view is context clicked. If the view is not
5308     * context clickable, it becomes context clickable.
5309     *
5310     * @param l The callback that will run
5311     * @see #setContextClickable(boolean)
5312     */
5313    public void setOnContextClickListener(@Nullable OnContextClickListener l) {
5314        if (!isContextClickable()) {
5315            setContextClickable(true);
5316        }
5317        getListenerInfo().mOnContextClickListener = l;
5318    }
5319
5320    /**
5321     * Register a callback to be invoked when the context menu for this view is
5322     * being built. If this view is not long clickable, it becomes long clickable.
5323     *
5324     * @param l The callback that will run
5325     *
5326     */
5327    public void setOnCreateContextMenuListener(OnCreateContextMenuListener l) {
5328        if (!isLongClickable()) {
5329            setLongClickable(true);
5330        }
5331        getListenerInfo().mOnCreateContextMenuListener = l;
5332    }
5333
5334    /**
5335     * Call this view's OnClickListener, if it is defined.  Performs all normal
5336     * actions associated with clicking: reporting accessibility event, playing
5337     * a sound, etc.
5338     *
5339     * @return True there was an assigned OnClickListener that was called, false
5340     *         otherwise is returned.
5341     */
5342    public boolean performClick() {
5343        final boolean result;
5344        final ListenerInfo li = mListenerInfo;
5345        if (li != null && li.mOnClickListener != null) {
5346            playSoundEffect(SoundEffectConstants.CLICK);
5347            li.mOnClickListener.onClick(this);
5348            result = true;
5349        } else {
5350            result = false;
5351        }
5352
5353        sendAccessibilityEvent(AccessibilityEvent.TYPE_VIEW_CLICKED);
5354        return result;
5355    }
5356
5357    /**
5358     * Directly call any attached OnClickListener.  Unlike {@link #performClick()},
5359     * this only calls the listener, and does not do any associated clicking
5360     * actions like reporting an accessibility event.
5361     *
5362     * @return True there was an assigned OnClickListener that was called, false
5363     *         otherwise is returned.
5364     */
5365    public boolean callOnClick() {
5366        ListenerInfo li = mListenerInfo;
5367        if (li != null && li.mOnClickListener != null) {
5368            li.mOnClickListener.onClick(this);
5369            return true;
5370        }
5371        return false;
5372    }
5373
5374    /**
5375     * Call this view's OnLongClickListener, if it is defined. Invokes the context menu if the
5376     * OnLongClickListener did not consume the event.
5377     *
5378     * @return True if one of the above receivers consumed the event, false otherwise.
5379     */
5380    public boolean performLongClick() {
5381        sendAccessibilityEvent(AccessibilityEvent.TYPE_VIEW_LONG_CLICKED);
5382
5383        boolean handled = false;
5384        ListenerInfo li = mListenerInfo;
5385        if (li != null && li.mOnLongClickListener != null) {
5386            handled = li.mOnLongClickListener.onLongClick(View.this);
5387        }
5388        if (!handled) {
5389            handled = showContextMenu();
5390        }
5391        if (handled) {
5392            performHapticFeedback(HapticFeedbackConstants.LONG_PRESS);
5393        }
5394        return handled;
5395    }
5396
5397    /**
5398     * Call this view's OnContextClickListener, if it is defined.
5399     *
5400     * @return True if there was an assigned OnContextClickListener that consumed the event, false
5401     *         otherwise.
5402     */
5403    public boolean performContextClick() {
5404        sendAccessibilityEvent(AccessibilityEvent.TYPE_VIEW_CONTEXT_CLICKED);
5405
5406        boolean handled = false;
5407        ListenerInfo li = mListenerInfo;
5408        if (li != null && li.mOnContextClickListener != null) {
5409            handled = li.mOnContextClickListener.onContextClick(View.this);
5410        }
5411        if (handled) {
5412            performHapticFeedback(HapticFeedbackConstants.CONTEXT_CLICK);
5413        }
5414        return handled;
5415    }
5416
5417    /**
5418     * Performs button-related actions during a touch down event.
5419     *
5420     * @param event The event.
5421     * @return True if the down was consumed.
5422     *
5423     * @hide
5424     */
5425    protected boolean performButtonActionOnTouchDown(MotionEvent event) {
5426        if (event.getToolType(0) == MotionEvent.TOOL_TYPE_MOUSE &&
5427            (event.getButtonState() & MotionEvent.BUTTON_SECONDARY) != 0) {
5428            showContextMenu(event.getX(), event.getY());
5429            mPrivateFlags |= PFLAG_CANCEL_NEXT_UP_EVENT;
5430            return true;
5431        }
5432        return false;
5433    }
5434
5435    /**
5436     * Bring up the context menu for this view.
5437     *
5438     * @return Whether a context menu was displayed.
5439     */
5440    public boolean showContextMenu() {
5441        return getParent().showContextMenuForChild(this);
5442    }
5443
5444    /**
5445     * Bring up the context menu for this view, referring to the item under the specified point.
5446     *
5447     * @param x The referenced x coordinate.
5448     * @param y The referenced y coordinate.
5449     * @return Whether a context menu was displayed.
5450     */
5451    public boolean showContextMenu(float x, float y) {
5452        return getParent().showContextMenuForChild(this, x, y);
5453    }
5454
5455    /**
5456     * Start an action mode with the default type {@link ActionMode#TYPE_PRIMARY}.
5457     *
5458     * @param callback Callback that will control the lifecycle of the action mode
5459     * @return The new action mode if it is started, null otherwise
5460     *
5461     * @see ActionMode
5462     * @see #startActionMode(android.view.ActionMode.Callback, int)
5463     */
5464    public ActionMode startActionMode(ActionMode.Callback callback) {
5465        return startActionMode(callback, ActionMode.TYPE_PRIMARY);
5466    }
5467
5468    /**
5469     * Start an action mode with the given type.
5470     *
5471     * @param callback Callback that will control the lifecycle of the action mode
5472     * @param type One of {@link ActionMode#TYPE_PRIMARY} or {@link ActionMode#TYPE_FLOATING}.
5473     * @return The new action mode if it is started, null otherwise
5474     *
5475     * @see ActionMode
5476     */
5477    public ActionMode startActionMode(ActionMode.Callback callback, int type) {
5478        ViewParent parent = getParent();
5479        if (parent == null) return null;
5480        try {
5481            return parent.startActionModeForChild(this, callback, type);
5482        } catch (AbstractMethodError ame) {
5483            // Older implementations of custom views might not implement this.
5484            return parent.startActionModeForChild(this, callback);
5485        }
5486    }
5487
5488    /**
5489     * Call {@link Context#startActivityForResult(String, Intent, int, Bundle)} for the View's
5490     * Context, creating a unique View identifier to retrieve the result.
5491     *
5492     * @param intent The Intent to be started.
5493     * @param requestCode The request code to use.
5494     * @hide
5495     */
5496    public void startActivityForResult(Intent intent, int requestCode) {
5497        mStartActivityRequestWho = "@android:view:" + System.identityHashCode(this);
5498        getContext().startActivityForResult(mStartActivityRequestWho, intent, requestCode, null);
5499    }
5500
5501    /**
5502     * If this View corresponds to the calling who, dispatches the activity result.
5503     * @param who The identifier for the targeted View to receive the result.
5504     * @param requestCode The integer request code originally supplied to
5505     *                    startActivityForResult(), allowing you to identify who this
5506     *                    result came from.
5507     * @param resultCode The integer result code returned by the child activity
5508     *                   through its setResult().
5509     * @param data An Intent, which can return result data to the caller
5510     *               (various data can be attached to Intent "extras").
5511     * @return {@code true} if the activity result was dispatched.
5512     * @hide
5513     */
5514    public boolean dispatchActivityResult(
5515            String who, int requestCode, int resultCode, Intent data) {
5516        if (mStartActivityRequestWho != null && mStartActivityRequestWho.equals(who)) {
5517            onActivityResult(requestCode, resultCode, data);
5518            mStartActivityRequestWho = null;
5519            return true;
5520        }
5521        return false;
5522    }
5523
5524    /**
5525     * Receive the result from a previous call to {@link #startActivityForResult(Intent, int)}.
5526     *
5527     * @param requestCode The integer request code originally supplied to
5528     *                    startActivityForResult(), allowing you to identify who this
5529     *                    result came from.
5530     * @param resultCode The integer result code returned by the child activity
5531     *                   through its setResult().
5532     * @param data An Intent, which can return result data to the caller
5533     *               (various data can be attached to Intent "extras").
5534     * @hide
5535     */
5536    public void onActivityResult(int requestCode, int resultCode, Intent data) {
5537        // Do nothing.
5538    }
5539
5540    /**
5541     * Register a callback to be invoked when a hardware key is pressed in this view.
5542     * Key presses in software input methods will generally not trigger the methods of
5543     * this listener.
5544     * @param l the key listener to attach to this view
5545     */
5546    public void setOnKeyListener(OnKeyListener l) {
5547        getListenerInfo().mOnKeyListener = l;
5548    }
5549
5550    /**
5551     * Register a callback to be invoked when a touch event is sent to this view.
5552     * @param l the touch listener to attach to this view
5553     */
5554    public void setOnTouchListener(OnTouchListener l) {
5555        getListenerInfo().mOnTouchListener = l;
5556    }
5557
5558    /**
5559     * Register a callback to be invoked when a generic motion event is sent to this view.
5560     * @param l the generic motion listener to attach to this view
5561     */
5562    public void setOnGenericMotionListener(OnGenericMotionListener l) {
5563        getListenerInfo().mOnGenericMotionListener = l;
5564    }
5565
5566    /**
5567     * Register a callback to be invoked when a hover event is sent to this view.
5568     * @param l the hover listener to attach to this view
5569     */
5570    public void setOnHoverListener(OnHoverListener l) {
5571        getListenerInfo().mOnHoverListener = l;
5572    }
5573
5574    /**
5575     * Register a drag event listener callback object for this View. The parameter is
5576     * an implementation of {@link android.view.View.OnDragListener}. To send a drag event to a
5577     * View, the system calls the
5578     * {@link android.view.View.OnDragListener#onDrag(View,DragEvent)} method.
5579     * @param l An implementation of {@link android.view.View.OnDragListener}.
5580     */
5581    public void setOnDragListener(OnDragListener l) {
5582        getListenerInfo().mOnDragListener = l;
5583    }
5584
5585    /**
5586     * Give this view focus. This will cause
5587     * {@link #onFocusChanged(boolean, int, android.graphics.Rect)} to be called.
5588     *
5589     * Note: this does not check whether this {@link View} should get focus, it just
5590     * gives it focus no matter what.  It should only be called internally by framework
5591     * code that knows what it is doing, namely {@link #requestFocus(int, Rect)}.
5592     *
5593     * @param direction values are {@link View#FOCUS_UP}, {@link View#FOCUS_DOWN},
5594     *        {@link View#FOCUS_LEFT} or {@link View#FOCUS_RIGHT}. This is the direction which
5595     *        focus moved when requestFocus() is called. It may not always
5596     *        apply, in which case use the default View.FOCUS_DOWN.
5597     * @param previouslyFocusedRect The rectangle of the view that had focus
5598     *        prior in this View's coordinate system.
5599     */
5600    void handleFocusGainInternal(@FocusRealDirection int direction, Rect previouslyFocusedRect) {
5601        if (DBG) {
5602            System.out.println(this + " requestFocus()");
5603        }
5604
5605        if ((mPrivateFlags & PFLAG_FOCUSED) == 0) {
5606            mPrivateFlags |= PFLAG_FOCUSED;
5607
5608            View oldFocus = (mAttachInfo != null) ? getRootView().findFocus() : null;
5609
5610            if (mParent != null) {
5611                mParent.requestChildFocus(this, this);
5612            }
5613
5614            if (mAttachInfo != null) {
5615                mAttachInfo.mTreeObserver.dispatchOnGlobalFocusChange(oldFocus, this);
5616            }
5617
5618            onFocusChanged(true, direction, previouslyFocusedRect);
5619            refreshDrawableState();
5620        }
5621    }
5622
5623    /**
5624     * Populates <code>outRect</code> with the hotspot bounds. By default,
5625     * the hotspot bounds are identical to the screen bounds.
5626     *
5627     * @param outRect rect to populate with hotspot bounds
5628     * @hide Only for internal use by views and widgets.
5629     */
5630    public void getHotspotBounds(Rect outRect) {
5631        final Drawable background = getBackground();
5632        if (background != null) {
5633            background.getHotspotBounds(outRect);
5634        } else {
5635            getBoundsOnScreen(outRect);
5636        }
5637    }
5638
5639    /**
5640     * Request that a rectangle of this view be visible on the screen,
5641     * scrolling if necessary just enough.
5642     *
5643     * <p>A View should call this if it maintains some notion of which part
5644     * of its content is interesting.  For example, a text editing view
5645     * should call this when its cursor moves.
5646     *
5647     * @param rectangle The rectangle.
5648     * @return Whether any parent scrolled.
5649     */
5650    public boolean requestRectangleOnScreen(Rect rectangle) {
5651        return requestRectangleOnScreen(rectangle, false);
5652    }
5653
5654    /**
5655     * Request that a rectangle of this view be visible on the screen,
5656     * scrolling if necessary just enough.
5657     *
5658     * <p>A View should call this if it maintains some notion of which part
5659     * of its content is interesting.  For example, a text editing view
5660     * should call this when its cursor moves.
5661     *
5662     * <p>When <code>immediate</code> is set to true, scrolling will not be
5663     * animated.
5664     *
5665     * @param rectangle The rectangle.
5666     * @param immediate True to forbid animated scrolling, false otherwise
5667     * @return Whether any parent scrolled.
5668     */
5669    public boolean requestRectangleOnScreen(Rect rectangle, boolean immediate) {
5670        if (mParent == null) {
5671            return false;
5672        }
5673
5674        View child = this;
5675
5676        RectF position = (mAttachInfo != null) ? mAttachInfo.mTmpTransformRect : new RectF();
5677        position.set(rectangle);
5678
5679        ViewParent parent = mParent;
5680        boolean scrolled = false;
5681        while (parent != null) {
5682            rectangle.set((int) position.left, (int) position.top,
5683                    (int) position.right, (int) position.bottom);
5684
5685            scrolled |= parent.requestChildRectangleOnScreen(child,
5686                    rectangle, immediate);
5687
5688            if (!child.hasIdentityMatrix()) {
5689                child.getMatrix().mapRect(position);
5690            }
5691
5692            position.offset(child.mLeft, child.mTop);
5693
5694            if (!(parent instanceof View)) {
5695                break;
5696            }
5697
5698            View parentView = (View) parent;
5699
5700            position.offset(-parentView.getScrollX(), -parentView.getScrollY());
5701
5702            child = parentView;
5703            parent = child.getParent();
5704        }
5705
5706        return scrolled;
5707    }
5708
5709    /**
5710     * Called when this view wants to give up focus. If focus is cleared
5711     * {@link #onFocusChanged(boolean, int, android.graphics.Rect)} is called.
5712     * <p>
5713     * <strong>Note:</strong> When a View clears focus the framework is trying
5714     * to give focus to the first focusable View from the top. Hence, if this
5715     * View is the first from the top that can take focus, then all callbacks
5716     * related to clearing focus will be invoked after which the framework will
5717     * give focus to this view.
5718     * </p>
5719     */
5720    public void clearFocus() {
5721        if (DBG) {
5722            System.out.println(this + " clearFocus()");
5723        }
5724
5725        clearFocusInternal(null, true, true);
5726    }
5727
5728    /**
5729     * Clears focus from the view, optionally propagating the change up through
5730     * the parent hierarchy and requesting that the root view place new focus.
5731     *
5732     * @param propagate whether to propagate the change up through the parent
5733     *            hierarchy
5734     * @param refocus when propagate is true, specifies whether to request the
5735     *            root view place new focus
5736     */
5737    void clearFocusInternal(View focused, boolean propagate, boolean refocus) {
5738        if ((mPrivateFlags & PFLAG_FOCUSED) != 0) {
5739            mPrivateFlags &= ~PFLAG_FOCUSED;
5740
5741            if (propagate && mParent != null) {
5742                mParent.clearChildFocus(this);
5743            }
5744
5745            onFocusChanged(false, 0, null);
5746            refreshDrawableState();
5747
5748            if (propagate && (!refocus || !rootViewRequestFocus())) {
5749                notifyGlobalFocusCleared(this);
5750            }
5751        }
5752    }
5753
5754    void notifyGlobalFocusCleared(View oldFocus) {
5755        if (oldFocus != null && mAttachInfo != null) {
5756            mAttachInfo.mTreeObserver.dispatchOnGlobalFocusChange(oldFocus, null);
5757        }
5758    }
5759
5760    boolean rootViewRequestFocus() {
5761        final View root = getRootView();
5762        return root != null && root.requestFocus();
5763    }
5764
5765    /**
5766     * Called internally by the view system when a new view is getting focus.
5767     * This is what clears the old focus.
5768     * <p>
5769     * <b>NOTE:</b> The parent view's focused child must be updated manually
5770     * after calling this method. Otherwise, the view hierarchy may be left in
5771     * an inconstent state.
5772     */
5773    void unFocus(View focused) {
5774        if (DBG) {
5775            System.out.println(this + " unFocus()");
5776        }
5777
5778        clearFocusInternal(focused, false, false);
5779    }
5780
5781    /**
5782     * Returns true if this view has focus itself, or is the ancestor of the
5783     * view that has focus.
5784     *
5785     * @return True if this view has or contains focus, false otherwise.
5786     */
5787    @ViewDebug.ExportedProperty(category = "focus")
5788    public boolean hasFocus() {
5789        return (mPrivateFlags & PFLAG_FOCUSED) != 0;
5790    }
5791
5792    /**
5793     * Returns true if this view is focusable or if it contains a reachable View
5794     * for which {@link #hasFocusable()} returns true. A "reachable hasFocusable()"
5795     * is a View whose parents do not block descendants focus.
5796     *
5797     * Only {@link #VISIBLE} views are considered focusable.
5798     *
5799     * @return True if the view is focusable or if the view contains a focusable
5800     *         View, false otherwise.
5801     *
5802     * @see ViewGroup#FOCUS_BLOCK_DESCENDANTS
5803     * @see ViewGroup#getTouchscreenBlocksFocus()
5804     */
5805    public boolean hasFocusable() {
5806        if (!isFocusableInTouchMode()) {
5807            for (ViewParent p = mParent; p instanceof ViewGroup; p = p.getParent()) {
5808                final ViewGroup g = (ViewGroup) p;
5809                if (g.shouldBlockFocusForTouchscreen()) {
5810                    return false;
5811                }
5812            }
5813        }
5814        return (mViewFlags & VISIBILITY_MASK) == VISIBLE && isFocusable();
5815    }
5816
5817    /**
5818     * Called by the view system when the focus state of this view changes.
5819     * When the focus change event is caused by directional navigation, direction
5820     * and previouslyFocusedRect provide insight into where the focus is coming from.
5821     * When overriding, be sure to call up through to the super class so that
5822     * the standard focus handling will occur.
5823     *
5824     * @param gainFocus True if the View has focus; false otherwise.
5825     * @param direction The direction focus has moved when requestFocus()
5826     *                  is called to give this view focus. Values are
5827     *                  {@link #FOCUS_UP}, {@link #FOCUS_DOWN}, {@link #FOCUS_LEFT},
5828     *                  {@link #FOCUS_RIGHT}, {@link #FOCUS_FORWARD}, or {@link #FOCUS_BACKWARD}.
5829     *                  It may not always apply, in which case use the default.
5830     * @param previouslyFocusedRect The rectangle, in this view's coordinate
5831     *        system, of the previously focused view.  If applicable, this will be
5832     *        passed in as finer grained information about where the focus is coming
5833     *        from (in addition to direction).  Will be <code>null</code> otherwise.
5834     */
5835    @CallSuper
5836    protected void onFocusChanged(boolean gainFocus, @FocusDirection int direction,
5837            @Nullable Rect previouslyFocusedRect) {
5838        if (gainFocus) {
5839            sendAccessibilityEvent(AccessibilityEvent.TYPE_VIEW_FOCUSED);
5840        } else {
5841            notifyViewAccessibilityStateChangedIfNeeded(
5842                    AccessibilityEvent.CONTENT_CHANGE_TYPE_UNDEFINED);
5843        }
5844
5845        InputMethodManager imm = InputMethodManager.peekInstance();
5846        if (!gainFocus) {
5847            if (isPressed()) {
5848                setPressed(false);
5849            }
5850            if (imm != null && mAttachInfo != null
5851                    && mAttachInfo.mHasWindowFocus) {
5852                imm.focusOut(this);
5853            }
5854            onFocusLost();
5855        } else if (imm != null && mAttachInfo != null
5856                && mAttachInfo.mHasWindowFocus) {
5857            imm.focusIn(this);
5858        }
5859
5860        invalidate(true);
5861        ListenerInfo li = mListenerInfo;
5862        if (li != null && li.mOnFocusChangeListener != null) {
5863            li.mOnFocusChangeListener.onFocusChange(this, gainFocus);
5864        }
5865
5866        if (mAttachInfo != null) {
5867            mAttachInfo.mKeyDispatchState.reset(this);
5868        }
5869    }
5870
5871    /**
5872     * Sends an accessibility event of the given type. If accessibility is
5873     * not enabled this method has no effect. The default implementation calls
5874     * {@link #onInitializeAccessibilityEvent(AccessibilityEvent)} first
5875     * to populate information about the event source (this View), then calls
5876     * {@link #dispatchPopulateAccessibilityEvent(AccessibilityEvent)} to
5877     * populate the text content of the event source including its descendants,
5878     * and last calls
5879     * {@link ViewParent#requestSendAccessibilityEvent(View, AccessibilityEvent)}
5880     * on its parent to request sending of the event to interested parties.
5881     * <p>
5882     * If an {@link AccessibilityDelegate} has been specified via calling
5883     * {@link #setAccessibilityDelegate(AccessibilityDelegate)} its
5884     * {@link AccessibilityDelegate#sendAccessibilityEvent(View, int)} is
5885     * responsible for handling this call.
5886     * </p>
5887     *
5888     * @param eventType The type of the event to send, as defined by several types from
5889     * {@link android.view.accessibility.AccessibilityEvent}, such as
5890     * {@link android.view.accessibility.AccessibilityEvent#TYPE_VIEW_CLICKED} or
5891     * {@link android.view.accessibility.AccessibilityEvent#TYPE_VIEW_HOVER_ENTER}.
5892     *
5893     * @see #onInitializeAccessibilityEvent(AccessibilityEvent)
5894     * @see #dispatchPopulateAccessibilityEvent(AccessibilityEvent)
5895     * @see ViewParent#requestSendAccessibilityEvent(View, AccessibilityEvent)
5896     * @see AccessibilityDelegate
5897     */
5898    public void sendAccessibilityEvent(int eventType) {
5899        if (mAccessibilityDelegate != null) {
5900            mAccessibilityDelegate.sendAccessibilityEvent(this, eventType);
5901        } else {
5902            sendAccessibilityEventInternal(eventType);
5903        }
5904    }
5905
5906    /**
5907     * Convenience method for sending a {@link AccessibilityEvent#TYPE_ANNOUNCEMENT}
5908     * {@link AccessibilityEvent} to make an announcement which is related to some
5909     * sort of a context change for which none of the events representing UI transitions
5910     * is a good fit. For example, announcing a new page in a book. If accessibility
5911     * is not enabled this method does nothing.
5912     *
5913     * @param text The announcement text.
5914     */
5915    public void announceForAccessibility(CharSequence text) {
5916        if (AccessibilityManager.getInstance(mContext).isEnabled() && mParent != null) {
5917            AccessibilityEvent event = AccessibilityEvent.obtain(
5918                    AccessibilityEvent.TYPE_ANNOUNCEMENT);
5919            onInitializeAccessibilityEvent(event);
5920            event.getText().add(text);
5921            event.setContentDescription(null);
5922            mParent.requestSendAccessibilityEvent(this, event);
5923        }
5924    }
5925
5926    /**
5927     * @see #sendAccessibilityEvent(int)
5928     *
5929     * Note: Called from the default {@link AccessibilityDelegate}.
5930     *
5931     * @hide
5932     */
5933    public void sendAccessibilityEventInternal(int eventType) {
5934        if (AccessibilityManager.getInstance(mContext).isEnabled()) {
5935            sendAccessibilityEventUnchecked(AccessibilityEvent.obtain(eventType));
5936        }
5937    }
5938
5939    /**
5940     * This method behaves exactly as {@link #sendAccessibilityEvent(int)} but
5941     * takes as an argument an empty {@link AccessibilityEvent} and does not
5942     * perform a check whether accessibility is enabled.
5943     * <p>
5944     * If an {@link AccessibilityDelegate} has been specified via calling
5945     * {@link #setAccessibilityDelegate(AccessibilityDelegate)} its
5946     * {@link AccessibilityDelegate#sendAccessibilityEventUnchecked(View, AccessibilityEvent)}
5947     * is responsible for handling this call.
5948     * </p>
5949     *
5950     * @param event The event to send.
5951     *
5952     * @see #sendAccessibilityEvent(int)
5953     */
5954    public void sendAccessibilityEventUnchecked(AccessibilityEvent event) {
5955        if (mAccessibilityDelegate != null) {
5956            mAccessibilityDelegate.sendAccessibilityEventUnchecked(this, event);
5957        } else {
5958            sendAccessibilityEventUncheckedInternal(event);
5959        }
5960    }
5961
5962    /**
5963     * @see #sendAccessibilityEventUnchecked(AccessibilityEvent)
5964     *
5965     * Note: Called from the default {@link AccessibilityDelegate}.
5966     *
5967     * @hide
5968     */
5969    public void sendAccessibilityEventUncheckedInternal(AccessibilityEvent event) {
5970        if (!isShown()) {
5971            return;
5972        }
5973        onInitializeAccessibilityEvent(event);
5974        // Only a subset of accessibility events populates text content.
5975        if ((event.getEventType() & POPULATING_ACCESSIBILITY_EVENT_TYPES) != 0) {
5976            dispatchPopulateAccessibilityEvent(event);
5977        }
5978        // In the beginning we called #isShown(), so we know that getParent() is not null.
5979        getParent().requestSendAccessibilityEvent(this, event);
5980    }
5981
5982    /**
5983     * Dispatches an {@link AccessibilityEvent} to the {@link View} first and then
5984     * to its children for adding their text content to the event. Note that the
5985     * event text is populated in a separate dispatch path since we add to the
5986     * event not only the text of the source but also the text of all its descendants.
5987     * A typical implementation will call
5988     * {@link #onPopulateAccessibilityEvent(AccessibilityEvent)} on the this view
5989     * and then call the {@link #dispatchPopulateAccessibilityEvent(AccessibilityEvent)}
5990     * on each child. Override this method if custom population of the event text
5991     * content is required.
5992     * <p>
5993     * If an {@link AccessibilityDelegate} has been specified via calling
5994     * {@link #setAccessibilityDelegate(AccessibilityDelegate)} its
5995     * {@link AccessibilityDelegate#dispatchPopulateAccessibilityEvent(View, AccessibilityEvent)}
5996     * is responsible for handling this call.
5997     * </p>
5998     * <p>
5999     * <em>Note:</em> Accessibility events of certain types are not dispatched for
6000     * populating the event text via this method. For details refer to {@link AccessibilityEvent}.
6001     * </p>
6002     *
6003     * @param event The event.
6004     *
6005     * @return True if the event population was completed.
6006     */
6007    public boolean dispatchPopulateAccessibilityEvent(AccessibilityEvent event) {
6008        if (mAccessibilityDelegate != null) {
6009            return mAccessibilityDelegate.dispatchPopulateAccessibilityEvent(this, event);
6010        } else {
6011            return dispatchPopulateAccessibilityEventInternal(event);
6012        }
6013    }
6014
6015    /**
6016     * @see #dispatchPopulateAccessibilityEvent(AccessibilityEvent)
6017     *
6018     * Note: Called from the default {@link AccessibilityDelegate}.
6019     *
6020     * @hide
6021     */
6022    public boolean dispatchPopulateAccessibilityEventInternal(AccessibilityEvent event) {
6023        onPopulateAccessibilityEvent(event);
6024        return false;
6025    }
6026
6027    /**
6028     * Called from {@link #dispatchPopulateAccessibilityEvent(AccessibilityEvent)}
6029     * giving a chance to this View to populate the accessibility event with its
6030     * text content. While this method is free to modify event
6031     * attributes other than text content, doing so should normally be performed in
6032     * {@link #onInitializeAccessibilityEvent(AccessibilityEvent)}.
6033     * <p>
6034     * Example: Adding formatted date string to an accessibility event in addition
6035     *          to the text added by the super implementation:
6036     * <pre> public void onPopulateAccessibilityEvent(AccessibilityEvent event) {
6037     *     super.onPopulateAccessibilityEvent(event);
6038     *     final int flags = DateUtils.FORMAT_SHOW_DATE | DateUtils.FORMAT_SHOW_WEEKDAY;
6039     *     String selectedDateUtterance = DateUtils.formatDateTime(mContext,
6040     *         mCurrentDate.getTimeInMillis(), flags);
6041     *     event.getText().add(selectedDateUtterance);
6042     * }</pre>
6043     * <p>
6044     * If an {@link AccessibilityDelegate} has been specified via calling
6045     * {@link #setAccessibilityDelegate(AccessibilityDelegate)} its
6046     * {@link AccessibilityDelegate#onPopulateAccessibilityEvent(View, AccessibilityEvent)}
6047     * is responsible for handling this call.
6048     * </p>
6049     * <p class="note"><strong>Note:</strong> Always call the super implementation before adding
6050     * information to the event, in case the default implementation has basic information to add.
6051     * </p>
6052     *
6053     * @param event The accessibility event which to populate.
6054     *
6055     * @see #sendAccessibilityEvent(int)
6056     * @see #dispatchPopulateAccessibilityEvent(AccessibilityEvent)
6057     */
6058    @CallSuper
6059    public void onPopulateAccessibilityEvent(AccessibilityEvent event) {
6060        if (mAccessibilityDelegate != null) {
6061            mAccessibilityDelegate.onPopulateAccessibilityEvent(this, event);
6062        } else {
6063            onPopulateAccessibilityEventInternal(event);
6064        }
6065    }
6066
6067    /**
6068     * @see #onPopulateAccessibilityEvent(AccessibilityEvent)
6069     *
6070     * Note: Called from the default {@link AccessibilityDelegate}.
6071     *
6072     * @hide
6073     */
6074    public void onPopulateAccessibilityEventInternal(AccessibilityEvent event) {
6075    }
6076
6077    /**
6078     * Initializes an {@link AccessibilityEvent} with information about
6079     * this View which is the event source. In other words, the source of
6080     * an accessibility event is the view whose state change triggered firing
6081     * the event.
6082     * <p>
6083     * Example: Setting the password property of an event in addition
6084     *          to properties set by the super implementation:
6085     * <pre> public void onInitializeAccessibilityEvent(AccessibilityEvent event) {
6086     *     super.onInitializeAccessibilityEvent(event);
6087     *     event.setPassword(true);
6088     * }</pre>
6089     * <p>
6090     * If an {@link AccessibilityDelegate} has been specified via calling
6091     * {@link #setAccessibilityDelegate(AccessibilityDelegate)} its
6092     * {@link AccessibilityDelegate#onInitializeAccessibilityEvent(View, AccessibilityEvent)}
6093     * is responsible for handling this call.
6094     * </p>
6095     * <p class="note"><strong>Note:</strong> Always call the super implementation before adding
6096     * information to the event, in case the default implementation has basic information to add.
6097     * </p>
6098     * @param event The event to initialize.
6099     *
6100     * @see #sendAccessibilityEvent(int)
6101     * @see #dispatchPopulateAccessibilityEvent(AccessibilityEvent)
6102     */
6103    @CallSuper
6104    public void onInitializeAccessibilityEvent(AccessibilityEvent event) {
6105        if (mAccessibilityDelegate != null) {
6106            mAccessibilityDelegate.onInitializeAccessibilityEvent(this, event);
6107        } else {
6108            onInitializeAccessibilityEventInternal(event);
6109        }
6110    }
6111
6112    /**
6113     * @see #onInitializeAccessibilityEvent(AccessibilityEvent)
6114     *
6115     * Note: Called from the default {@link AccessibilityDelegate}.
6116     *
6117     * @hide
6118     */
6119    public void onInitializeAccessibilityEventInternal(AccessibilityEvent event) {
6120        event.setSource(this);
6121        event.setClassName(getAccessibilityClassName());
6122        event.setPackageName(getContext().getPackageName());
6123        event.setEnabled(isEnabled());
6124        event.setContentDescription(mContentDescription);
6125
6126        switch (event.getEventType()) {
6127            case AccessibilityEvent.TYPE_VIEW_FOCUSED: {
6128                ArrayList<View> focusablesTempList = (mAttachInfo != null)
6129                        ? mAttachInfo.mTempArrayList : new ArrayList<View>();
6130                getRootView().addFocusables(focusablesTempList, View.FOCUS_FORWARD, FOCUSABLES_ALL);
6131                event.setItemCount(focusablesTempList.size());
6132                event.setCurrentItemIndex(focusablesTempList.indexOf(this));
6133                if (mAttachInfo != null) {
6134                    focusablesTempList.clear();
6135                }
6136            } break;
6137            case AccessibilityEvent.TYPE_VIEW_TEXT_SELECTION_CHANGED: {
6138                CharSequence text = getIterableTextForAccessibility();
6139                if (text != null && text.length() > 0) {
6140                    event.setFromIndex(getAccessibilitySelectionStart());
6141                    event.setToIndex(getAccessibilitySelectionEnd());
6142                    event.setItemCount(text.length());
6143                }
6144            } break;
6145        }
6146    }
6147
6148    /**
6149     * Returns an {@link AccessibilityNodeInfo} representing this view from the
6150     * point of view of an {@link android.accessibilityservice.AccessibilityService}.
6151     * This method is responsible for obtaining an accessibility node info from a
6152     * pool of reusable instances and calling
6153     * {@link #onInitializeAccessibilityNodeInfo(AccessibilityNodeInfo)} on this view to
6154     * initialize the former.
6155     * <p>
6156     * Note: The client is responsible for recycling the obtained instance by calling
6157     *       {@link AccessibilityNodeInfo#recycle()} to minimize object creation.
6158     * </p>
6159     *
6160     * @return A populated {@link AccessibilityNodeInfo}.
6161     *
6162     * @see AccessibilityNodeInfo
6163     */
6164    public AccessibilityNodeInfo createAccessibilityNodeInfo() {
6165        if (mAccessibilityDelegate != null) {
6166            return mAccessibilityDelegate.createAccessibilityNodeInfo(this);
6167        } else {
6168            return createAccessibilityNodeInfoInternal();
6169        }
6170    }
6171
6172    /**
6173     * @see #createAccessibilityNodeInfo()
6174     *
6175     * @hide
6176     */
6177    public AccessibilityNodeInfo createAccessibilityNodeInfoInternal() {
6178        AccessibilityNodeProvider provider = getAccessibilityNodeProvider();
6179        if (provider != null) {
6180            return provider.createAccessibilityNodeInfo(AccessibilityNodeProvider.HOST_VIEW_ID);
6181        } else {
6182            AccessibilityNodeInfo info = AccessibilityNodeInfo.obtain(this);
6183            onInitializeAccessibilityNodeInfo(info);
6184            return info;
6185        }
6186    }
6187
6188    /**
6189     * Initializes an {@link AccessibilityNodeInfo} with information about this view.
6190     * The base implementation sets:
6191     * <ul>
6192     *   <li>{@link AccessibilityNodeInfo#setParent(View)},</li>
6193     *   <li>{@link AccessibilityNodeInfo#setBoundsInParent(Rect)},</li>
6194     *   <li>{@link AccessibilityNodeInfo#setBoundsInScreen(Rect)},</li>
6195     *   <li>{@link AccessibilityNodeInfo#setPackageName(CharSequence)},</li>
6196     *   <li>{@link AccessibilityNodeInfo#setClassName(CharSequence)},</li>
6197     *   <li>{@link AccessibilityNodeInfo#setContentDescription(CharSequence)},</li>
6198     *   <li>{@link AccessibilityNodeInfo#setEnabled(boolean)},</li>
6199     *   <li>{@link AccessibilityNodeInfo#setClickable(boolean)},</li>
6200     *   <li>{@link AccessibilityNodeInfo#setFocusable(boolean)},</li>
6201     *   <li>{@link AccessibilityNodeInfo#setFocused(boolean)},</li>
6202     *   <li>{@link AccessibilityNodeInfo#setLongClickable(boolean)},</li>
6203     *   <li>{@link AccessibilityNodeInfo#setSelected(boolean)},</li>
6204     *   <li>{@link AccessibilityNodeInfo#setContextClickable(boolean)}</li>
6205     * </ul>
6206     * <p>
6207     * Subclasses should override this method, call the super implementation,
6208     * and set additional attributes.
6209     * </p>
6210     * <p>
6211     * If an {@link AccessibilityDelegate} has been specified via calling
6212     * {@link #setAccessibilityDelegate(AccessibilityDelegate)} its
6213     * {@link AccessibilityDelegate#onInitializeAccessibilityNodeInfo(View, AccessibilityNodeInfo)}
6214     * is responsible for handling this call.
6215     * </p>
6216     *
6217     * @param info The instance to initialize.
6218     */
6219    @CallSuper
6220    public void onInitializeAccessibilityNodeInfo(AccessibilityNodeInfo info) {
6221        if (mAccessibilityDelegate != null) {
6222            mAccessibilityDelegate.onInitializeAccessibilityNodeInfo(this, info);
6223        } else {
6224            onInitializeAccessibilityNodeInfoInternal(info);
6225        }
6226    }
6227
6228    /**
6229     * Gets the location of this view in screen coordinates.
6230     *
6231     * @param outRect The output location
6232     * @hide
6233     */
6234    public void getBoundsOnScreen(Rect outRect) {
6235        getBoundsOnScreen(outRect, false);
6236    }
6237
6238    /**
6239     * Gets the location of this view in screen coordinates.
6240     *
6241     * @param outRect The output location
6242     * @param clipToParent Whether to clip child bounds to the parent ones.
6243     * @hide
6244     */
6245    public void getBoundsOnScreen(Rect outRect, boolean clipToParent) {
6246        if (mAttachInfo == null) {
6247            return;
6248        }
6249
6250        RectF position = mAttachInfo.mTmpTransformRect;
6251        position.set(0, 0, mRight - mLeft, mBottom - mTop);
6252
6253        if (!hasIdentityMatrix()) {
6254            getMatrix().mapRect(position);
6255        }
6256
6257        position.offset(mLeft, mTop);
6258
6259        ViewParent parent = mParent;
6260        while (parent instanceof View) {
6261            View parentView = (View) parent;
6262
6263            position.offset(-parentView.mScrollX, -parentView.mScrollY);
6264
6265            if (clipToParent) {
6266                position.left = Math.max(position.left, 0);
6267                position.top = Math.max(position.top, 0);
6268                position.right = Math.min(position.right, parentView.getWidth());
6269                position.bottom = Math.min(position.bottom, parentView.getHeight());
6270            }
6271
6272            if (!parentView.hasIdentityMatrix()) {
6273                parentView.getMatrix().mapRect(position);
6274            }
6275
6276            position.offset(parentView.mLeft, parentView.mTop);
6277
6278            parent = parentView.mParent;
6279        }
6280
6281        if (parent instanceof ViewRootImpl) {
6282            ViewRootImpl viewRootImpl = (ViewRootImpl) parent;
6283            position.offset(0, -viewRootImpl.mCurScrollY);
6284        }
6285
6286        position.offset(mAttachInfo.mWindowLeft, mAttachInfo.mWindowTop);
6287
6288        outRect.set((int) (position.left + 0.5f), (int) (position.top + 0.5f),
6289                (int) (position.right + 0.5f), (int) (position.bottom + 0.5f));
6290    }
6291
6292    /**
6293     * Return the class name of this object to be used for accessibility purposes.
6294     * Subclasses should only override this if they are implementing something that
6295     * should be seen as a completely new class of view when used by accessibility,
6296     * unrelated to the class it is deriving from.  This is used to fill in
6297     * {@link AccessibilityNodeInfo#setClassName AccessibilityNodeInfo.setClassName}.
6298     */
6299    public CharSequence getAccessibilityClassName() {
6300        return View.class.getName();
6301    }
6302
6303    /**
6304     * Called when assist structure is being retrieved from a view as part of
6305     * {@link android.app.Activity#onProvideAssistData Activity.onProvideAssistData}.
6306     * @param structure Fill in with structured view data.  The default implementation
6307     * fills in all data that can be inferred from the view itself.
6308     */
6309    public void onProvideStructure(ViewStructure structure) {
6310        final int id = mID;
6311        if (id > 0 && (id&0xff000000) != 0 && (id&0x00ff0000) != 0
6312                && (id&0x0000ffff) != 0) {
6313            String pkg, type, entry;
6314            try {
6315                final Resources res = getResources();
6316                entry = res.getResourceEntryName(id);
6317                type = res.getResourceTypeName(id);
6318                pkg = res.getResourcePackageName(id);
6319            } catch (Resources.NotFoundException e) {
6320                entry = type = pkg = null;
6321            }
6322            structure.setId(id, pkg, type, entry);
6323        } else {
6324            structure.setId(id, null, null, null);
6325        }
6326        structure.setDimens(mLeft, mTop, mScrollX, mScrollY, mRight - mLeft, mBottom - mTop);
6327        if (!hasIdentityMatrix()) {
6328            structure.setTransformation(getMatrix());
6329        }
6330        structure.setElevation(getZ());
6331        structure.setVisibility(getVisibility());
6332        structure.setEnabled(isEnabled());
6333        if (isClickable()) {
6334            structure.setClickable(true);
6335        }
6336        if (isFocusable()) {
6337            structure.setFocusable(true);
6338        }
6339        if (isFocused()) {
6340            structure.setFocused(true);
6341        }
6342        if (isAccessibilityFocused()) {
6343            structure.setAccessibilityFocused(true);
6344        }
6345        if (isSelected()) {
6346            structure.setSelected(true);
6347        }
6348        if (isActivated()) {
6349            structure.setActivated(true);
6350        }
6351        if (isLongClickable()) {
6352            structure.setLongClickable(true);
6353        }
6354        if (this instanceof Checkable) {
6355            structure.setCheckable(true);
6356            if (((Checkable)this).isChecked()) {
6357                structure.setChecked(true);
6358            }
6359        }
6360        if (isContextClickable()) {
6361            structure.setContextClickable(true);
6362        }
6363        structure.setClassName(getAccessibilityClassName().toString());
6364        structure.setContentDescription(getContentDescription());
6365    }
6366
6367    /**
6368     * Called when assist structure is being retrieved from a view as part of
6369     * {@link android.app.Activity#onProvideAssistData Activity.onProvideAssistData} to
6370     * generate additional virtual structure under this view.  The defaullt implementation
6371     * uses {@link #getAccessibilityNodeProvider()} to try to generate this from the
6372     * view's virtual accessibility nodes, if any.  You can override this for a more
6373     * optimal implementation providing this data.
6374     */
6375    public void onProvideVirtualStructure(ViewStructure structure) {
6376        AccessibilityNodeProvider provider = getAccessibilityNodeProvider();
6377        if (provider != null) {
6378            AccessibilityNodeInfo info = createAccessibilityNodeInfo();
6379            structure.setChildCount(1);
6380            ViewStructure root = structure.newChild(0);
6381            populateVirtualStructure(root, provider, info);
6382            info.recycle();
6383        }
6384    }
6385
6386    private void populateVirtualStructure(ViewStructure structure,
6387            AccessibilityNodeProvider provider, AccessibilityNodeInfo info) {
6388        structure.setId(AccessibilityNodeInfo.getVirtualDescendantId(info.getSourceNodeId()),
6389                null, null, null);
6390        Rect rect = structure.getTempRect();
6391        info.getBoundsInParent(rect);
6392        structure.setDimens(rect.left, rect.top, 0, 0, rect.width(), rect.height());
6393        structure.setVisibility(VISIBLE);
6394        structure.setEnabled(info.isEnabled());
6395        if (info.isClickable()) {
6396            structure.setClickable(true);
6397        }
6398        if (info.isFocusable()) {
6399            structure.setFocusable(true);
6400        }
6401        if (info.isFocused()) {
6402            structure.setFocused(true);
6403        }
6404        if (info.isAccessibilityFocused()) {
6405            structure.setAccessibilityFocused(true);
6406        }
6407        if (info.isSelected()) {
6408            structure.setSelected(true);
6409        }
6410        if (info.isLongClickable()) {
6411            structure.setLongClickable(true);
6412        }
6413        if (info.isCheckable()) {
6414            structure.setCheckable(true);
6415            if (info.isChecked()) {
6416                structure.setChecked(true);
6417            }
6418        }
6419        if (info.isContextClickable()) {
6420            structure.setContextClickable(true);
6421        }
6422        CharSequence cname = info.getClassName();
6423        structure.setClassName(cname != null ? cname.toString() : null);
6424        structure.setContentDescription(info.getContentDescription());
6425        if (info.getText() != null || info.getError() != null) {
6426            structure.setText(info.getText(), info.getTextSelectionStart(),
6427                    info.getTextSelectionEnd());
6428        }
6429        final int NCHILDREN = info.getChildCount();
6430        if (NCHILDREN > 0) {
6431            structure.setChildCount(NCHILDREN);
6432            for (int i=0; i<NCHILDREN; i++) {
6433                AccessibilityNodeInfo cinfo = provider.createAccessibilityNodeInfo(
6434                        AccessibilityNodeInfo.getVirtualDescendantId(info.getChildId(i)));
6435                ViewStructure child = structure.newChild(i);
6436                populateVirtualStructure(child, provider, cinfo);
6437                cinfo.recycle();
6438            }
6439        }
6440    }
6441
6442    /**
6443     * Dispatch creation of {@link ViewStructure} down the hierarchy.  The default
6444     * implementation calls {@link #onProvideStructure} and
6445     * {@link #onProvideVirtualStructure}.
6446     */
6447    public void dispatchProvideStructure(ViewStructure structure) {
6448        if (!isAssistBlocked()) {
6449            onProvideStructure(structure);
6450            onProvideVirtualStructure(structure);
6451        } else {
6452            structure.setClassName(getAccessibilityClassName().toString());
6453            structure.setAssistBlocked(true);
6454        }
6455    }
6456
6457    /**
6458     * @see #onInitializeAccessibilityNodeInfo(AccessibilityNodeInfo)
6459     *
6460     * Note: Called from the default {@link AccessibilityDelegate}.
6461     *
6462     * @hide
6463     */
6464    public void onInitializeAccessibilityNodeInfoInternal(AccessibilityNodeInfo info) {
6465        if (mAttachInfo == null) {
6466            return;
6467        }
6468
6469        Rect bounds = mAttachInfo.mTmpInvalRect;
6470
6471        getDrawingRect(bounds);
6472        info.setBoundsInParent(bounds);
6473
6474        getBoundsOnScreen(bounds, true);
6475        info.setBoundsInScreen(bounds);
6476
6477        ViewParent parent = getParentForAccessibility();
6478        if (parent instanceof View) {
6479            info.setParent((View) parent);
6480        }
6481
6482        if (mID != View.NO_ID) {
6483            View rootView = getRootView();
6484            if (rootView == null) {
6485                rootView = this;
6486            }
6487
6488            View label = rootView.findLabelForView(this, mID);
6489            if (label != null) {
6490                info.setLabeledBy(label);
6491            }
6492
6493            if ((mAttachInfo.mAccessibilityFetchFlags
6494                    & AccessibilityNodeInfo.FLAG_REPORT_VIEW_IDS) != 0
6495                    && Resources.resourceHasPackage(mID)) {
6496                try {
6497                    String viewId = getResources().getResourceName(mID);
6498                    info.setViewIdResourceName(viewId);
6499                } catch (Resources.NotFoundException nfe) {
6500                    /* ignore */
6501                }
6502            }
6503        }
6504
6505        if (mLabelForId != View.NO_ID) {
6506            View rootView = getRootView();
6507            if (rootView == null) {
6508                rootView = this;
6509            }
6510            View labeled = rootView.findViewInsideOutShouldExist(this, mLabelForId);
6511            if (labeled != null) {
6512                info.setLabelFor(labeled);
6513            }
6514        }
6515
6516        if (mAccessibilityTraversalBeforeId != View.NO_ID) {
6517            View rootView = getRootView();
6518            if (rootView == null) {
6519                rootView = this;
6520            }
6521            View next = rootView.findViewInsideOutShouldExist(this,
6522                    mAccessibilityTraversalBeforeId);
6523            if (next != null && next.includeForAccessibility()) {
6524                info.setTraversalBefore(next);
6525            }
6526        }
6527
6528        if (mAccessibilityTraversalAfterId != View.NO_ID) {
6529            View rootView = getRootView();
6530            if (rootView == null) {
6531                rootView = this;
6532            }
6533            View next = rootView.findViewInsideOutShouldExist(this,
6534                    mAccessibilityTraversalAfterId);
6535            if (next != null && next.includeForAccessibility()) {
6536                info.setTraversalAfter(next);
6537            }
6538        }
6539
6540        info.setVisibleToUser(isVisibleToUser());
6541
6542        info.setPackageName(mContext.getPackageName());
6543        info.setClassName(getAccessibilityClassName());
6544        info.setContentDescription(getContentDescription());
6545
6546        info.setEnabled(isEnabled());
6547        info.setClickable(isClickable());
6548        info.setFocusable(isFocusable());
6549        info.setFocused(isFocused());
6550        info.setAccessibilityFocused(isAccessibilityFocused());
6551        info.setSelected(isSelected());
6552        info.setLongClickable(isLongClickable());
6553        info.setContextClickable(isContextClickable());
6554        info.setLiveRegion(getAccessibilityLiveRegion());
6555
6556        // TODO: These make sense only if we are in an AdapterView but all
6557        // views can be selected. Maybe from accessibility perspective
6558        // we should report as selectable view in an AdapterView.
6559        info.addAction(AccessibilityNodeInfo.ACTION_SELECT);
6560        info.addAction(AccessibilityNodeInfo.ACTION_CLEAR_SELECTION);
6561
6562        if (isFocusable()) {
6563            if (isFocused()) {
6564                info.addAction(AccessibilityNodeInfo.ACTION_CLEAR_FOCUS);
6565            } else {
6566                info.addAction(AccessibilityNodeInfo.ACTION_FOCUS);
6567            }
6568        }
6569
6570        if (!isAccessibilityFocused()) {
6571            info.addAction(AccessibilityNodeInfo.ACTION_ACCESSIBILITY_FOCUS);
6572        } else {
6573            info.addAction(AccessibilityNodeInfo.ACTION_CLEAR_ACCESSIBILITY_FOCUS);
6574        }
6575
6576        if (isClickable() && isEnabled()) {
6577            info.addAction(AccessibilityNodeInfo.ACTION_CLICK);
6578        }
6579
6580        if (isLongClickable() && isEnabled()) {
6581            info.addAction(AccessibilityNodeInfo.ACTION_LONG_CLICK);
6582        }
6583
6584        if (isContextClickable() && isEnabled()) {
6585            info.addAction(AccessibilityAction.ACTION_CONTEXT_CLICK);
6586        }
6587
6588        CharSequence text = getIterableTextForAccessibility();
6589        if (text != null && text.length() > 0) {
6590            info.setTextSelection(getAccessibilitySelectionStart(), getAccessibilitySelectionEnd());
6591
6592            info.addAction(AccessibilityNodeInfo.ACTION_SET_SELECTION);
6593            info.addAction(AccessibilityNodeInfo.ACTION_NEXT_AT_MOVEMENT_GRANULARITY);
6594            info.addAction(AccessibilityNodeInfo.ACTION_PREVIOUS_AT_MOVEMENT_GRANULARITY);
6595            info.setMovementGranularities(AccessibilityNodeInfo.MOVEMENT_GRANULARITY_CHARACTER
6596                    | AccessibilityNodeInfo.MOVEMENT_GRANULARITY_WORD
6597                    | AccessibilityNodeInfo.MOVEMENT_GRANULARITY_PARAGRAPH);
6598        }
6599
6600        info.addAction(AccessibilityAction.ACTION_SHOW_ON_SCREEN);
6601    }
6602
6603    private View findLabelForView(View view, int labeledId) {
6604        if (mMatchLabelForPredicate == null) {
6605            mMatchLabelForPredicate = new MatchLabelForPredicate();
6606        }
6607        mMatchLabelForPredicate.mLabeledId = labeledId;
6608        return findViewByPredicateInsideOut(view, mMatchLabelForPredicate);
6609    }
6610
6611    /**
6612     * Computes whether this view is visible to the user. Such a view is
6613     * attached, visible, all its predecessors are visible, it is not clipped
6614     * entirely by its predecessors, and has an alpha greater than zero.
6615     *
6616     * @return Whether the view is visible on the screen.
6617     *
6618     * @hide
6619     */
6620    protected boolean isVisibleToUser() {
6621        return isVisibleToUser(null);
6622    }
6623
6624    /**
6625     * Computes whether the given portion of this view is visible to the user.
6626     * Such a view is attached, visible, all its predecessors are visible,
6627     * has an alpha greater than zero, and the specified portion is not
6628     * clipped entirely by its predecessors.
6629     *
6630     * @param boundInView the portion of the view to test; coordinates should be relative; may be
6631     *                    <code>null</code>, and the entire view will be tested in this case.
6632     *                    When <code>true</code> is returned by the function, the actual visible
6633     *                    region will be stored in this parameter; that is, if boundInView is fully
6634     *                    contained within the view, no modification will be made, otherwise regions
6635     *                    outside of the visible area of the view will be clipped.
6636     *
6637     * @return Whether the specified portion of the view is visible on the screen.
6638     *
6639     * @hide
6640     */
6641    protected boolean isVisibleToUser(Rect boundInView) {
6642        if (mAttachInfo != null) {
6643            // Attached to invisible window means this view is not visible.
6644            if (mAttachInfo.mWindowVisibility != View.VISIBLE) {
6645                return false;
6646            }
6647            // An invisible predecessor or one with alpha zero means
6648            // that this view is not visible to the user.
6649            Object current = this;
6650            while (current instanceof View) {
6651                View view = (View) current;
6652                // We have attach info so this view is attached and there is no
6653                // need to check whether we reach to ViewRootImpl on the way up.
6654                if (view.getAlpha() <= 0 || view.getTransitionAlpha() <= 0 ||
6655                        view.getVisibility() != VISIBLE) {
6656                    return false;
6657                }
6658                current = view.mParent;
6659            }
6660            // Check if the view is entirely covered by its predecessors.
6661            Rect visibleRect = mAttachInfo.mTmpInvalRect;
6662            Point offset = mAttachInfo.mPoint;
6663            if (!getGlobalVisibleRect(visibleRect, offset)) {
6664                return false;
6665            }
6666            // Check if the visible portion intersects the rectangle of interest.
6667            if (boundInView != null) {
6668                visibleRect.offset(-offset.x, -offset.y);
6669                return boundInView.intersect(visibleRect);
6670            }
6671            return true;
6672        }
6673        return false;
6674    }
6675
6676    /**
6677     * Returns the delegate for implementing accessibility support via
6678     * composition. For more details see {@link AccessibilityDelegate}.
6679     *
6680     * @return The delegate, or null if none set.
6681     *
6682     * @hide
6683     */
6684    public AccessibilityDelegate getAccessibilityDelegate() {
6685        return mAccessibilityDelegate;
6686    }
6687
6688    /**
6689     * Sets a delegate for implementing accessibility support via composition
6690     * (as opposed to inheritance). For more details, see
6691     * {@link AccessibilityDelegate}.
6692     * <p>
6693     * <strong>Note:</strong> On platform versions prior to
6694     * {@link android.os.Build.VERSION_CODES#M API 23}, delegate methods on
6695     * views in the {@code android.widget.*} package are called <i>before</i>
6696     * host methods. This prevents certain properties such as class name from
6697     * being modified by overriding
6698     * {@link AccessibilityDelegate#onInitializeAccessibilityNodeInfo(View, AccessibilityNodeInfo)},
6699     * as any changes will be overwritten by the host class.
6700     * <p>
6701     * Starting in {@link android.os.Build.VERSION_CODES#M API 23}, delegate
6702     * methods are called <i>after</i> host methods, which all properties to be
6703     * modified without being overwritten by the host class.
6704     *
6705     * @param delegate the object to which accessibility method calls should be
6706     *                 delegated
6707     * @see AccessibilityDelegate
6708     */
6709    public void setAccessibilityDelegate(@Nullable AccessibilityDelegate delegate) {
6710        mAccessibilityDelegate = delegate;
6711    }
6712
6713    /**
6714     * Gets the provider for managing a virtual view hierarchy rooted at this View
6715     * and reported to {@link android.accessibilityservice.AccessibilityService}s
6716     * that explore the window content.
6717     * <p>
6718     * If this method returns an instance, this instance is responsible for managing
6719     * {@link AccessibilityNodeInfo}s describing the virtual sub-tree rooted at this
6720     * View including the one representing the View itself. Similarly the returned
6721     * instance is responsible for performing accessibility actions on any virtual
6722     * view or the root view itself.
6723     * </p>
6724     * <p>
6725     * If an {@link AccessibilityDelegate} has been specified via calling
6726     * {@link #setAccessibilityDelegate(AccessibilityDelegate)} its
6727     * {@link AccessibilityDelegate#getAccessibilityNodeProvider(View)}
6728     * is responsible for handling this call.
6729     * </p>
6730     *
6731     * @return The provider.
6732     *
6733     * @see AccessibilityNodeProvider
6734     */
6735    public AccessibilityNodeProvider getAccessibilityNodeProvider() {
6736        if (mAccessibilityDelegate != null) {
6737            return mAccessibilityDelegate.getAccessibilityNodeProvider(this);
6738        } else {
6739            return null;
6740        }
6741    }
6742
6743    /**
6744     * Gets the unique identifier of this view on the screen for accessibility purposes.
6745     * If this {@link View} is not attached to any window, {@value #NO_ID} is returned.
6746     *
6747     * @return The view accessibility id.
6748     *
6749     * @hide
6750     */
6751    public int getAccessibilityViewId() {
6752        if (mAccessibilityViewId == NO_ID) {
6753            mAccessibilityViewId = sNextAccessibilityViewId++;
6754        }
6755        return mAccessibilityViewId;
6756    }
6757
6758    /**
6759     * Gets the unique identifier of the window in which this View reseides.
6760     *
6761     * @return The window accessibility id.
6762     *
6763     * @hide
6764     */
6765    public int getAccessibilityWindowId() {
6766        return mAttachInfo != null ? mAttachInfo.mAccessibilityWindowId
6767                : AccessibilityNodeInfo.UNDEFINED_ITEM_ID;
6768    }
6769
6770    /**
6771     * Returns the {@link View}'s content description.
6772     * <p>
6773     * <strong>Note:</strong> Do not override this method, as it will have no
6774     * effect on the content description presented to accessibility services.
6775     * You must call {@link #setContentDescription(CharSequence)} to modify the
6776     * content description.
6777     *
6778     * @return the content description
6779     * @see #setContentDescription(CharSequence)
6780     * @attr ref android.R.styleable#View_contentDescription
6781     */
6782    @ViewDebug.ExportedProperty(category = "accessibility")
6783    public CharSequence getContentDescription() {
6784        return mContentDescription;
6785    }
6786
6787    /**
6788     * Sets the {@link View}'s content description.
6789     * <p>
6790     * A content description briefly describes the view and is primarily used
6791     * for accessibility support to determine how a view should be presented to
6792     * the user. In the case of a view with no textual representation, such as
6793     * {@link android.widget.ImageButton}, a useful content description
6794     * explains what the view does. For example, an image button with a phone
6795     * icon that is used to place a call may use "Call" as its content
6796     * description. An image of a floppy disk that is used to save a file may
6797     * use "Save".
6798     *
6799     * @param contentDescription The content description.
6800     * @see #getContentDescription()
6801     * @attr ref android.R.styleable#View_contentDescription
6802     */
6803    @RemotableViewMethod
6804    public void setContentDescription(CharSequence contentDescription) {
6805        if (mContentDescription == null) {
6806            if (contentDescription == null) {
6807                return;
6808            }
6809        } else if (mContentDescription.equals(contentDescription)) {
6810            return;
6811        }
6812        mContentDescription = contentDescription;
6813        final boolean nonEmptyDesc = contentDescription != null && contentDescription.length() > 0;
6814        if (nonEmptyDesc && getImportantForAccessibility() == IMPORTANT_FOR_ACCESSIBILITY_AUTO) {
6815            setImportantForAccessibility(IMPORTANT_FOR_ACCESSIBILITY_YES);
6816            notifySubtreeAccessibilityStateChangedIfNeeded();
6817        } else {
6818            notifyViewAccessibilityStateChangedIfNeeded(
6819                    AccessibilityEvent.CONTENT_CHANGE_TYPE_CONTENT_DESCRIPTION);
6820        }
6821    }
6822
6823    /**
6824     * Sets the id of a view before which this one is visited in accessibility traversal.
6825     * A screen-reader must visit the content of this view before the content of the one
6826     * it precedes. For example, if view B is set to be before view A, then a screen-reader
6827     * will traverse the entire content of B before traversing the entire content of A,
6828     * regardles of what traversal strategy it is using.
6829     * <p>
6830     * Views that do not have specified before/after relationships are traversed in order
6831     * determined by the screen-reader.
6832     * </p>
6833     * <p>
6834     * Setting that this view is before a view that is not important for accessibility
6835     * or if this view is not important for accessibility will have no effect as the
6836     * screen-reader is not aware of unimportant views.
6837     * </p>
6838     *
6839     * @param beforeId The id of a view this one precedes in accessibility traversal.
6840     *
6841     * @attr ref android.R.styleable#View_accessibilityTraversalBefore
6842     *
6843     * @see #setImportantForAccessibility(int)
6844     */
6845    @RemotableViewMethod
6846    public void setAccessibilityTraversalBefore(int beforeId) {
6847        if (mAccessibilityTraversalBeforeId == beforeId) {
6848            return;
6849        }
6850        mAccessibilityTraversalBeforeId = beforeId;
6851        notifyViewAccessibilityStateChangedIfNeeded(
6852                AccessibilityEvent.CONTENT_CHANGE_TYPE_UNDEFINED);
6853    }
6854
6855    /**
6856     * Gets the id of a view before which this one is visited in accessibility traversal.
6857     *
6858     * @return The id of a view this one precedes in accessibility traversal if
6859     *         specified, otherwise {@link #NO_ID}.
6860     *
6861     * @see #setAccessibilityTraversalBefore(int)
6862     */
6863    public int getAccessibilityTraversalBefore() {
6864        return mAccessibilityTraversalBeforeId;
6865    }
6866
6867    /**
6868     * Sets the id of a view after which this one is visited in accessibility traversal.
6869     * A screen-reader must visit the content of the other view before the content of this
6870     * one. For example, if view B is set to be after view A, then a screen-reader
6871     * will traverse the entire content of A before traversing the entire content of B,
6872     * regardles of what traversal strategy it is using.
6873     * <p>
6874     * Views that do not have specified before/after relationships are traversed in order
6875     * determined by the screen-reader.
6876     * </p>
6877     * <p>
6878     * Setting that this view is after a view that is not important for accessibility
6879     * or if this view is not important for accessibility will have no effect as the
6880     * screen-reader is not aware of unimportant views.
6881     * </p>
6882     *
6883     * @param afterId The id of a view this one succedees in accessibility traversal.
6884     *
6885     * @attr ref android.R.styleable#View_accessibilityTraversalAfter
6886     *
6887     * @see #setImportantForAccessibility(int)
6888     */
6889    @RemotableViewMethod
6890    public void setAccessibilityTraversalAfter(int afterId) {
6891        if (mAccessibilityTraversalAfterId == afterId) {
6892            return;
6893        }
6894        mAccessibilityTraversalAfterId = afterId;
6895        notifyViewAccessibilityStateChangedIfNeeded(
6896                AccessibilityEvent.CONTENT_CHANGE_TYPE_UNDEFINED);
6897    }
6898
6899    /**
6900     * Gets the id of a view after which this one is visited in accessibility traversal.
6901     *
6902     * @return The id of a view this one succeedes in accessibility traversal if
6903     *         specified, otherwise {@link #NO_ID}.
6904     *
6905     * @see #setAccessibilityTraversalAfter(int)
6906     */
6907    public int getAccessibilityTraversalAfter() {
6908        return mAccessibilityTraversalAfterId;
6909    }
6910
6911    /**
6912     * Gets the id of a view for which this view serves as a label for
6913     * accessibility purposes.
6914     *
6915     * @return The labeled view id.
6916     */
6917    @ViewDebug.ExportedProperty(category = "accessibility")
6918    public int getLabelFor() {
6919        return mLabelForId;
6920    }
6921
6922    /**
6923     * Sets the id of a view for which this view serves as a label for
6924     * accessibility purposes.
6925     *
6926     * @param id The labeled view id.
6927     */
6928    @RemotableViewMethod
6929    public void setLabelFor(@IdRes int id) {
6930        if (mLabelForId == id) {
6931            return;
6932        }
6933        mLabelForId = id;
6934        if (mLabelForId != View.NO_ID
6935                && mID == View.NO_ID) {
6936            mID = generateViewId();
6937        }
6938        notifyViewAccessibilityStateChangedIfNeeded(
6939                AccessibilityEvent.CONTENT_CHANGE_TYPE_UNDEFINED);
6940    }
6941
6942    /**
6943     * Invoked whenever this view loses focus, either by losing window focus or by losing
6944     * focus within its window. This method can be used to clear any state tied to the
6945     * focus. For instance, if a button is held pressed with the trackball and the window
6946     * loses focus, this method can be used to cancel the press.
6947     *
6948     * Subclasses of View overriding this method should always call super.onFocusLost().
6949     *
6950     * @see #onFocusChanged(boolean, int, android.graphics.Rect)
6951     * @see #onWindowFocusChanged(boolean)
6952     *
6953     * @hide pending API council approval
6954     */
6955    @CallSuper
6956    protected void onFocusLost() {
6957        resetPressedState();
6958    }
6959
6960    private void resetPressedState() {
6961        if ((mViewFlags & ENABLED_MASK) == DISABLED) {
6962            return;
6963        }
6964
6965        if (isPressed()) {
6966            setPressed(false);
6967
6968            if (!mHasPerformedLongPress) {
6969                removeLongPressCallback();
6970            }
6971        }
6972    }
6973
6974    /**
6975     * Returns true if this view has focus
6976     *
6977     * @return True if this view has focus, false otherwise.
6978     */
6979    @ViewDebug.ExportedProperty(category = "focus")
6980    public boolean isFocused() {
6981        return (mPrivateFlags & PFLAG_FOCUSED) != 0;
6982    }
6983
6984    /**
6985     * Find the view in the hierarchy rooted at this view that currently has
6986     * focus.
6987     *
6988     * @return The view that currently has focus, or null if no focused view can
6989     *         be found.
6990     */
6991    public View findFocus() {
6992        return (mPrivateFlags & PFLAG_FOCUSED) != 0 ? this : null;
6993    }
6994
6995    /**
6996     * Indicates whether this view is one of the set of scrollable containers in
6997     * its window.
6998     *
6999     * @return whether this view is one of the set of scrollable containers in
7000     * its window
7001     *
7002     * @attr ref android.R.styleable#View_isScrollContainer
7003     */
7004    public boolean isScrollContainer() {
7005        return (mPrivateFlags & PFLAG_SCROLL_CONTAINER_ADDED) != 0;
7006    }
7007
7008    /**
7009     * Change whether this view is one of the set of scrollable containers in
7010     * its window.  This will be used to determine whether the window can
7011     * resize or must pan when a soft input area is open -- scrollable
7012     * containers allow the window to use resize mode since the container
7013     * will appropriately shrink.
7014     *
7015     * @attr ref android.R.styleable#View_isScrollContainer
7016     */
7017    public void setScrollContainer(boolean isScrollContainer) {
7018        if (isScrollContainer) {
7019            if (mAttachInfo != null && (mPrivateFlags&PFLAG_SCROLL_CONTAINER_ADDED) == 0) {
7020                mAttachInfo.mScrollContainers.add(this);
7021                mPrivateFlags |= PFLAG_SCROLL_CONTAINER_ADDED;
7022            }
7023            mPrivateFlags |= PFLAG_SCROLL_CONTAINER;
7024        } else {
7025            if ((mPrivateFlags&PFLAG_SCROLL_CONTAINER_ADDED) != 0) {
7026                mAttachInfo.mScrollContainers.remove(this);
7027            }
7028            mPrivateFlags &= ~(PFLAG_SCROLL_CONTAINER|PFLAG_SCROLL_CONTAINER_ADDED);
7029        }
7030    }
7031
7032    /**
7033     * Returns the quality of the drawing cache.
7034     *
7035     * @return One of {@link #DRAWING_CACHE_QUALITY_AUTO},
7036     *         {@link #DRAWING_CACHE_QUALITY_LOW}, or {@link #DRAWING_CACHE_QUALITY_HIGH}
7037     *
7038     * @see #setDrawingCacheQuality(int)
7039     * @see #setDrawingCacheEnabled(boolean)
7040     * @see #isDrawingCacheEnabled()
7041     *
7042     * @attr ref android.R.styleable#View_drawingCacheQuality
7043     */
7044    @DrawingCacheQuality
7045    public int getDrawingCacheQuality() {
7046        return mViewFlags & DRAWING_CACHE_QUALITY_MASK;
7047    }
7048
7049    /**
7050     * Set the drawing cache quality of this view. This value is used only when the
7051     * drawing cache is enabled
7052     *
7053     * @param quality One of {@link #DRAWING_CACHE_QUALITY_AUTO},
7054     *        {@link #DRAWING_CACHE_QUALITY_LOW}, or {@link #DRAWING_CACHE_QUALITY_HIGH}
7055     *
7056     * @see #getDrawingCacheQuality()
7057     * @see #setDrawingCacheEnabled(boolean)
7058     * @see #isDrawingCacheEnabled()
7059     *
7060     * @attr ref android.R.styleable#View_drawingCacheQuality
7061     */
7062    public void setDrawingCacheQuality(@DrawingCacheQuality int quality) {
7063        setFlags(quality, DRAWING_CACHE_QUALITY_MASK);
7064    }
7065
7066    /**
7067     * Returns whether the screen should remain on, corresponding to the current
7068     * value of {@link #KEEP_SCREEN_ON}.
7069     *
7070     * @return Returns true if {@link #KEEP_SCREEN_ON} is set.
7071     *
7072     * @see #setKeepScreenOn(boolean)
7073     *
7074     * @attr ref android.R.styleable#View_keepScreenOn
7075     */
7076    public boolean getKeepScreenOn() {
7077        return (mViewFlags & KEEP_SCREEN_ON) != 0;
7078    }
7079
7080    /**
7081     * Controls whether the screen should remain on, modifying the
7082     * value of {@link #KEEP_SCREEN_ON}.
7083     *
7084     * @param keepScreenOn Supply true to set {@link #KEEP_SCREEN_ON}.
7085     *
7086     * @see #getKeepScreenOn()
7087     *
7088     * @attr ref android.R.styleable#View_keepScreenOn
7089     */
7090    public void setKeepScreenOn(boolean keepScreenOn) {
7091        setFlags(keepScreenOn ? KEEP_SCREEN_ON : 0, KEEP_SCREEN_ON);
7092    }
7093
7094    /**
7095     * Gets the id of the view to use when the next focus is {@link #FOCUS_LEFT}.
7096     * @return The next focus ID, or {@link #NO_ID} if the framework should decide automatically.
7097     *
7098     * @attr ref android.R.styleable#View_nextFocusLeft
7099     */
7100    public int getNextFocusLeftId() {
7101        return mNextFocusLeftId;
7102    }
7103
7104    /**
7105     * Sets the id of the view to use when the next focus is {@link #FOCUS_LEFT}.
7106     * @param nextFocusLeftId The next focus ID, or {@link #NO_ID} if the framework should
7107     * decide automatically.
7108     *
7109     * @attr ref android.R.styleable#View_nextFocusLeft
7110     */
7111    public void setNextFocusLeftId(int nextFocusLeftId) {
7112        mNextFocusLeftId = nextFocusLeftId;
7113    }
7114
7115    /**
7116     * Gets the id of the view to use when the next focus is {@link #FOCUS_RIGHT}.
7117     * @return The next focus ID, or {@link #NO_ID} if the framework should decide automatically.
7118     *
7119     * @attr ref android.R.styleable#View_nextFocusRight
7120     */
7121    public int getNextFocusRightId() {
7122        return mNextFocusRightId;
7123    }
7124
7125    /**
7126     * Sets the id of the view to use when the next focus is {@link #FOCUS_RIGHT}.
7127     * @param nextFocusRightId The next focus ID, or {@link #NO_ID} if the framework should
7128     * decide automatically.
7129     *
7130     * @attr ref android.R.styleable#View_nextFocusRight
7131     */
7132    public void setNextFocusRightId(int nextFocusRightId) {
7133        mNextFocusRightId = nextFocusRightId;
7134    }
7135
7136    /**
7137     * Gets the id of the view to use when the next focus is {@link #FOCUS_UP}.
7138     * @return The next focus ID, or {@link #NO_ID} if the framework should decide automatically.
7139     *
7140     * @attr ref android.R.styleable#View_nextFocusUp
7141     */
7142    public int getNextFocusUpId() {
7143        return mNextFocusUpId;
7144    }
7145
7146    /**
7147     * Sets the id of the view to use when the next focus is {@link #FOCUS_UP}.
7148     * @param nextFocusUpId The next focus ID, or {@link #NO_ID} if the framework should
7149     * decide automatically.
7150     *
7151     * @attr ref android.R.styleable#View_nextFocusUp
7152     */
7153    public void setNextFocusUpId(int nextFocusUpId) {
7154        mNextFocusUpId = nextFocusUpId;
7155    }
7156
7157    /**
7158     * Gets the id of the view to use when the next focus is {@link #FOCUS_DOWN}.
7159     * @return The next focus ID, or {@link #NO_ID} if the framework should decide automatically.
7160     *
7161     * @attr ref android.R.styleable#View_nextFocusDown
7162     */
7163    public int getNextFocusDownId() {
7164        return mNextFocusDownId;
7165    }
7166
7167    /**
7168     * Sets the id of the view to use when the next focus is {@link #FOCUS_DOWN}.
7169     * @param nextFocusDownId The next focus ID, or {@link #NO_ID} if the framework should
7170     * decide automatically.
7171     *
7172     * @attr ref android.R.styleable#View_nextFocusDown
7173     */
7174    public void setNextFocusDownId(int nextFocusDownId) {
7175        mNextFocusDownId = nextFocusDownId;
7176    }
7177
7178    /**
7179     * Gets the id of the view to use when the next focus is {@link #FOCUS_FORWARD}.
7180     * @return The next focus ID, or {@link #NO_ID} if the framework should decide automatically.
7181     *
7182     * @attr ref android.R.styleable#View_nextFocusForward
7183     */
7184    public int getNextFocusForwardId() {
7185        return mNextFocusForwardId;
7186    }
7187
7188    /**
7189     * Sets the id of the view to use when the next focus is {@link #FOCUS_FORWARD}.
7190     * @param nextFocusForwardId The next focus ID, or {@link #NO_ID} if the framework should
7191     * decide automatically.
7192     *
7193     * @attr ref android.R.styleable#View_nextFocusForward
7194     */
7195    public void setNextFocusForwardId(int nextFocusForwardId) {
7196        mNextFocusForwardId = nextFocusForwardId;
7197    }
7198
7199    /**
7200     * Returns the visibility of this view and all of its ancestors
7201     *
7202     * @return True if this view and all of its ancestors are {@link #VISIBLE}
7203     */
7204    public boolean isShown() {
7205        View current = this;
7206        //noinspection ConstantConditions
7207        do {
7208            if ((current.mViewFlags & VISIBILITY_MASK) != VISIBLE) {
7209                return false;
7210            }
7211            ViewParent parent = current.mParent;
7212            if (parent == null) {
7213                return false; // We are not attached to the view root
7214            }
7215            if (!(parent instanceof View)) {
7216                return true;
7217            }
7218            current = (View) parent;
7219        } while (current != null);
7220
7221        return false;
7222    }
7223
7224    /**
7225     * Called by the view hierarchy when the content insets for a window have
7226     * changed, to allow it to adjust its content to fit within those windows.
7227     * The content insets tell you the space that the status bar, input method,
7228     * and other system windows infringe on the application's window.
7229     *
7230     * <p>You do not normally need to deal with this function, since the default
7231     * window decoration given to applications takes care of applying it to the
7232     * content of the window.  If you use {@link #SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN}
7233     * or {@link #SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION} this will not be the case,
7234     * and your content can be placed under those system elements.  You can then
7235     * use this method within your view hierarchy if you have parts of your UI
7236     * which you would like to ensure are not being covered.
7237     *
7238     * <p>The default implementation of this method simply applies the content
7239     * insets to the view's padding, consuming that content (modifying the
7240     * insets to be 0), and returning true.  This behavior is off by default, but can
7241     * be enabled through {@link #setFitsSystemWindows(boolean)}.
7242     *
7243     * <p>This function's traversal down the hierarchy is depth-first.  The same content
7244     * insets object is propagated down the hierarchy, so any changes made to it will
7245     * be seen by all following views (including potentially ones above in
7246     * the hierarchy since this is a depth-first traversal).  The first view
7247     * that returns true will abort the entire traversal.
7248     *
7249     * <p>The default implementation works well for a situation where it is
7250     * used with a container that covers the entire window, allowing it to
7251     * apply the appropriate insets to its content on all edges.  If you need
7252     * a more complicated layout (such as two different views fitting system
7253     * windows, one on the top of the window, and one on the bottom),
7254     * you can override the method and handle the insets however you would like.
7255     * Note that the insets provided by the framework are always relative to the
7256     * far edges of the window, not accounting for the location of the called view
7257     * within that window.  (In fact when this method is called you do not yet know
7258     * where the layout will place the view, as it is done before layout happens.)
7259     *
7260     * <p>Note: unlike many View methods, there is no dispatch phase to this
7261     * call.  If you are overriding it in a ViewGroup and want to allow the
7262     * call to continue to your children, you must be sure to call the super
7263     * implementation.
7264     *
7265     * <p>Here is a sample layout that makes use of fitting system windows
7266     * to have controls for a video view placed inside of the window decorations
7267     * that it hides and shows.  This can be used with code like the second
7268     * sample (video player) shown in {@link #setSystemUiVisibility(int)}.
7269     *
7270     * {@sample development/samples/ApiDemos/res/layout/video_player.xml complete}
7271     *
7272     * @param insets Current content insets of the window.  Prior to
7273     * {@link android.os.Build.VERSION_CODES#JELLY_BEAN} you must not modify
7274     * the insets or else you and Android will be unhappy.
7275     *
7276     * @return {@code true} if this view applied the insets and it should not
7277     * continue propagating further down the hierarchy, {@code false} otherwise.
7278     * @see #getFitsSystemWindows()
7279     * @see #setFitsSystemWindows(boolean)
7280     * @see #setSystemUiVisibility(int)
7281     *
7282     * @deprecated As of API 20 use {@link #dispatchApplyWindowInsets(WindowInsets)} to apply
7283     * insets to views. Views should override {@link #onApplyWindowInsets(WindowInsets)} or use
7284     * {@link #setOnApplyWindowInsetsListener(android.view.View.OnApplyWindowInsetsListener)}
7285     * to implement handling their own insets.
7286     */
7287    protected boolean fitSystemWindows(Rect insets) {
7288        if ((mPrivateFlags3 & PFLAG3_APPLYING_INSETS) == 0) {
7289            if (insets == null) {
7290                // Null insets by definition have already been consumed.
7291                // This call cannot apply insets since there are none to apply,
7292                // so return false.
7293                return false;
7294            }
7295            // If we're not in the process of dispatching the newer apply insets call,
7296            // that means we're not in the compatibility path. Dispatch into the newer
7297            // apply insets path and take things from there.
7298            try {
7299                mPrivateFlags3 |= PFLAG3_FITTING_SYSTEM_WINDOWS;
7300                return dispatchApplyWindowInsets(new WindowInsets(insets)).isConsumed();
7301            } finally {
7302                mPrivateFlags3 &= ~PFLAG3_FITTING_SYSTEM_WINDOWS;
7303            }
7304        } else {
7305            // We're being called from the newer apply insets path.
7306            // Perform the standard fallback behavior.
7307            return fitSystemWindowsInt(insets);
7308        }
7309    }
7310
7311    private boolean fitSystemWindowsInt(Rect insets) {
7312        if ((mViewFlags & FITS_SYSTEM_WINDOWS) == FITS_SYSTEM_WINDOWS) {
7313            mUserPaddingStart = UNDEFINED_PADDING;
7314            mUserPaddingEnd = UNDEFINED_PADDING;
7315            Rect localInsets = sThreadLocal.get();
7316            if (localInsets == null) {
7317                localInsets = new Rect();
7318                sThreadLocal.set(localInsets);
7319            }
7320            boolean res = computeFitSystemWindows(insets, localInsets);
7321            mUserPaddingLeftInitial = localInsets.left;
7322            mUserPaddingRightInitial = localInsets.right;
7323            internalSetPadding(localInsets.left, localInsets.top,
7324                    localInsets.right, localInsets.bottom);
7325            return res;
7326        }
7327        return false;
7328    }
7329
7330    /**
7331     * Called when the view should apply {@link WindowInsets} according to its internal policy.
7332     *
7333     * <p>This method should be overridden by views that wish to apply a policy different from or
7334     * in addition to the default behavior. Clients that wish to force a view subtree
7335     * to apply insets should call {@link #dispatchApplyWindowInsets(WindowInsets)}.</p>
7336     *
7337     * <p>Clients may supply an {@link OnApplyWindowInsetsListener} to a view. If one is set
7338     * it will be called during dispatch instead of this method. The listener may optionally
7339     * call this method from its own implementation if it wishes to apply the view's default
7340     * insets policy in addition to its own.</p>
7341     *
7342     * <p>Implementations of this method should either return the insets parameter unchanged
7343     * or a new {@link WindowInsets} cloned from the supplied insets with any insets consumed
7344     * that this view applied itself. This allows new inset types added in future platform
7345     * versions to pass through existing implementations unchanged without being erroneously
7346     * consumed.</p>
7347     *
7348     * <p>By default if a view's {@link #setFitsSystemWindows(boolean) fitsSystemWindows}
7349     * property is set then the view will consume the system window insets and apply them
7350     * as padding for the view.</p>
7351     *
7352     * @param insets Insets to apply
7353     * @return The supplied insets with any applied insets consumed
7354     */
7355    public WindowInsets onApplyWindowInsets(WindowInsets insets) {
7356        if ((mPrivateFlags3 & PFLAG3_FITTING_SYSTEM_WINDOWS) == 0) {
7357            // We weren't called from within a direct call to fitSystemWindows,
7358            // call into it as a fallback in case we're in a class that overrides it
7359            // and has logic to perform.
7360            if (fitSystemWindows(insets.getSystemWindowInsets())) {
7361                return insets.consumeSystemWindowInsets();
7362            }
7363        } else {
7364            // We were called from within a direct call to fitSystemWindows.
7365            if (fitSystemWindowsInt(insets.getSystemWindowInsets())) {
7366                return insets.consumeSystemWindowInsets();
7367            }
7368        }
7369        return insets;
7370    }
7371
7372    /**
7373     * Set an {@link OnApplyWindowInsetsListener} to take over the policy for applying
7374     * window insets to this view. The listener's
7375     * {@link OnApplyWindowInsetsListener#onApplyWindowInsets(View, WindowInsets) onApplyWindowInsets}
7376     * method will be called instead of the view's
7377     * {@link #onApplyWindowInsets(WindowInsets) onApplyWindowInsets} method.
7378     *
7379     * @param listener Listener to set
7380     *
7381     * @see #onApplyWindowInsets(WindowInsets)
7382     */
7383    public void setOnApplyWindowInsetsListener(OnApplyWindowInsetsListener listener) {
7384        getListenerInfo().mOnApplyWindowInsetsListener = listener;
7385    }
7386
7387    /**
7388     * Request to apply the given window insets to this view or another view in its subtree.
7389     *
7390     * <p>This method should be called by clients wishing to apply insets corresponding to areas
7391     * obscured by window decorations or overlays. This can include the status and navigation bars,
7392     * action bars, input methods and more. New inset categories may be added in the future.
7393     * The method returns the insets provided minus any that were applied by this view or its
7394     * children.</p>
7395     *
7396     * <p>Clients wishing to provide custom behavior should override the
7397     * {@link #onApplyWindowInsets(WindowInsets)} method or alternatively provide a
7398     * {@link OnApplyWindowInsetsListener} via the
7399     * {@link #setOnApplyWindowInsetsListener(View.OnApplyWindowInsetsListener) setOnApplyWindowInsetsListener}
7400     * method.</p>
7401     *
7402     * <p>This method replaces the older {@link #fitSystemWindows(Rect) fitSystemWindows} method.
7403     * </p>
7404     *
7405     * @param insets Insets to apply
7406     * @return The provided insets minus the insets that were consumed
7407     */
7408    public WindowInsets dispatchApplyWindowInsets(WindowInsets insets) {
7409        try {
7410            mPrivateFlags3 |= PFLAG3_APPLYING_INSETS;
7411            if (mListenerInfo != null && mListenerInfo.mOnApplyWindowInsetsListener != null) {
7412                return mListenerInfo.mOnApplyWindowInsetsListener.onApplyWindowInsets(this, insets);
7413            } else {
7414                return onApplyWindowInsets(insets);
7415            }
7416        } finally {
7417            mPrivateFlags3 &= ~PFLAG3_APPLYING_INSETS;
7418        }
7419    }
7420
7421    /**
7422     * Compute the view's coordinate within the surface.
7423     *
7424     * <p>Computes the coordinates of this view in its surface. The argument
7425     * must be an array of two integers. After the method returns, the array
7426     * contains the x and y location in that order.</p>
7427     * @hide
7428     * @param location an array of two integers in which to hold the coordinates
7429     */
7430    public void getLocationInSurface(@Size(2) int[] location) {
7431        getLocationInWindow(location);
7432        if (mAttachInfo != null && mAttachInfo.mViewRootImpl != null) {
7433            location[0] += mAttachInfo.mViewRootImpl.mWindowAttributes.surfaceInsets.left;
7434            location[1] += mAttachInfo.mViewRootImpl.mWindowAttributes.surfaceInsets.top;
7435        }
7436    }
7437
7438    /**
7439     * Provide original WindowInsets that are dispatched to the view hierarchy. The insets are
7440     * only available if the view is attached.
7441     *
7442     * @return WindowInsets from the top of the view hierarchy or null if View is detached
7443     */
7444    public WindowInsets getRootWindowInsets() {
7445        if (mAttachInfo != null) {
7446            return mAttachInfo.mViewRootImpl.getWindowInsets(false /* forceConstruct */);
7447        }
7448        return null;
7449    }
7450
7451    /**
7452     * @hide Compute the insets that should be consumed by this view and the ones
7453     * that should propagate to those under it.
7454     */
7455    protected boolean computeFitSystemWindows(Rect inoutInsets, Rect outLocalInsets) {
7456        if ((mViewFlags & OPTIONAL_FITS_SYSTEM_WINDOWS) == 0
7457                || mAttachInfo == null
7458                || ((mAttachInfo.mSystemUiVisibility & SYSTEM_UI_LAYOUT_FLAGS) == 0
7459                        && !mAttachInfo.mOverscanRequested)) {
7460            outLocalInsets.set(inoutInsets);
7461            inoutInsets.set(0, 0, 0, 0);
7462            return true;
7463        } else {
7464            // The application wants to take care of fitting system window for
7465            // the content...  however we still need to take care of any overscan here.
7466            final Rect overscan = mAttachInfo.mOverscanInsets;
7467            outLocalInsets.set(overscan);
7468            inoutInsets.left -= overscan.left;
7469            inoutInsets.top -= overscan.top;
7470            inoutInsets.right -= overscan.right;
7471            inoutInsets.bottom -= overscan.bottom;
7472            return false;
7473        }
7474    }
7475
7476    /**
7477     * Compute insets that should be consumed by this view and the ones that should propagate
7478     * to those under it.
7479     *
7480     * @param in Insets currently being processed by this View, likely received as a parameter
7481     *           to {@link #onApplyWindowInsets(WindowInsets)}.
7482     * @param outLocalInsets A Rect that will receive the insets that should be consumed
7483     *                       by this view
7484     * @return Insets that should be passed along to views under this one
7485     */
7486    public WindowInsets computeSystemWindowInsets(WindowInsets in, Rect outLocalInsets) {
7487        if ((mViewFlags & OPTIONAL_FITS_SYSTEM_WINDOWS) == 0
7488                || mAttachInfo == null
7489                || (mAttachInfo.mSystemUiVisibility & SYSTEM_UI_LAYOUT_FLAGS) == 0) {
7490            outLocalInsets.set(in.getSystemWindowInsets());
7491            return in.consumeSystemWindowInsets();
7492        } else {
7493            outLocalInsets.set(0, 0, 0, 0);
7494            return in;
7495        }
7496    }
7497
7498    /**
7499     * Sets whether or not this view should account for system screen decorations
7500     * such as the status bar and inset its content; that is, controlling whether
7501     * the default implementation of {@link #fitSystemWindows(Rect)} will be
7502     * executed.  See that method for more details.
7503     *
7504     * <p>Note that if you are providing your own implementation of
7505     * {@link #fitSystemWindows(Rect)}, then there is no need to set this
7506     * flag to true -- your implementation will be overriding the default
7507     * implementation that checks this flag.
7508     *
7509     * @param fitSystemWindows If true, then the default implementation of
7510     * {@link #fitSystemWindows(Rect)} will be executed.
7511     *
7512     * @attr ref android.R.styleable#View_fitsSystemWindows
7513     * @see #getFitsSystemWindows()
7514     * @see #fitSystemWindows(Rect)
7515     * @see #setSystemUiVisibility(int)
7516     */
7517    public void setFitsSystemWindows(boolean fitSystemWindows) {
7518        setFlags(fitSystemWindows ? FITS_SYSTEM_WINDOWS : 0, FITS_SYSTEM_WINDOWS);
7519    }
7520
7521    /**
7522     * Check for state of {@link #setFitsSystemWindows(boolean)}. If this method
7523     * returns {@code true}, the default implementation of {@link #fitSystemWindows(Rect)}
7524     * will be executed.
7525     *
7526     * @return {@code true} if the default implementation of
7527     * {@link #fitSystemWindows(Rect)} will be executed.
7528     *
7529     * @attr ref android.R.styleable#View_fitsSystemWindows
7530     * @see #setFitsSystemWindows(boolean)
7531     * @see #fitSystemWindows(Rect)
7532     * @see #setSystemUiVisibility(int)
7533     */
7534    @ViewDebug.ExportedProperty
7535    public boolean getFitsSystemWindows() {
7536        return (mViewFlags & FITS_SYSTEM_WINDOWS) == FITS_SYSTEM_WINDOWS;
7537    }
7538
7539    /** @hide */
7540    public boolean fitsSystemWindows() {
7541        return getFitsSystemWindows();
7542    }
7543
7544    /**
7545     * Ask that a new dispatch of {@link #fitSystemWindows(Rect)} be performed.
7546     * @deprecated Use {@link #requestApplyInsets()} for newer platform versions.
7547     */
7548    public void requestFitSystemWindows() {
7549        if (mParent != null) {
7550            mParent.requestFitSystemWindows();
7551        }
7552    }
7553
7554    /**
7555     * Ask that a new dispatch of {@link #onApplyWindowInsets(WindowInsets)} be performed.
7556     */
7557    public void requestApplyInsets() {
7558        requestFitSystemWindows();
7559    }
7560
7561    /**
7562     * For use by PhoneWindow to make its own system window fitting optional.
7563     * @hide
7564     */
7565    public void makeOptionalFitsSystemWindows() {
7566        setFlags(OPTIONAL_FITS_SYSTEM_WINDOWS, OPTIONAL_FITS_SYSTEM_WINDOWS);
7567    }
7568
7569    /**
7570     * Returns the outsets, which areas of the device that aren't a surface, but we would like to
7571     * treat them as such.
7572     * @hide
7573     */
7574    public void getOutsets(Rect outOutsetRect) {
7575        if (mAttachInfo != null) {
7576            outOutsetRect.set(mAttachInfo.mOutsets);
7577        } else {
7578            outOutsetRect.setEmpty();
7579        }
7580    }
7581
7582    /**
7583     * Returns the visibility status for this view.
7584     *
7585     * @return One of {@link #VISIBLE}, {@link #INVISIBLE}, or {@link #GONE}.
7586     * @attr ref android.R.styleable#View_visibility
7587     */
7588    @ViewDebug.ExportedProperty(mapping = {
7589        @ViewDebug.IntToString(from = VISIBLE,   to = "VISIBLE"),
7590        @ViewDebug.IntToString(from = INVISIBLE, to = "INVISIBLE"),
7591        @ViewDebug.IntToString(from = GONE,      to = "GONE")
7592    })
7593    @Visibility
7594    public int getVisibility() {
7595        return mViewFlags & VISIBILITY_MASK;
7596    }
7597
7598    /**
7599     * Set the enabled state of this view.
7600     *
7601     * @param visibility One of {@link #VISIBLE}, {@link #INVISIBLE}, or {@link #GONE}.
7602     * @attr ref android.R.styleable#View_visibility
7603     */
7604    @RemotableViewMethod
7605    public void setVisibility(@Visibility int visibility) {
7606        setFlags(visibility, VISIBILITY_MASK);
7607    }
7608
7609    /**
7610     * Returns the enabled status for this view. The interpretation of the
7611     * enabled state varies by subclass.
7612     *
7613     * @return True if this view is enabled, false otherwise.
7614     */
7615    @ViewDebug.ExportedProperty
7616    public boolean isEnabled() {
7617        return (mViewFlags & ENABLED_MASK) == ENABLED;
7618    }
7619
7620    /**
7621     * Set the enabled state of this view. The interpretation of the enabled
7622     * state varies by subclass.
7623     *
7624     * @param enabled True if this view is enabled, false otherwise.
7625     */
7626    @RemotableViewMethod
7627    public void setEnabled(boolean enabled) {
7628        if (enabled == isEnabled()) return;
7629
7630        setFlags(enabled ? ENABLED : DISABLED, ENABLED_MASK);
7631
7632        /*
7633         * The View most likely has to change its appearance, so refresh
7634         * the drawable state.
7635         */
7636        refreshDrawableState();
7637
7638        // Invalidate too, since the default behavior for views is to be
7639        // be drawn at 50% alpha rather than to change the drawable.
7640        invalidate(true);
7641
7642        if (!enabled) {
7643            cancelPendingInputEvents();
7644        }
7645    }
7646
7647    /**
7648     * Set whether this view can receive the focus.
7649     *
7650     * Setting this to false will also ensure that this view is not focusable
7651     * in touch mode.
7652     *
7653     * @param focusable If true, this view can receive the focus.
7654     *
7655     * @see #setFocusableInTouchMode(boolean)
7656     * @attr ref android.R.styleable#View_focusable
7657     */
7658    public void setFocusable(boolean focusable) {
7659        if (!focusable) {
7660            setFlags(0, FOCUSABLE_IN_TOUCH_MODE);
7661        }
7662        setFlags(focusable ? FOCUSABLE : NOT_FOCUSABLE, FOCUSABLE_MASK);
7663    }
7664
7665    /**
7666     * Set whether this view can receive focus while in touch mode.
7667     *
7668     * Setting this to true will also ensure that this view is focusable.
7669     *
7670     * @param focusableInTouchMode If true, this view can receive the focus while
7671     *   in touch mode.
7672     *
7673     * @see #setFocusable(boolean)
7674     * @attr ref android.R.styleable#View_focusableInTouchMode
7675     */
7676    public void setFocusableInTouchMode(boolean focusableInTouchMode) {
7677        // Focusable in touch mode should always be set before the focusable flag
7678        // otherwise, setting the focusable flag will trigger a focusableViewAvailable()
7679        // which, in touch mode, will not successfully request focus on this view
7680        // because the focusable in touch mode flag is not set
7681        setFlags(focusableInTouchMode ? FOCUSABLE_IN_TOUCH_MODE : 0, FOCUSABLE_IN_TOUCH_MODE);
7682        if (focusableInTouchMode) {
7683            setFlags(FOCUSABLE, FOCUSABLE_MASK);
7684        }
7685    }
7686
7687    /**
7688     * Set whether this view should have sound effects enabled for events such as
7689     * clicking and touching.
7690     *
7691     * <p>You may wish to disable sound effects for a view if you already play sounds,
7692     * for instance, a dial key that plays dtmf tones.
7693     *
7694     * @param soundEffectsEnabled whether sound effects are enabled for this view.
7695     * @see #isSoundEffectsEnabled()
7696     * @see #playSoundEffect(int)
7697     * @attr ref android.R.styleable#View_soundEffectsEnabled
7698     */
7699    public void setSoundEffectsEnabled(boolean soundEffectsEnabled) {
7700        setFlags(soundEffectsEnabled ? SOUND_EFFECTS_ENABLED: 0, SOUND_EFFECTS_ENABLED);
7701    }
7702
7703    /**
7704     * @return whether this view should have sound effects enabled for events such as
7705     *     clicking and touching.
7706     *
7707     * @see #setSoundEffectsEnabled(boolean)
7708     * @see #playSoundEffect(int)
7709     * @attr ref android.R.styleable#View_soundEffectsEnabled
7710     */
7711    @ViewDebug.ExportedProperty
7712    public boolean isSoundEffectsEnabled() {
7713        return SOUND_EFFECTS_ENABLED == (mViewFlags & SOUND_EFFECTS_ENABLED);
7714    }
7715
7716    /**
7717     * Set whether this view should have haptic feedback for events such as
7718     * long presses.
7719     *
7720     * <p>You may wish to disable haptic feedback if your view already controls
7721     * its own haptic feedback.
7722     *
7723     * @param hapticFeedbackEnabled whether haptic feedback enabled for this view.
7724     * @see #isHapticFeedbackEnabled()
7725     * @see #performHapticFeedback(int)
7726     * @attr ref android.R.styleable#View_hapticFeedbackEnabled
7727     */
7728    public void setHapticFeedbackEnabled(boolean hapticFeedbackEnabled) {
7729        setFlags(hapticFeedbackEnabled ? HAPTIC_FEEDBACK_ENABLED: 0, HAPTIC_FEEDBACK_ENABLED);
7730    }
7731
7732    /**
7733     * @return whether this view should have haptic feedback enabled for events
7734     * long presses.
7735     *
7736     * @see #setHapticFeedbackEnabled(boolean)
7737     * @see #performHapticFeedback(int)
7738     * @attr ref android.R.styleable#View_hapticFeedbackEnabled
7739     */
7740    @ViewDebug.ExportedProperty
7741    public boolean isHapticFeedbackEnabled() {
7742        return HAPTIC_FEEDBACK_ENABLED == (mViewFlags & HAPTIC_FEEDBACK_ENABLED);
7743    }
7744
7745    /**
7746     * Returns the layout direction for this view.
7747     *
7748     * @return One of {@link #LAYOUT_DIRECTION_LTR},
7749     *   {@link #LAYOUT_DIRECTION_RTL},
7750     *   {@link #LAYOUT_DIRECTION_INHERIT} or
7751     *   {@link #LAYOUT_DIRECTION_LOCALE}.
7752     *
7753     * @attr ref android.R.styleable#View_layoutDirection
7754     *
7755     * @hide
7756     */
7757    @ViewDebug.ExportedProperty(category = "layout", mapping = {
7758        @ViewDebug.IntToString(from = LAYOUT_DIRECTION_LTR,     to = "LTR"),
7759        @ViewDebug.IntToString(from = LAYOUT_DIRECTION_RTL,     to = "RTL"),
7760        @ViewDebug.IntToString(from = LAYOUT_DIRECTION_INHERIT, to = "INHERIT"),
7761        @ViewDebug.IntToString(from = LAYOUT_DIRECTION_LOCALE,  to = "LOCALE")
7762    })
7763    @LayoutDir
7764    public int getRawLayoutDirection() {
7765        return (mPrivateFlags2 & PFLAG2_LAYOUT_DIRECTION_MASK) >> PFLAG2_LAYOUT_DIRECTION_MASK_SHIFT;
7766    }
7767
7768    /**
7769     * Set the layout direction for this view. This will propagate a reset of layout direction
7770     * resolution to the view's children and resolve layout direction for this view.
7771     *
7772     * @param layoutDirection the layout direction to set. Should be one of:
7773     *
7774     * {@link #LAYOUT_DIRECTION_LTR},
7775     * {@link #LAYOUT_DIRECTION_RTL},
7776     * {@link #LAYOUT_DIRECTION_INHERIT},
7777     * {@link #LAYOUT_DIRECTION_LOCALE}.
7778     *
7779     * Resolution will be done if the value is set to LAYOUT_DIRECTION_INHERIT. The resolution
7780     * proceeds up the parent chain of the view to get the value. If there is no parent, then it
7781     * will return the default {@link #LAYOUT_DIRECTION_LTR}.
7782     *
7783     * @attr ref android.R.styleable#View_layoutDirection
7784     */
7785    @RemotableViewMethod
7786    public void setLayoutDirection(@LayoutDir int layoutDirection) {
7787        if (getRawLayoutDirection() != layoutDirection) {
7788            // Reset the current layout direction and the resolved one
7789            mPrivateFlags2 &= ~PFLAG2_LAYOUT_DIRECTION_MASK;
7790            resetRtlProperties();
7791            // Set the new layout direction (filtered)
7792            mPrivateFlags2 |=
7793                    ((layoutDirection << PFLAG2_LAYOUT_DIRECTION_MASK_SHIFT) & PFLAG2_LAYOUT_DIRECTION_MASK);
7794            // We need to resolve all RTL properties as they all depend on layout direction
7795            resolveRtlPropertiesIfNeeded();
7796            requestLayout();
7797            invalidate(true);
7798        }
7799    }
7800
7801    /**
7802     * Returns the resolved layout direction for this view.
7803     *
7804     * @return {@link #LAYOUT_DIRECTION_RTL} if the layout direction is RTL or returns
7805     * {@link #LAYOUT_DIRECTION_LTR} if the layout direction is not RTL.
7806     *
7807     * For compatibility, this will return {@link #LAYOUT_DIRECTION_LTR} if API version
7808     * is lower than {@link android.os.Build.VERSION_CODES#JELLY_BEAN_MR1}.
7809     *
7810     * @attr ref android.R.styleable#View_layoutDirection
7811     */
7812    @ViewDebug.ExportedProperty(category = "layout", mapping = {
7813        @ViewDebug.IntToString(from = LAYOUT_DIRECTION_LTR, to = "RESOLVED_DIRECTION_LTR"),
7814        @ViewDebug.IntToString(from = LAYOUT_DIRECTION_RTL, to = "RESOLVED_DIRECTION_RTL")
7815    })
7816    @ResolvedLayoutDir
7817    public int getLayoutDirection() {
7818        final int targetSdkVersion = getContext().getApplicationInfo().targetSdkVersion;
7819        if (targetSdkVersion < JELLY_BEAN_MR1) {
7820            mPrivateFlags2 |= PFLAG2_LAYOUT_DIRECTION_RESOLVED;
7821            return LAYOUT_DIRECTION_RESOLVED_DEFAULT;
7822        }
7823        return ((mPrivateFlags2 & PFLAG2_LAYOUT_DIRECTION_RESOLVED_RTL) ==
7824                PFLAG2_LAYOUT_DIRECTION_RESOLVED_RTL) ? LAYOUT_DIRECTION_RTL : LAYOUT_DIRECTION_LTR;
7825    }
7826
7827    /**
7828     * Indicates whether or not this view's layout is right-to-left. This is resolved from
7829     * layout attribute and/or the inherited value from the parent
7830     *
7831     * @return true if the layout is right-to-left.
7832     *
7833     * @hide
7834     */
7835    @ViewDebug.ExportedProperty(category = "layout")
7836    public boolean isLayoutRtl() {
7837        return (getLayoutDirection() == LAYOUT_DIRECTION_RTL);
7838    }
7839
7840    /**
7841     * Indicates whether the view is currently tracking transient state that the
7842     * app should not need to concern itself with saving and restoring, but that
7843     * the framework should take special note to preserve when possible.
7844     *
7845     * <p>A view with transient state cannot be trivially rebound from an external
7846     * data source, such as an adapter binding item views in a list. This may be
7847     * because the view is performing an animation, tracking user selection
7848     * of content, or similar.</p>
7849     *
7850     * @return true if the view has transient state
7851     */
7852    @ViewDebug.ExportedProperty(category = "layout")
7853    public boolean hasTransientState() {
7854        return (mPrivateFlags2 & PFLAG2_HAS_TRANSIENT_STATE) == PFLAG2_HAS_TRANSIENT_STATE;
7855    }
7856
7857    /**
7858     * Set whether this view is currently tracking transient state that the
7859     * framework should attempt to preserve when possible. This flag is reference counted,
7860     * so every call to setHasTransientState(true) should be paired with a later call
7861     * to setHasTransientState(false).
7862     *
7863     * <p>A view with transient state cannot be trivially rebound from an external
7864     * data source, such as an adapter binding item views in a list. This may be
7865     * because the view is performing an animation, tracking user selection
7866     * of content, or similar.</p>
7867     *
7868     * @param hasTransientState true if this view has transient state
7869     */
7870    public void setHasTransientState(boolean hasTransientState) {
7871        mTransientStateCount = hasTransientState ? mTransientStateCount + 1 :
7872                mTransientStateCount - 1;
7873        if (mTransientStateCount < 0) {
7874            mTransientStateCount = 0;
7875            Log.e(VIEW_LOG_TAG, "hasTransientState decremented below 0: " +
7876                    "unmatched pair of setHasTransientState calls");
7877        } else if ((hasTransientState && mTransientStateCount == 1) ||
7878                (!hasTransientState && mTransientStateCount == 0)) {
7879            // update flag if we've just incremented up from 0 or decremented down to 0
7880            mPrivateFlags2 = (mPrivateFlags2 & ~PFLAG2_HAS_TRANSIENT_STATE) |
7881                    (hasTransientState ? PFLAG2_HAS_TRANSIENT_STATE : 0);
7882            if (mParent != null) {
7883                try {
7884                    mParent.childHasTransientStateChanged(this, hasTransientState);
7885                } catch (AbstractMethodError e) {
7886                    Log.e(VIEW_LOG_TAG, mParent.getClass().getSimpleName() +
7887                            " does not fully implement ViewParent", e);
7888                }
7889            }
7890        }
7891    }
7892
7893    /**
7894     * Returns true if this view is currently attached to a window.
7895     */
7896    public boolean isAttachedToWindow() {
7897        return mAttachInfo != null;
7898    }
7899
7900    /**
7901     * Returns true if this view has been through at least one layout since it
7902     * was last attached to or detached from a window.
7903     */
7904    public boolean isLaidOut() {
7905        return (mPrivateFlags3 & PFLAG3_IS_LAID_OUT) == PFLAG3_IS_LAID_OUT;
7906    }
7907
7908    /**
7909     * If this view doesn't do any drawing on its own, set this flag to
7910     * allow further optimizations. By default, this flag is not set on
7911     * View, but could be set on some View subclasses such as ViewGroup.
7912     *
7913     * Typically, if you override {@link #onDraw(android.graphics.Canvas)}
7914     * you should clear this flag.
7915     *
7916     * @param willNotDraw whether or not this View draw on its own
7917     */
7918    public void setWillNotDraw(boolean willNotDraw) {
7919        setFlags(willNotDraw ? WILL_NOT_DRAW : 0, DRAW_MASK);
7920    }
7921
7922    /**
7923     * Returns whether or not this View draws on its own.
7924     *
7925     * @return true if this view has nothing to draw, false otherwise
7926     */
7927    @ViewDebug.ExportedProperty(category = "drawing")
7928    public boolean willNotDraw() {
7929        return (mViewFlags & DRAW_MASK) == WILL_NOT_DRAW;
7930    }
7931
7932    /**
7933     * When a View's drawing cache is enabled, drawing is redirected to an
7934     * offscreen bitmap. Some views, like an ImageView, must be able to
7935     * bypass this mechanism if they already draw a single bitmap, to avoid
7936     * unnecessary usage of the memory.
7937     *
7938     * @param willNotCacheDrawing true if this view does not cache its
7939     *        drawing, false otherwise
7940     */
7941    public void setWillNotCacheDrawing(boolean willNotCacheDrawing) {
7942        setFlags(willNotCacheDrawing ? WILL_NOT_CACHE_DRAWING : 0, WILL_NOT_CACHE_DRAWING);
7943    }
7944
7945    /**
7946     * Returns whether or not this View can cache its drawing or not.
7947     *
7948     * @return true if this view does not cache its drawing, false otherwise
7949     */
7950    @ViewDebug.ExportedProperty(category = "drawing")
7951    public boolean willNotCacheDrawing() {
7952        return (mViewFlags & WILL_NOT_CACHE_DRAWING) == WILL_NOT_CACHE_DRAWING;
7953    }
7954
7955    /**
7956     * Indicates whether this view reacts to click events or not.
7957     *
7958     * @return true if the view is clickable, false otherwise
7959     *
7960     * @see #setClickable(boolean)
7961     * @attr ref android.R.styleable#View_clickable
7962     */
7963    @ViewDebug.ExportedProperty
7964    public boolean isClickable() {
7965        return (mViewFlags & CLICKABLE) == CLICKABLE;
7966    }
7967
7968    /**
7969     * Enables or disables click events for this view. When a view
7970     * is clickable it will change its state to "pressed" on every click.
7971     * Subclasses should set the view clickable to visually react to
7972     * user's clicks.
7973     *
7974     * @param clickable true to make the view clickable, false otherwise
7975     *
7976     * @see #isClickable()
7977     * @attr ref android.R.styleable#View_clickable
7978     */
7979    public void setClickable(boolean clickable) {
7980        setFlags(clickable ? CLICKABLE : 0, CLICKABLE);
7981    }
7982
7983    /**
7984     * Indicates whether this view reacts to long click events or not.
7985     *
7986     * @return true if the view is long clickable, false otherwise
7987     *
7988     * @see #setLongClickable(boolean)
7989     * @attr ref android.R.styleable#View_longClickable
7990     */
7991    public boolean isLongClickable() {
7992        return (mViewFlags & LONG_CLICKABLE) == LONG_CLICKABLE;
7993    }
7994
7995    /**
7996     * Enables or disables long click events for this view. When a view is long
7997     * clickable it reacts to the user holding down the button for a longer
7998     * duration than a tap. This event can either launch the listener or a
7999     * context menu.
8000     *
8001     * @param longClickable true to make the view long clickable, false otherwise
8002     * @see #isLongClickable()
8003     * @attr ref android.R.styleable#View_longClickable
8004     */
8005    public void setLongClickable(boolean longClickable) {
8006        setFlags(longClickable ? LONG_CLICKABLE : 0, LONG_CLICKABLE);
8007    }
8008
8009    /**
8010     * Indicates whether this view reacts to context clicks or not.
8011     *
8012     * @return true if the view is context clickable, false otherwise
8013     * @see #setContextClickable(boolean)
8014     * @attr ref android.R.styleable#View_contextClickable
8015     */
8016    public boolean isContextClickable() {
8017        return (mViewFlags & CONTEXT_CLICKABLE) == CONTEXT_CLICKABLE;
8018    }
8019
8020    /**
8021     * Enables or disables context clicking for this view. This event can launch the listener.
8022     *
8023     * @param contextClickable true to make the view react to a context click, false otherwise
8024     * @see #isContextClickable()
8025     * @attr ref android.R.styleable#View_contextClickable
8026     */
8027    public void setContextClickable(boolean contextClickable) {
8028        setFlags(contextClickable ? CONTEXT_CLICKABLE : 0, CONTEXT_CLICKABLE);
8029    }
8030
8031    /**
8032     * Sets the pressed state for this view and provides a touch coordinate for
8033     * animation hinting.
8034     *
8035     * @param pressed Pass true to set the View's internal state to "pressed",
8036     *            or false to reverts the View's internal state from a
8037     *            previously set "pressed" state.
8038     * @param x The x coordinate of the touch that caused the press
8039     * @param y The y coordinate of the touch that caused the press
8040     */
8041    private void setPressed(boolean pressed, float x, float y) {
8042        if (pressed) {
8043            drawableHotspotChanged(x, y);
8044        }
8045
8046        setPressed(pressed);
8047    }
8048
8049    /**
8050     * Sets the pressed state for this view.
8051     *
8052     * @see #isClickable()
8053     * @see #setClickable(boolean)
8054     *
8055     * @param pressed Pass true to set the View's internal state to "pressed", or false to reverts
8056     *        the View's internal state from a previously set "pressed" state.
8057     */
8058    public void setPressed(boolean pressed) {
8059        final boolean needsRefresh = pressed != ((mPrivateFlags & PFLAG_PRESSED) == PFLAG_PRESSED);
8060
8061        if (pressed) {
8062            mPrivateFlags |= PFLAG_PRESSED;
8063        } else {
8064            mPrivateFlags &= ~PFLAG_PRESSED;
8065        }
8066
8067        if (needsRefresh) {
8068            refreshDrawableState();
8069        }
8070        dispatchSetPressed(pressed);
8071    }
8072
8073    /**
8074     * Dispatch setPressed to all of this View's children.
8075     *
8076     * @see #setPressed(boolean)
8077     *
8078     * @param pressed The new pressed state
8079     */
8080    protected void dispatchSetPressed(boolean pressed) {
8081    }
8082
8083    /**
8084     * Indicates whether the view is currently in pressed state. Unless
8085     * {@link #setPressed(boolean)} is explicitly called, only clickable views can enter
8086     * the pressed state.
8087     *
8088     * @see #setPressed(boolean)
8089     * @see #isClickable()
8090     * @see #setClickable(boolean)
8091     *
8092     * @return true if the view is currently pressed, false otherwise
8093     */
8094    @ViewDebug.ExportedProperty
8095    public boolean isPressed() {
8096        return (mPrivateFlags & PFLAG_PRESSED) == PFLAG_PRESSED;
8097    }
8098
8099    /**
8100     * @hide
8101     * Indicates whether this view will participate in data collection through
8102     * {@link ViewStructure}.  If true, it will not provide any data
8103     * for itself or its children.  If false, the normal data collection will be allowed.
8104     *
8105     * @return Returns false if assist data collection is not blocked, else true.
8106     *
8107     * @see #setAssistBlocked(boolean)
8108     * @attr ref android.R.styleable#View_assistBlocked
8109     */
8110    public boolean isAssistBlocked() {
8111        return (mPrivateFlags3 & PFLAG3_ASSIST_BLOCKED) != 0;
8112    }
8113
8114    /**
8115     * @hide
8116     * Controls whether assist data collection from this view and its children is enabled
8117     * (that is, whether {@link #onProvideStructure} and
8118     * {@link #onProvideVirtualStructure} will be called).  The default value is false,
8119     * allowing normal assist collection.  Setting this to false will disable assist collection.
8120     *
8121     * @param enabled Set to true to <em>disable</em> assist data collection, or false
8122     * (the default) to allow it.
8123     *
8124     * @see #isAssistBlocked()
8125     * @see #onProvideStructure
8126     * @see #onProvideVirtualStructure
8127     * @attr ref android.R.styleable#View_assistBlocked
8128     */
8129    public void setAssistBlocked(boolean enabled) {
8130        if (enabled) {
8131            mPrivateFlags3 |= PFLAG3_ASSIST_BLOCKED;
8132        } else {
8133            mPrivateFlags3 &= ~PFLAG3_ASSIST_BLOCKED;
8134        }
8135    }
8136
8137    /**
8138     * Indicates whether this view will save its state (that is,
8139     * whether its {@link #onSaveInstanceState} method will be called).
8140     *
8141     * @return Returns true if the view state saving is enabled, else false.
8142     *
8143     * @see #setSaveEnabled(boolean)
8144     * @attr ref android.R.styleable#View_saveEnabled
8145     */
8146    public boolean isSaveEnabled() {
8147        return (mViewFlags & SAVE_DISABLED_MASK) != SAVE_DISABLED;
8148    }
8149
8150    /**
8151     * Controls whether the saving of this view's state is
8152     * enabled (that is, whether its {@link #onSaveInstanceState} method
8153     * will be called).  Note that even if freezing is enabled, the
8154     * view still must have an id assigned to it (via {@link #setId(int)})
8155     * for its state to be saved.  This flag can only disable the
8156     * saving of this view; any child views may still have their state saved.
8157     *
8158     * @param enabled Set to false to <em>disable</em> state saving, or true
8159     * (the default) to allow it.
8160     *
8161     * @see #isSaveEnabled()
8162     * @see #setId(int)
8163     * @see #onSaveInstanceState()
8164     * @attr ref android.R.styleable#View_saveEnabled
8165     */
8166    public void setSaveEnabled(boolean enabled) {
8167        setFlags(enabled ? 0 : SAVE_DISABLED, SAVE_DISABLED_MASK);
8168    }
8169
8170    /**
8171     * Gets whether the framework should discard touches when the view's
8172     * window is obscured by another visible window.
8173     * Refer to the {@link View} security documentation for more details.
8174     *
8175     * @return True if touch filtering is enabled.
8176     *
8177     * @see #setFilterTouchesWhenObscured(boolean)
8178     * @attr ref android.R.styleable#View_filterTouchesWhenObscured
8179     */
8180    @ViewDebug.ExportedProperty
8181    public boolean getFilterTouchesWhenObscured() {
8182        return (mViewFlags & FILTER_TOUCHES_WHEN_OBSCURED) != 0;
8183    }
8184
8185    /**
8186     * Sets whether the framework should discard touches when the view's
8187     * window is obscured by another visible window.
8188     * Refer to the {@link View} security documentation for more details.
8189     *
8190     * @param enabled True if touch filtering should be enabled.
8191     *
8192     * @see #getFilterTouchesWhenObscured
8193     * @attr ref android.R.styleable#View_filterTouchesWhenObscured
8194     */
8195    public void setFilterTouchesWhenObscured(boolean enabled) {
8196        setFlags(enabled ? FILTER_TOUCHES_WHEN_OBSCURED : 0,
8197                FILTER_TOUCHES_WHEN_OBSCURED);
8198    }
8199
8200    /**
8201     * Indicates whether the entire hierarchy under this view will save its
8202     * state when a state saving traversal occurs from its parent.  The default
8203     * is true; if false, these views will not be saved unless
8204     * {@link #saveHierarchyState(SparseArray)} is called directly on this view.
8205     *
8206     * @return Returns true if the view state saving from parent is enabled, else false.
8207     *
8208     * @see #setSaveFromParentEnabled(boolean)
8209     */
8210    public boolean isSaveFromParentEnabled() {
8211        return (mViewFlags & PARENT_SAVE_DISABLED_MASK) != PARENT_SAVE_DISABLED;
8212    }
8213
8214    /**
8215     * Controls whether the entire hierarchy under this view will save its
8216     * state when a state saving traversal occurs from its parent.  The default
8217     * is true; if false, these views will not be saved unless
8218     * {@link #saveHierarchyState(SparseArray)} is called directly on this view.
8219     *
8220     * @param enabled Set to false to <em>disable</em> state saving, or true
8221     * (the default) to allow it.
8222     *
8223     * @see #isSaveFromParentEnabled()
8224     * @see #setId(int)
8225     * @see #onSaveInstanceState()
8226     */
8227    public void setSaveFromParentEnabled(boolean enabled) {
8228        setFlags(enabled ? 0 : PARENT_SAVE_DISABLED, PARENT_SAVE_DISABLED_MASK);
8229    }
8230
8231
8232    /**
8233     * Returns whether this View is able to take focus.
8234     *
8235     * @return True if this view can take focus, or false otherwise.
8236     * @attr ref android.R.styleable#View_focusable
8237     */
8238    @ViewDebug.ExportedProperty(category = "focus")
8239    public final boolean isFocusable() {
8240        return FOCUSABLE == (mViewFlags & FOCUSABLE_MASK);
8241    }
8242
8243    /**
8244     * When a view is focusable, it may not want to take focus when in touch mode.
8245     * For example, a button would like focus when the user is navigating via a D-pad
8246     * so that the user can click on it, but once the user starts touching the screen,
8247     * the button shouldn't take focus
8248     * @return Whether the view is focusable in touch mode.
8249     * @attr ref android.R.styleable#View_focusableInTouchMode
8250     */
8251    @ViewDebug.ExportedProperty
8252    public final boolean isFocusableInTouchMode() {
8253        return FOCUSABLE_IN_TOUCH_MODE == (mViewFlags & FOCUSABLE_IN_TOUCH_MODE);
8254    }
8255
8256    /**
8257     * Find the nearest view in the specified direction that can take focus.
8258     * This does not actually give focus to that view.
8259     *
8260     * @param direction One of FOCUS_UP, FOCUS_DOWN, FOCUS_LEFT, and FOCUS_RIGHT
8261     *
8262     * @return The nearest focusable in the specified direction, or null if none
8263     *         can be found.
8264     */
8265    public View focusSearch(@FocusRealDirection int direction) {
8266        if (mParent != null) {
8267            return mParent.focusSearch(this, direction);
8268        } else {
8269            return null;
8270        }
8271    }
8272
8273    /**
8274     * This method is the last chance for the focused view and its ancestors to
8275     * respond to an arrow key. This is called when the focused view did not
8276     * consume the key internally, nor could the view system find a new view in
8277     * the requested direction to give focus to.
8278     *
8279     * @param focused The currently focused view.
8280     * @param direction The direction focus wants to move. One of FOCUS_UP,
8281     *        FOCUS_DOWN, FOCUS_LEFT, and FOCUS_RIGHT.
8282     * @return True if the this view consumed this unhandled move.
8283     */
8284    public boolean dispatchUnhandledMove(View focused, @FocusRealDirection int direction) {
8285        return false;
8286    }
8287
8288    /**
8289     * If a user manually specified the next view id for a particular direction,
8290     * use the root to look up the view.
8291     * @param root The root view of the hierarchy containing this view.
8292     * @param direction One of FOCUS_UP, FOCUS_DOWN, FOCUS_LEFT, FOCUS_RIGHT, FOCUS_FORWARD,
8293     * or FOCUS_BACKWARD.
8294     * @return The user specified next view, or null if there is none.
8295     */
8296    View findUserSetNextFocus(View root, @FocusDirection int direction) {
8297        switch (direction) {
8298            case FOCUS_LEFT:
8299                if (mNextFocusLeftId == View.NO_ID) return null;
8300                return findViewInsideOutShouldExist(root, mNextFocusLeftId);
8301            case FOCUS_RIGHT:
8302                if (mNextFocusRightId == View.NO_ID) return null;
8303                return findViewInsideOutShouldExist(root, mNextFocusRightId);
8304            case FOCUS_UP:
8305                if (mNextFocusUpId == View.NO_ID) return null;
8306                return findViewInsideOutShouldExist(root, mNextFocusUpId);
8307            case FOCUS_DOWN:
8308                if (mNextFocusDownId == View.NO_ID) return null;
8309                return findViewInsideOutShouldExist(root, mNextFocusDownId);
8310            case FOCUS_FORWARD:
8311                if (mNextFocusForwardId == View.NO_ID) return null;
8312                return findViewInsideOutShouldExist(root, mNextFocusForwardId);
8313            case FOCUS_BACKWARD: {
8314                if (mID == View.NO_ID) return null;
8315                final int id = mID;
8316                return root.findViewByPredicateInsideOut(this, new Predicate<View>() {
8317                    @Override
8318                    public boolean apply(View t) {
8319                        return t.mNextFocusForwardId == id;
8320                    }
8321                });
8322            }
8323        }
8324        return null;
8325    }
8326
8327    private View findViewInsideOutShouldExist(View root, int id) {
8328        if (mMatchIdPredicate == null) {
8329            mMatchIdPredicate = new MatchIdPredicate();
8330        }
8331        mMatchIdPredicate.mId = id;
8332        View result = root.findViewByPredicateInsideOut(this, mMatchIdPredicate);
8333        if (result == null) {
8334            Log.w(VIEW_LOG_TAG, "couldn't find view with id " + id);
8335        }
8336        return result;
8337    }
8338
8339    /**
8340     * Find and return all focusable views that are descendants of this view,
8341     * possibly including this view if it is focusable itself.
8342     *
8343     * @param direction The direction of the focus
8344     * @return A list of focusable views
8345     */
8346    public ArrayList<View> getFocusables(@FocusDirection int direction) {
8347        ArrayList<View> result = new ArrayList<View>(24);
8348        addFocusables(result, direction);
8349        return result;
8350    }
8351
8352    /**
8353     * Add any focusable views that are descendants of this view (possibly
8354     * including this view if it is focusable itself) to views.  If we are in touch mode,
8355     * only add views that are also focusable in touch mode.
8356     *
8357     * @param views Focusable views found so far
8358     * @param direction The direction of the focus
8359     */
8360    public void addFocusables(ArrayList<View> views, @FocusDirection int direction) {
8361        addFocusables(views, direction, FOCUSABLES_TOUCH_MODE);
8362    }
8363
8364    /**
8365     * Adds any focusable views that are descendants of this view (possibly
8366     * including this view if it is focusable itself) to views. This method
8367     * adds all focusable views regardless if we are in touch mode or
8368     * only views focusable in touch mode if we are in touch mode or
8369     * only views that can take accessibility focus if accessibility is enabled
8370     * depending on the focusable mode parameter.
8371     *
8372     * @param views Focusable views found so far or null if all we are interested is
8373     *        the number of focusables.
8374     * @param direction The direction of the focus.
8375     * @param focusableMode The type of focusables to be added.
8376     *
8377     * @see #FOCUSABLES_ALL
8378     * @see #FOCUSABLES_TOUCH_MODE
8379     */
8380    public void addFocusables(ArrayList<View> views, @FocusDirection int direction,
8381            @FocusableMode int focusableMode) {
8382        if (views == null) {
8383            return;
8384        }
8385        if (!isFocusable()) {
8386            return;
8387        }
8388        if ((focusableMode & FOCUSABLES_TOUCH_MODE) == FOCUSABLES_TOUCH_MODE
8389                && isInTouchMode() && !isFocusableInTouchMode()) {
8390            return;
8391        }
8392        views.add(this);
8393    }
8394
8395    /**
8396     * Finds the Views that contain given text. The containment is case insensitive.
8397     * The search is performed by either the text that the View renders or the content
8398     * description that describes the view for accessibility purposes and the view does
8399     * not render or both. Clients can specify how the search is to be performed via
8400     * passing the {@link #FIND_VIEWS_WITH_TEXT} and
8401     * {@link #FIND_VIEWS_WITH_CONTENT_DESCRIPTION} flags.
8402     *
8403     * @param outViews The output list of matching Views.
8404     * @param searched The text to match against.
8405     *
8406     * @see #FIND_VIEWS_WITH_TEXT
8407     * @see #FIND_VIEWS_WITH_CONTENT_DESCRIPTION
8408     * @see #setContentDescription(CharSequence)
8409     */
8410    public void findViewsWithText(ArrayList<View> outViews, CharSequence searched,
8411            @FindViewFlags int flags) {
8412        if (getAccessibilityNodeProvider() != null) {
8413            if ((flags & FIND_VIEWS_WITH_ACCESSIBILITY_NODE_PROVIDERS) != 0) {
8414                outViews.add(this);
8415            }
8416        } else if ((flags & FIND_VIEWS_WITH_CONTENT_DESCRIPTION) != 0
8417                && (searched != null && searched.length() > 0)
8418                && (mContentDescription != null && mContentDescription.length() > 0)) {
8419            String searchedLowerCase = searched.toString().toLowerCase();
8420            String contentDescriptionLowerCase = mContentDescription.toString().toLowerCase();
8421            if (contentDescriptionLowerCase.contains(searchedLowerCase)) {
8422                outViews.add(this);
8423            }
8424        }
8425    }
8426
8427    /**
8428     * Find and return all touchable views that are descendants of this view,
8429     * possibly including this view if it is touchable itself.
8430     *
8431     * @return A list of touchable views
8432     */
8433    public ArrayList<View> getTouchables() {
8434        ArrayList<View> result = new ArrayList<View>();
8435        addTouchables(result);
8436        return result;
8437    }
8438
8439    /**
8440     * Add any touchable views that are descendants of this view (possibly
8441     * including this view if it is touchable itself) to views.
8442     *
8443     * @param views Touchable views found so far
8444     */
8445    public void addTouchables(ArrayList<View> views) {
8446        final int viewFlags = mViewFlags;
8447
8448        if (((viewFlags & CLICKABLE) == CLICKABLE || (viewFlags & LONG_CLICKABLE) == LONG_CLICKABLE
8449                || (viewFlags & CONTEXT_CLICKABLE) == CONTEXT_CLICKABLE)
8450                && (viewFlags & ENABLED_MASK) == ENABLED) {
8451            views.add(this);
8452        }
8453    }
8454
8455    /**
8456     * Returns whether this View is accessibility focused.
8457     *
8458     * @return True if this View is accessibility focused.
8459     */
8460    public boolean isAccessibilityFocused() {
8461        return (mPrivateFlags2 & PFLAG2_ACCESSIBILITY_FOCUSED) != 0;
8462    }
8463
8464    /**
8465     * Call this to try to give accessibility focus to this view.
8466     *
8467     * A view will not actually take focus if {@link AccessibilityManager#isEnabled()}
8468     * returns false or the view is no visible or the view already has accessibility
8469     * focus.
8470     *
8471     * See also {@link #focusSearch(int)}, which is what you call to say that you
8472     * have focus, and you want your parent to look for the next one.
8473     *
8474     * @return Whether this view actually took accessibility focus.
8475     *
8476     * @hide
8477     */
8478    public boolean requestAccessibilityFocus() {
8479        AccessibilityManager manager = AccessibilityManager.getInstance(mContext);
8480        if (!manager.isEnabled() || !manager.isTouchExplorationEnabled()) {
8481            return false;
8482        }
8483        if ((mViewFlags & VISIBILITY_MASK) != VISIBLE) {
8484            return false;
8485        }
8486        if ((mPrivateFlags2 & PFLAG2_ACCESSIBILITY_FOCUSED) == 0) {
8487            mPrivateFlags2 |= PFLAG2_ACCESSIBILITY_FOCUSED;
8488            ViewRootImpl viewRootImpl = getViewRootImpl();
8489            if (viewRootImpl != null) {
8490                viewRootImpl.setAccessibilityFocus(this, null);
8491            }
8492            invalidate();
8493            sendAccessibilityEvent(AccessibilityEvent.TYPE_VIEW_ACCESSIBILITY_FOCUSED);
8494            return true;
8495        }
8496        return false;
8497    }
8498
8499    /**
8500     * Call this to try to clear accessibility focus of this view.
8501     *
8502     * See also {@link #focusSearch(int)}, which is what you call to say that you
8503     * have focus, and you want your parent to look for the next one.
8504     *
8505     * @hide
8506     */
8507    public void clearAccessibilityFocus() {
8508        clearAccessibilityFocusNoCallbacks();
8509
8510        // Clear the global reference of accessibility focus if this view or
8511        // any of its descendants had accessibility focus. This will NOT send
8512        // an event or update internal state if focus is cleared from a
8513        // descendant view, which may leave views in inconsistent states.
8514        final ViewRootImpl viewRootImpl = getViewRootImpl();
8515        if (viewRootImpl != null) {
8516            final View focusHost = viewRootImpl.getAccessibilityFocusedHost();
8517            if (focusHost != null && ViewRootImpl.isViewDescendantOf(focusHost, this)) {
8518                viewRootImpl.setAccessibilityFocus(null, null);
8519            }
8520        }
8521    }
8522
8523    private void sendAccessibilityHoverEvent(int eventType) {
8524        // Since we are not delivering to a client accessibility events from not
8525        // important views (unless the clinet request that) we need to fire the
8526        // event from the deepest view exposed to the client. As a consequence if
8527        // the user crosses a not exposed view the client will see enter and exit
8528        // of the exposed predecessor followed by and enter and exit of that same
8529        // predecessor when entering and exiting the not exposed descendant. This
8530        // is fine since the client has a clear idea which view is hovered at the
8531        // price of a couple more events being sent. This is a simple and
8532        // working solution.
8533        View source = this;
8534        while (true) {
8535            if (source.includeForAccessibility()) {
8536                source.sendAccessibilityEvent(eventType);
8537                return;
8538            }
8539            ViewParent parent = source.getParent();
8540            if (parent instanceof View) {
8541                source = (View) parent;
8542            } else {
8543                return;
8544            }
8545        }
8546    }
8547
8548    /**
8549     * Clears accessibility focus without calling any callback methods
8550     * normally invoked in {@link #clearAccessibilityFocus()}. This method
8551     * is used for clearing accessibility focus when giving this focus to
8552     * another view.
8553     */
8554    void clearAccessibilityFocusNoCallbacks() {
8555        if ((mPrivateFlags2 & PFLAG2_ACCESSIBILITY_FOCUSED) != 0) {
8556            mPrivateFlags2 &= ~PFLAG2_ACCESSIBILITY_FOCUSED;
8557            invalidate();
8558            sendAccessibilityEvent(AccessibilityEvent.TYPE_VIEW_ACCESSIBILITY_FOCUS_CLEARED);
8559        }
8560    }
8561
8562    /**
8563     * Call this to try to give focus to a specific view or to one of its
8564     * descendants.
8565     *
8566     * A view will not actually take focus if it is not focusable ({@link #isFocusable} returns
8567     * false), or if it is focusable and it is not focusable in touch mode
8568     * ({@link #isFocusableInTouchMode}) while the device is in touch mode.
8569     *
8570     * See also {@link #focusSearch(int)}, which is what you call to say that you
8571     * have focus, and you want your parent to look for the next one.
8572     *
8573     * This is equivalent to calling {@link #requestFocus(int, Rect)} with arguments
8574     * {@link #FOCUS_DOWN} and <code>null</code>.
8575     *
8576     * @return Whether this view or one of its descendants actually took focus.
8577     */
8578    public final boolean requestFocus() {
8579        return requestFocus(View.FOCUS_DOWN);
8580    }
8581
8582    /**
8583     * Call this to try to give focus to a specific view or to one of its
8584     * descendants and give it a hint about what direction focus is heading.
8585     *
8586     * A view will not actually take focus if it is not focusable ({@link #isFocusable} returns
8587     * false), or if it is focusable and it is not focusable in touch mode
8588     * ({@link #isFocusableInTouchMode}) while the device is in touch mode.
8589     *
8590     * See also {@link #focusSearch(int)}, which is what you call to say that you
8591     * have focus, and you want your parent to look for the next one.
8592     *
8593     * This is equivalent to calling {@link #requestFocus(int, Rect)} with
8594     * <code>null</code> set for the previously focused rectangle.
8595     *
8596     * @param direction One of FOCUS_UP, FOCUS_DOWN, FOCUS_LEFT, and FOCUS_RIGHT
8597     * @return Whether this view or one of its descendants actually took focus.
8598     */
8599    public final boolean requestFocus(int direction) {
8600        return requestFocus(direction, null);
8601    }
8602
8603    /**
8604     * Call this to try to give focus to a specific view or to one of its descendants
8605     * and give it hints about the direction and a specific rectangle that the focus
8606     * is coming from.  The rectangle can help give larger views a finer grained hint
8607     * about where focus is coming from, and therefore, where to show selection, or
8608     * forward focus change internally.
8609     *
8610     * A view will not actually take focus if it is not focusable ({@link #isFocusable} returns
8611     * false), or if it is focusable and it is not focusable in touch mode
8612     * ({@link #isFocusableInTouchMode}) while the device is in touch mode.
8613     *
8614     * A View will not take focus if it is not visible.
8615     *
8616     * A View will not take focus if one of its parents has
8617     * {@link android.view.ViewGroup#getDescendantFocusability()} equal to
8618     * {@link ViewGroup#FOCUS_BLOCK_DESCENDANTS}.
8619     *
8620     * See also {@link #focusSearch(int)}, which is what you call to say that you
8621     * have focus, and you want your parent to look for the next one.
8622     *
8623     * You may wish to override this method if your custom {@link View} has an internal
8624     * {@link View} that it wishes to forward the request to.
8625     *
8626     * @param direction One of FOCUS_UP, FOCUS_DOWN, FOCUS_LEFT, and FOCUS_RIGHT
8627     * @param previouslyFocusedRect The rectangle (in this View's coordinate system)
8628     *        to give a finer grained hint about where focus is coming from.  May be null
8629     *        if there is no hint.
8630     * @return Whether this view or one of its descendants actually took focus.
8631     */
8632    public boolean requestFocus(int direction, Rect previouslyFocusedRect) {
8633        return requestFocusNoSearch(direction, previouslyFocusedRect);
8634    }
8635
8636    private boolean requestFocusNoSearch(int direction, Rect previouslyFocusedRect) {
8637        // need to be focusable
8638        if ((mViewFlags & FOCUSABLE_MASK) != FOCUSABLE ||
8639                (mViewFlags & VISIBILITY_MASK) != VISIBLE) {
8640            return false;
8641        }
8642
8643        // need to be focusable in touch mode if in touch mode
8644        if (isInTouchMode() &&
8645            (FOCUSABLE_IN_TOUCH_MODE != (mViewFlags & FOCUSABLE_IN_TOUCH_MODE))) {
8646               return false;
8647        }
8648
8649        // need to not have any parents blocking us
8650        if (hasAncestorThatBlocksDescendantFocus()) {
8651            return false;
8652        }
8653
8654        handleFocusGainInternal(direction, previouslyFocusedRect);
8655        return true;
8656    }
8657
8658    /**
8659     * Call this to try to give focus to a specific view or to one of its descendants. This is a
8660     * special variant of {@link #requestFocus() } that will allow views that are not focusable in
8661     * touch mode to request focus when they are touched.
8662     *
8663     * @return Whether this view or one of its descendants actually took focus.
8664     *
8665     * @see #isInTouchMode()
8666     *
8667     */
8668    public final boolean requestFocusFromTouch() {
8669        // Leave touch mode if we need to
8670        if (isInTouchMode()) {
8671            ViewRootImpl viewRoot = getViewRootImpl();
8672            if (viewRoot != null) {
8673                viewRoot.ensureTouchMode(false);
8674            }
8675        }
8676        return requestFocus(View.FOCUS_DOWN);
8677    }
8678
8679    /**
8680     * @return Whether any ancestor of this view blocks descendant focus.
8681     */
8682    private boolean hasAncestorThatBlocksDescendantFocus() {
8683        final boolean focusableInTouchMode = isFocusableInTouchMode();
8684        ViewParent ancestor = mParent;
8685        while (ancestor instanceof ViewGroup) {
8686            final ViewGroup vgAncestor = (ViewGroup) ancestor;
8687            if (vgAncestor.getDescendantFocusability() == ViewGroup.FOCUS_BLOCK_DESCENDANTS
8688                    || (!focusableInTouchMode && vgAncestor.shouldBlockFocusForTouchscreen())) {
8689                return true;
8690            } else {
8691                ancestor = vgAncestor.getParent();
8692            }
8693        }
8694        return false;
8695    }
8696
8697    /**
8698     * Gets the mode for determining whether this View is important for accessibility
8699     * which is if it fires accessibility events and if it is reported to
8700     * accessibility services that query the screen.
8701     *
8702     * @return The mode for determining whether a View is important for accessibility.
8703     *
8704     * @attr ref android.R.styleable#View_importantForAccessibility
8705     *
8706     * @see #IMPORTANT_FOR_ACCESSIBILITY_YES
8707     * @see #IMPORTANT_FOR_ACCESSIBILITY_NO
8708     * @see #IMPORTANT_FOR_ACCESSIBILITY_NO_HIDE_DESCENDANTS
8709     * @see #IMPORTANT_FOR_ACCESSIBILITY_AUTO
8710     */
8711    @ViewDebug.ExportedProperty(category = "accessibility", mapping = {
8712            @ViewDebug.IntToString(from = IMPORTANT_FOR_ACCESSIBILITY_AUTO, to = "auto"),
8713            @ViewDebug.IntToString(from = IMPORTANT_FOR_ACCESSIBILITY_YES, to = "yes"),
8714            @ViewDebug.IntToString(from = IMPORTANT_FOR_ACCESSIBILITY_NO, to = "no"),
8715            @ViewDebug.IntToString(from = IMPORTANT_FOR_ACCESSIBILITY_NO_HIDE_DESCENDANTS,
8716                    to = "noHideDescendants")
8717        })
8718    public int getImportantForAccessibility() {
8719        return (mPrivateFlags2 & PFLAG2_IMPORTANT_FOR_ACCESSIBILITY_MASK)
8720                >> PFLAG2_IMPORTANT_FOR_ACCESSIBILITY_SHIFT;
8721    }
8722
8723    /**
8724     * Sets the live region mode for this view. This indicates to accessibility
8725     * services whether they should automatically notify the user about changes
8726     * to the view's content description or text, or to the content descriptions
8727     * or text of the view's children (where applicable).
8728     * <p>
8729     * For example, in a login screen with a TextView that displays an "incorrect
8730     * password" notification, that view should be marked as a live region with
8731     * mode {@link #ACCESSIBILITY_LIVE_REGION_POLITE}.
8732     * <p>
8733     * To disable change notifications for this view, use
8734     * {@link #ACCESSIBILITY_LIVE_REGION_NONE}. This is the default live region
8735     * mode for most views.
8736     * <p>
8737     * To indicate that the user should be notified of changes, use
8738     * {@link #ACCESSIBILITY_LIVE_REGION_POLITE}.
8739     * <p>
8740     * If the view's changes should interrupt ongoing speech and notify the user
8741     * immediately, use {@link #ACCESSIBILITY_LIVE_REGION_ASSERTIVE}.
8742     *
8743     * @param mode The live region mode for this view, one of:
8744     *        <ul>
8745     *        <li>{@link #ACCESSIBILITY_LIVE_REGION_NONE}
8746     *        <li>{@link #ACCESSIBILITY_LIVE_REGION_POLITE}
8747     *        <li>{@link #ACCESSIBILITY_LIVE_REGION_ASSERTIVE}
8748     *        </ul>
8749     * @attr ref android.R.styleable#View_accessibilityLiveRegion
8750     */
8751    public void setAccessibilityLiveRegion(int mode) {
8752        if (mode != getAccessibilityLiveRegion()) {
8753            mPrivateFlags2 &= ~PFLAG2_ACCESSIBILITY_LIVE_REGION_MASK;
8754            mPrivateFlags2 |= (mode << PFLAG2_ACCESSIBILITY_LIVE_REGION_SHIFT)
8755                    & PFLAG2_ACCESSIBILITY_LIVE_REGION_MASK;
8756            notifyViewAccessibilityStateChangedIfNeeded(
8757                    AccessibilityEvent.CONTENT_CHANGE_TYPE_UNDEFINED);
8758        }
8759    }
8760
8761    /**
8762     * Gets the live region mode for this View.
8763     *
8764     * @return The live region mode for the view.
8765     *
8766     * @attr ref android.R.styleable#View_accessibilityLiveRegion
8767     *
8768     * @see #setAccessibilityLiveRegion(int)
8769     */
8770    public int getAccessibilityLiveRegion() {
8771        return (mPrivateFlags2 & PFLAG2_ACCESSIBILITY_LIVE_REGION_MASK)
8772                >> PFLAG2_ACCESSIBILITY_LIVE_REGION_SHIFT;
8773    }
8774
8775    /**
8776     * Sets how to determine whether this view is important for accessibility
8777     * which is if it fires accessibility events and if it is reported to
8778     * accessibility services that query the screen.
8779     *
8780     * @param mode How to determine whether this view is important for accessibility.
8781     *
8782     * @attr ref android.R.styleable#View_importantForAccessibility
8783     *
8784     * @see #IMPORTANT_FOR_ACCESSIBILITY_YES
8785     * @see #IMPORTANT_FOR_ACCESSIBILITY_NO
8786     * @see #IMPORTANT_FOR_ACCESSIBILITY_NO_HIDE_DESCENDANTS
8787     * @see #IMPORTANT_FOR_ACCESSIBILITY_AUTO
8788     */
8789    public void setImportantForAccessibility(int mode) {
8790        final int oldMode = getImportantForAccessibility();
8791        if (mode != oldMode) {
8792            final boolean hideDescendants =
8793                    mode == IMPORTANT_FOR_ACCESSIBILITY_NO_HIDE_DESCENDANTS;
8794
8795            // If this node or its descendants are no longer important, try to
8796            // clear accessibility focus.
8797            if (mode == IMPORTANT_FOR_ACCESSIBILITY_NO || hideDescendants) {
8798                final View focusHost = findAccessibilityFocusHost(hideDescendants);
8799                if (focusHost != null) {
8800                    focusHost.clearAccessibilityFocus();
8801                }
8802            }
8803
8804            // If we're moving between AUTO and another state, we might not need
8805            // to send a subtree changed notification. We'll store the computed
8806            // importance, since we'll need to check it later to make sure.
8807            final boolean maySkipNotify = oldMode == IMPORTANT_FOR_ACCESSIBILITY_AUTO
8808                    || mode == IMPORTANT_FOR_ACCESSIBILITY_AUTO;
8809            final boolean oldIncludeForAccessibility = maySkipNotify && includeForAccessibility();
8810            mPrivateFlags2 &= ~PFLAG2_IMPORTANT_FOR_ACCESSIBILITY_MASK;
8811            mPrivateFlags2 |= (mode << PFLAG2_IMPORTANT_FOR_ACCESSIBILITY_SHIFT)
8812                    & PFLAG2_IMPORTANT_FOR_ACCESSIBILITY_MASK;
8813            if (!maySkipNotify || oldIncludeForAccessibility != includeForAccessibility()) {
8814                notifySubtreeAccessibilityStateChangedIfNeeded();
8815            } else {
8816                notifyViewAccessibilityStateChangedIfNeeded(
8817                        AccessibilityEvent.CONTENT_CHANGE_TYPE_UNDEFINED);
8818            }
8819        }
8820    }
8821
8822    /**
8823     * Returns the view within this view's hierarchy that is hosting
8824     * accessibility focus.
8825     *
8826     * @param searchDescendants whether to search for focus in descendant views
8827     * @return the view hosting accessibility focus, or {@code null}
8828     */
8829    private View findAccessibilityFocusHost(boolean searchDescendants) {
8830        if (isAccessibilityFocusedViewOrHost()) {
8831            return this;
8832        }
8833
8834        if (searchDescendants) {
8835            final ViewRootImpl viewRoot = getViewRootImpl();
8836            if (viewRoot != null) {
8837                final View focusHost = viewRoot.getAccessibilityFocusedHost();
8838                if (focusHost != null && ViewRootImpl.isViewDescendantOf(focusHost, this)) {
8839                    return focusHost;
8840                }
8841            }
8842        }
8843
8844        return null;
8845    }
8846
8847    /**
8848     * Computes whether this view should be exposed for accessibility. In
8849     * general, views that are interactive or provide information are exposed
8850     * while views that serve only as containers are hidden.
8851     * <p>
8852     * If an ancestor of this view has importance
8853     * {@link #IMPORTANT_FOR_ACCESSIBILITY_NO_HIDE_DESCENDANTS}, this method
8854     * returns <code>false</code>.
8855     * <p>
8856     * Otherwise, the value is computed according to the view's
8857     * {@link #getImportantForAccessibility()} value:
8858     * <ol>
8859     * <li>{@link #IMPORTANT_FOR_ACCESSIBILITY_NO} or
8860     * {@link #IMPORTANT_FOR_ACCESSIBILITY_NO_HIDE_DESCENDANTS}, return <code>false
8861     * </code>
8862     * <li>{@link #IMPORTANT_FOR_ACCESSIBILITY_YES}, return <code>true</code>
8863     * <li>{@link #IMPORTANT_FOR_ACCESSIBILITY_AUTO}, return <code>true</code> if
8864     * view satisfies any of the following:
8865     * <ul>
8866     * <li>Is actionable, e.g. {@link #isClickable()},
8867     * {@link #isLongClickable()}, or {@link #isFocusable()}
8868     * <li>Has an {@link AccessibilityDelegate}
8869     * <li>Has an interaction listener, e.g. {@link OnTouchListener},
8870     * {@link OnKeyListener}, etc.
8871     * <li>Is an accessibility live region, e.g.
8872     * {@link #getAccessibilityLiveRegion()} is not
8873     * {@link #ACCESSIBILITY_LIVE_REGION_NONE}.
8874     * </ul>
8875     * </ol>
8876     *
8877     * @return Whether the view is exposed for accessibility.
8878     * @see #setImportantForAccessibility(int)
8879     * @see #getImportantForAccessibility()
8880     */
8881    public boolean isImportantForAccessibility() {
8882        final int mode = (mPrivateFlags2 & PFLAG2_IMPORTANT_FOR_ACCESSIBILITY_MASK)
8883                >> PFLAG2_IMPORTANT_FOR_ACCESSIBILITY_SHIFT;
8884        if (mode == IMPORTANT_FOR_ACCESSIBILITY_NO
8885                || mode == IMPORTANT_FOR_ACCESSIBILITY_NO_HIDE_DESCENDANTS) {
8886            return false;
8887        }
8888
8889        // Check parent mode to ensure we're not hidden.
8890        ViewParent parent = mParent;
8891        while (parent instanceof View) {
8892            if (((View) parent).getImportantForAccessibility()
8893                    == IMPORTANT_FOR_ACCESSIBILITY_NO_HIDE_DESCENDANTS) {
8894                return false;
8895            }
8896            parent = parent.getParent();
8897        }
8898
8899        return mode == IMPORTANT_FOR_ACCESSIBILITY_YES || isActionableForAccessibility()
8900                || hasListenersForAccessibility() || getAccessibilityNodeProvider() != null
8901                || getAccessibilityLiveRegion() != ACCESSIBILITY_LIVE_REGION_NONE;
8902    }
8903
8904    /**
8905     * Gets the parent for accessibility purposes. Note that the parent for
8906     * accessibility is not necessary the immediate parent. It is the first
8907     * predecessor that is important for accessibility.
8908     *
8909     * @return The parent for accessibility purposes.
8910     */
8911    public ViewParent getParentForAccessibility() {
8912        if (mParent instanceof View) {
8913            View parentView = (View) mParent;
8914            if (parentView.includeForAccessibility()) {
8915                return mParent;
8916            } else {
8917                return mParent.getParentForAccessibility();
8918            }
8919        }
8920        return null;
8921    }
8922
8923    /**
8924     * Adds the children of this View relevant for accessibility to the given list
8925     * as output. Since some Views are not important for accessibility the added
8926     * child views are not necessarily direct children of this view, rather they are
8927     * the first level of descendants important for accessibility.
8928     *
8929     * @param outChildren The output list that will receive children for accessibility.
8930     */
8931    public void addChildrenForAccessibility(ArrayList<View> outChildren) {
8932
8933    }
8934
8935    /**
8936     * Whether to regard this view for accessibility. A view is regarded for
8937     * accessibility if it is important for accessibility or the querying
8938     * accessibility service has explicitly requested that view not
8939     * important for accessibility are regarded.
8940     *
8941     * @return Whether to regard the view for accessibility.
8942     *
8943     * @hide
8944     */
8945    public boolean includeForAccessibility() {
8946        if (mAttachInfo != null) {
8947            return (mAttachInfo.mAccessibilityFetchFlags
8948                    & AccessibilityNodeInfo.FLAG_INCLUDE_NOT_IMPORTANT_VIEWS) != 0
8949                    || isImportantForAccessibility();
8950        }
8951        return false;
8952    }
8953
8954    /**
8955     * Returns whether the View is considered actionable from
8956     * accessibility perspective. Such view are important for
8957     * accessibility.
8958     *
8959     * @return True if the view is actionable for accessibility.
8960     *
8961     * @hide
8962     */
8963    public boolean isActionableForAccessibility() {
8964        return (isClickable() || isLongClickable() || isFocusable());
8965    }
8966
8967    /**
8968     * Returns whether the View has registered callbacks which makes it
8969     * important for accessibility.
8970     *
8971     * @return True if the view is actionable for accessibility.
8972     */
8973    private boolean hasListenersForAccessibility() {
8974        ListenerInfo info = getListenerInfo();
8975        return mTouchDelegate != null || info.mOnKeyListener != null
8976                || info.mOnTouchListener != null || info.mOnGenericMotionListener != null
8977                || info.mOnHoverListener != null || info.mOnDragListener != null;
8978    }
8979
8980    /**
8981     * Notifies that the accessibility state of this view changed. The change
8982     * is local to this view and does not represent structural changes such
8983     * as children and parent. For example, the view became focusable. The
8984     * notification is at at most once every
8985     * {@link ViewConfiguration#getSendRecurringAccessibilityEventsInterval()}
8986     * to avoid unnecessary load to the system. Also once a view has a pending
8987     * notification this method is a NOP until the notification has been sent.
8988     *
8989     * @hide
8990     */
8991    public void notifyViewAccessibilityStateChangedIfNeeded(int changeType) {
8992        if (!AccessibilityManager.getInstance(mContext).isEnabled() || mAttachInfo == null) {
8993            return;
8994        }
8995        if (mSendViewStateChangedAccessibilityEvent == null) {
8996            mSendViewStateChangedAccessibilityEvent =
8997                    new SendViewStateChangedAccessibilityEvent();
8998        }
8999        mSendViewStateChangedAccessibilityEvent.runOrPost(changeType);
9000    }
9001
9002    /**
9003     * Notifies that the accessibility state of this view changed. The change
9004     * is *not* local to this view and does represent structural changes such
9005     * as children and parent. For example, the view size changed. The
9006     * notification is at at most once every
9007     * {@link ViewConfiguration#getSendRecurringAccessibilityEventsInterval()}
9008     * to avoid unnecessary load to the system. Also once a view has a pending
9009     * notification this method is a NOP until the notification has been sent.
9010     *
9011     * @hide
9012     */
9013    public void notifySubtreeAccessibilityStateChangedIfNeeded() {
9014        if (!AccessibilityManager.getInstance(mContext).isEnabled() || mAttachInfo == null) {
9015            return;
9016        }
9017        if ((mPrivateFlags2 & PFLAG2_SUBTREE_ACCESSIBILITY_STATE_CHANGED) == 0) {
9018            mPrivateFlags2 |= PFLAG2_SUBTREE_ACCESSIBILITY_STATE_CHANGED;
9019            if (mParent != null) {
9020                try {
9021                    mParent.notifySubtreeAccessibilityStateChanged(
9022                            this, this, AccessibilityEvent.CONTENT_CHANGE_TYPE_SUBTREE);
9023                } catch (AbstractMethodError e) {
9024                    Log.e(VIEW_LOG_TAG, mParent.getClass().getSimpleName() +
9025                            " does not fully implement ViewParent", e);
9026                }
9027            }
9028        }
9029    }
9030
9031    /**
9032     * Change the visibility of the View without triggering any other changes. This is
9033     * important for transitions, where visibility changes should not adjust focus or
9034     * trigger a new layout. This is only used when the visibility has already been changed
9035     * and we need a transient value during an animation. When the animation completes,
9036     * the original visibility value is always restored.
9037     *
9038     * @param visibility One of {@link #VISIBLE}, {@link #INVISIBLE}, or {@link #GONE}.
9039     * @hide
9040     */
9041    public void setTransitionVisibility(@Visibility int visibility) {
9042        mViewFlags = (mViewFlags & ~View.VISIBILITY_MASK) | visibility;
9043    }
9044
9045    /**
9046     * Reset the flag indicating the accessibility state of the subtree rooted
9047     * at this view changed.
9048     */
9049    void resetSubtreeAccessibilityStateChanged() {
9050        mPrivateFlags2 &= ~PFLAG2_SUBTREE_ACCESSIBILITY_STATE_CHANGED;
9051    }
9052
9053    /**
9054     * Report an accessibility action to this view's parents for delegated processing.
9055     *
9056     * <p>Implementations of {@link #performAccessibilityAction(int, Bundle)} may internally
9057     * call this method to delegate an accessibility action to a supporting parent. If the parent
9058     * returns true from its
9059     * {@link ViewParent#onNestedPrePerformAccessibilityAction(View, int, android.os.Bundle)}
9060     * method this method will return true to signify that the action was consumed.</p>
9061     *
9062     * <p>This method is useful for implementing nested scrolling child views. If
9063     * {@link #isNestedScrollingEnabled()} returns true and the action is a scrolling action
9064     * a custom view implementation may invoke this method to allow a parent to consume the
9065     * scroll first. If this method returns true the custom view should skip its own scrolling
9066     * behavior.</p>
9067     *
9068     * @param action Accessibility action to delegate
9069     * @param arguments Optional action arguments
9070     * @return true if the action was consumed by a parent
9071     */
9072    public boolean dispatchNestedPrePerformAccessibilityAction(int action, Bundle arguments) {
9073        for (ViewParent p = getParent(); p != null; p = p.getParent()) {
9074            if (p.onNestedPrePerformAccessibilityAction(this, action, arguments)) {
9075                return true;
9076            }
9077        }
9078        return false;
9079    }
9080
9081    /**
9082     * Performs the specified accessibility action on the view. For
9083     * possible accessibility actions look at {@link AccessibilityNodeInfo}.
9084     * <p>
9085     * If an {@link AccessibilityDelegate} has been specified via calling
9086     * {@link #setAccessibilityDelegate(AccessibilityDelegate)} its
9087     * {@link AccessibilityDelegate#performAccessibilityAction(View, int, Bundle)}
9088     * is responsible for handling this call.
9089     * </p>
9090     *
9091     * <p>The default implementation will delegate
9092     * {@link AccessibilityNodeInfo#ACTION_SCROLL_BACKWARD} and
9093     * {@link AccessibilityNodeInfo#ACTION_SCROLL_FORWARD} to nested scrolling parents if
9094     * {@link #isNestedScrollingEnabled() nested scrolling is enabled} on this view.</p>
9095     *
9096     * @param action The action to perform.
9097     * @param arguments Optional action arguments.
9098     * @return Whether the action was performed.
9099     */
9100    public boolean performAccessibilityAction(int action, Bundle arguments) {
9101      if (mAccessibilityDelegate != null) {
9102          return mAccessibilityDelegate.performAccessibilityAction(this, action, arguments);
9103      } else {
9104          return performAccessibilityActionInternal(action, arguments);
9105      }
9106    }
9107
9108   /**
9109    * @see #performAccessibilityAction(int, Bundle)
9110    *
9111    * Note: Called from the default {@link AccessibilityDelegate}.
9112    *
9113    * @hide
9114    */
9115    public boolean performAccessibilityActionInternal(int action, Bundle arguments) {
9116        if (isNestedScrollingEnabled()
9117                && (action == AccessibilityNodeInfo.ACTION_SCROLL_BACKWARD
9118                || action == AccessibilityNodeInfo.ACTION_SCROLL_FORWARD
9119                || action == R.id.accessibilityActionScrollUp
9120                || action == R.id.accessibilityActionScrollLeft
9121                || action == R.id.accessibilityActionScrollDown
9122                || action == R.id.accessibilityActionScrollRight)) {
9123            if (dispatchNestedPrePerformAccessibilityAction(action, arguments)) {
9124                return true;
9125            }
9126        }
9127
9128        switch (action) {
9129            case AccessibilityNodeInfo.ACTION_CLICK: {
9130                if (isClickable()) {
9131                    performClick();
9132                    return true;
9133                }
9134            } break;
9135            case AccessibilityNodeInfo.ACTION_LONG_CLICK: {
9136                if (isLongClickable()) {
9137                    performLongClick();
9138                    return true;
9139                }
9140            } break;
9141            case AccessibilityNodeInfo.ACTION_FOCUS: {
9142                if (!hasFocus()) {
9143                    // Get out of touch mode since accessibility
9144                    // wants to move focus around.
9145                    getViewRootImpl().ensureTouchMode(false);
9146                    return requestFocus();
9147                }
9148            } break;
9149            case AccessibilityNodeInfo.ACTION_CLEAR_FOCUS: {
9150                if (hasFocus()) {
9151                    clearFocus();
9152                    return !isFocused();
9153                }
9154            } break;
9155            case AccessibilityNodeInfo.ACTION_SELECT: {
9156                if (!isSelected()) {
9157                    setSelected(true);
9158                    return isSelected();
9159                }
9160            } break;
9161            case AccessibilityNodeInfo.ACTION_CLEAR_SELECTION: {
9162                if (isSelected()) {
9163                    setSelected(false);
9164                    return !isSelected();
9165                }
9166            } break;
9167            case AccessibilityNodeInfo.ACTION_ACCESSIBILITY_FOCUS: {
9168                if (!isAccessibilityFocused()) {
9169                    return requestAccessibilityFocus();
9170                }
9171            } break;
9172            case AccessibilityNodeInfo.ACTION_CLEAR_ACCESSIBILITY_FOCUS: {
9173                if (isAccessibilityFocused()) {
9174                    clearAccessibilityFocus();
9175                    return true;
9176                }
9177            } break;
9178            case AccessibilityNodeInfo.ACTION_NEXT_AT_MOVEMENT_GRANULARITY: {
9179                if (arguments != null) {
9180                    final int granularity = arguments.getInt(
9181                            AccessibilityNodeInfo.ACTION_ARGUMENT_MOVEMENT_GRANULARITY_INT);
9182                    final boolean extendSelection = arguments.getBoolean(
9183                            AccessibilityNodeInfo.ACTION_ARGUMENT_EXTEND_SELECTION_BOOLEAN);
9184                    return traverseAtGranularity(granularity, true, extendSelection);
9185                }
9186            } break;
9187            case AccessibilityNodeInfo.ACTION_PREVIOUS_AT_MOVEMENT_GRANULARITY: {
9188                if (arguments != null) {
9189                    final int granularity = arguments.getInt(
9190                            AccessibilityNodeInfo.ACTION_ARGUMENT_MOVEMENT_GRANULARITY_INT);
9191                    final boolean extendSelection = arguments.getBoolean(
9192                            AccessibilityNodeInfo.ACTION_ARGUMENT_EXTEND_SELECTION_BOOLEAN);
9193                    return traverseAtGranularity(granularity, false, extendSelection);
9194                }
9195            } break;
9196            case AccessibilityNodeInfo.ACTION_SET_SELECTION: {
9197                CharSequence text = getIterableTextForAccessibility();
9198                if (text == null) {
9199                    return false;
9200                }
9201                final int start = (arguments != null) ? arguments.getInt(
9202                        AccessibilityNodeInfo.ACTION_ARGUMENT_SELECTION_START_INT, -1) : -1;
9203                final int end = (arguments != null) ? arguments.getInt(
9204                AccessibilityNodeInfo.ACTION_ARGUMENT_SELECTION_END_INT, -1) : -1;
9205                // Only cursor position can be specified (selection length == 0)
9206                if ((getAccessibilitySelectionStart() != start
9207                        || getAccessibilitySelectionEnd() != end)
9208                        && (start == end)) {
9209                    setAccessibilitySelection(start, end);
9210                    notifyViewAccessibilityStateChangedIfNeeded(
9211                            AccessibilityEvent.CONTENT_CHANGE_TYPE_UNDEFINED);
9212                    return true;
9213                }
9214            } break;
9215            case R.id.accessibilityActionShowOnScreen: {
9216                if (mAttachInfo != null) {
9217                    final Rect r = mAttachInfo.mTmpInvalRect;
9218                    getDrawingRect(r);
9219                    return requestRectangleOnScreen(r, true);
9220                }
9221            } break;
9222            case R.id.accessibilityActionContextClick: {
9223                if (isContextClickable()) {
9224                    performContextClick();
9225                    return true;
9226                }
9227            } break;
9228        }
9229        return false;
9230    }
9231
9232    private boolean traverseAtGranularity(int granularity, boolean forward,
9233            boolean extendSelection) {
9234        CharSequence text = getIterableTextForAccessibility();
9235        if (text == null || text.length() == 0) {
9236            return false;
9237        }
9238        TextSegmentIterator iterator = getIteratorForGranularity(granularity);
9239        if (iterator == null) {
9240            return false;
9241        }
9242        int current = getAccessibilitySelectionEnd();
9243        if (current == ACCESSIBILITY_CURSOR_POSITION_UNDEFINED) {
9244            current = forward ? 0 : text.length();
9245        }
9246        final int[] range = forward ? iterator.following(current) : iterator.preceding(current);
9247        if (range == null) {
9248            return false;
9249        }
9250        final int segmentStart = range[0];
9251        final int segmentEnd = range[1];
9252        int selectionStart;
9253        int selectionEnd;
9254        if (extendSelection && isAccessibilitySelectionExtendable()) {
9255            selectionStart = getAccessibilitySelectionStart();
9256            if (selectionStart == ACCESSIBILITY_CURSOR_POSITION_UNDEFINED) {
9257                selectionStart = forward ? segmentStart : segmentEnd;
9258            }
9259            selectionEnd = forward ? segmentEnd : segmentStart;
9260        } else {
9261            selectionStart = selectionEnd= forward ? segmentEnd : segmentStart;
9262        }
9263        setAccessibilitySelection(selectionStart, selectionEnd);
9264        final int action = forward ? AccessibilityNodeInfo.ACTION_NEXT_AT_MOVEMENT_GRANULARITY
9265                : AccessibilityNodeInfo.ACTION_PREVIOUS_AT_MOVEMENT_GRANULARITY;
9266        sendViewTextTraversedAtGranularityEvent(action, granularity, segmentStart, segmentEnd);
9267        return true;
9268    }
9269
9270    /**
9271     * Gets the text reported for accessibility purposes.
9272     *
9273     * @return The accessibility text.
9274     *
9275     * @hide
9276     */
9277    public CharSequence getIterableTextForAccessibility() {
9278        return getContentDescription();
9279    }
9280
9281    /**
9282     * Gets whether accessibility selection can be extended.
9283     *
9284     * @return If selection is extensible.
9285     *
9286     * @hide
9287     */
9288    public boolean isAccessibilitySelectionExtendable() {
9289        return false;
9290    }
9291
9292    /**
9293     * @hide
9294     */
9295    public int getAccessibilitySelectionStart() {
9296        return mAccessibilityCursorPosition;
9297    }
9298
9299    /**
9300     * @hide
9301     */
9302    public int getAccessibilitySelectionEnd() {
9303        return getAccessibilitySelectionStart();
9304    }
9305
9306    /**
9307     * @hide
9308     */
9309    public void setAccessibilitySelection(int start, int end) {
9310        if (start ==  end && end == mAccessibilityCursorPosition) {
9311            return;
9312        }
9313        if (start >= 0 && start == end && end <= getIterableTextForAccessibility().length()) {
9314            mAccessibilityCursorPosition = start;
9315        } else {
9316            mAccessibilityCursorPosition = ACCESSIBILITY_CURSOR_POSITION_UNDEFINED;
9317        }
9318        sendAccessibilityEvent(AccessibilityEvent.TYPE_VIEW_TEXT_SELECTION_CHANGED);
9319    }
9320
9321    private void sendViewTextTraversedAtGranularityEvent(int action, int granularity,
9322            int fromIndex, int toIndex) {
9323        if (mParent == null) {
9324            return;
9325        }
9326        AccessibilityEvent event = AccessibilityEvent.obtain(
9327                AccessibilityEvent.TYPE_VIEW_TEXT_TRAVERSED_AT_MOVEMENT_GRANULARITY);
9328        onInitializeAccessibilityEvent(event);
9329        onPopulateAccessibilityEvent(event);
9330        event.setFromIndex(fromIndex);
9331        event.setToIndex(toIndex);
9332        event.setAction(action);
9333        event.setMovementGranularity(granularity);
9334        mParent.requestSendAccessibilityEvent(this, event);
9335    }
9336
9337    /**
9338     * @hide
9339     */
9340    public TextSegmentIterator getIteratorForGranularity(int granularity) {
9341        switch (granularity) {
9342            case AccessibilityNodeInfo.MOVEMENT_GRANULARITY_CHARACTER: {
9343                CharSequence text = getIterableTextForAccessibility();
9344                if (text != null && text.length() > 0) {
9345                    CharacterTextSegmentIterator iterator =
9346                        CharacterTextSegmentIterator.getInstance(
9347                                mContext.getResources().getConfiguration().locale);
9348                    iterator.initialize(text.toString());
9349                    return iterator;
9350                }
9351            } break;
9352            case AccessibilityNodeInfo.MOVEMENT_GRANULARITY_WORD: {
9353                CharSequence text = getIterableTextForAccessibility();
9354                if (text != null && text.length() > 0) {
9355                    WordTextSegmentIterator iterator =
9356                        WordTextSegmentIterator.getInstance(
9357                                mContext.getResources().getConfiguration().locale);
9358                    iterator.initialize(text.toString());
9359                    return iterator;
9360                }
9361            } break;
9362            case AccessibilityNodeInfo.MOVEMENT_GRANULARITY_PARAGRAPH: {
9363                CharSequence text = getIterableTextForAccessibility();
9364                if (text != null && text.length() > 0) {
9365                    ParagraphTextSegmentIterator iterator =
9366                        ParagraphTextSegmentIterator.getInstance();
9367                    iterator.initialize(text.toString());
9368                    return iterator;
9369                }
9370            } break;
9371        }
9372        return null;
9373    }
9374
9375    /**
9376     * @hide
9377     */
9378    public void dispatchStartTemporaryDetach() {
9379        onStartTemporaryDetach();
9380    }
9381
9382    /**
9383     * This is called when a container is going to temporarily detach a child, with
9384     * {@link ViewGroup#detachViewFromParent(View) ViewGroup.detachViewFromParent}.
9385     * It will either be followed by {@link #onFinishTemporaryDetach()} or
9386     * {@link #onDetachedFromWindow()} when the container is done.
9387     */
9388    public void onStartTemporaryDetach() {
9389        removeUnsetPressCallback();
9390        mPrivateFlags |= PFLAG_CANCEL_NEXT_UP_EVENT;
9391    }
9392
9393    /**
9394     * @hide
9395     */
9396    public void dispatchFinishTemporaryDetach() {
9397        onFinishTemporaryDetach();
9398    }
9399
9400    /**
9401     * Called after {@link #onStartTemporaryDetach} when the container is done
9402     * changing the view.
9403     */
9404    public void onFinishTemporaryDetach() {
9405    }
9406
9407    /**
9408     * Return the global {@link KeyEvent.DispatcherState KeyEvent.DispatcherState}
9409     * for this view's window.  Returns null if the view is not currently attached
9410     * to the window.  Normally you will not need to use this directly, but
9411     * just use the standard high-level event callbacks like
9412     * {@link #onKeyDown(int, KeyEvent)}.
9413     */
9414    public KeyEvent.DispatcherState getKeyDispatcherState() {
9415        return mAttachInfo != null ? mAttachInfo.mKeyDispatchState : null;
9416    }
9417
9418    /**
9419     * Dispatch a key event before it is processed by any input method
9420     * associated with the view hierarchy.  This can be used to intercept
9421     * key events in special situations before the IME consumes them; a
9422     * typical example would be handling the BACK key to update the application's
9423     * UI instead of allowing the IME to see it and close itself.
9424     *
9425     * @param event The key event to be dispatched.
9426     * @return True if the event was handled, false otherwise.
9427     */
9428    public boolean dispatchKeyEventPreIme(KeyEvent event) {
9429        return onKeyPreIme(event.getKeyCode(), event);
9430    }
9431
9432    /**
9433     * Dispatch a key event to the next view on the focus path. This path runs
9434     * from the top of the view tree down to the currently focused view. If this
9435     * view has focus, it will dispatch to itself. Otherwise it will dispatch
9436     * the next node down the focus path. This method also fires any key
9437     * listeners.
9438     *
9439     * @param event The key event to be dispatched.
9440     * @return True if the event was handled, false otherwise.
9441     */
9442    public boolean dispatchKeyEvent(KeyEvent event) {
9443        if (mInputEventConsistencyVerifier != null) {
9444            mInputEventConsistencyVerifier.onKeyEvent(event, 0);
9445        }
9446
9447        // Give any attached key listener a first crack at the event.
9448        //noinspection SimplifiableIfStatement
9449        ListenerInfo li = mListenerInfo;
9450        if (li != null && li.mOnKeyListener != null && (mViewFlags & ENABLED_MASK) == ENABLED
9451                && li.mOnKeyListener.onKey(this, event.getKeyCode(), event)) {
9452            return true;
9453        }
9454
9455        if (event.dispatch(this, mAttachInfo != null
9456                ? mAttachInfo.mKeyDispatchState : null, this)) {
9457            return true;
9458        }
9459
9460        if (mInputEventConsistencyVerifier != null) {
9461            mInputEventConsistencyVerifier.onUnhandledEvent(event, 0);
9462        }
9463        return false;
9464    }
9465
9466    /**
9467     * Dispatches a key shortcut event.
9468     *
9469     * @param event The key event to be dispatched.
9470     * @return True if the event was handled by the view, false otherwise.
9471     */
9472    public boolean dispatchKeyShortcutEvent(KeyEvent event) {
9473        return onKeyShortcut(event.getKeyCode(), event);
9474    }
9475
9476    /**
9477     * Pass the touch screen motion event down to the target view, or this
9478     * view if it is the target.
9479     *
9480     * @param event The motion event to be dispatched.
9481     * @return True if the event was handled by the view, false otherwise.
9482     */
9483    public boolean dispatchTouchEvent(MotionEvent event) {
9484        // If the event should be handled by accessibility focus first.
9485        if (event.isTargetAccessibilityFocus()) {
9486            // We don't have focus or no virtual descendant has it, do not handle the event.
9487            if (!isAccessibilityFocusedViewOrHost()) {
9488                return false;
9489            }
9490            // We have focus and got the event, then use normal event dispatch.
9491            event.setTargetAccessibilityFocus(false);
9492        }
9493
9494        boolean result = false;
9495
9496        if (mInputEventConsistencyVerifier != null) {
9497            mInputEventConsistencyVerifier.onTouchEvent(event, 0);
9498        }
9499
9500        final int actionMasked = event.getActionMasked();
9501        if (actionMasked == MotionEvent.ACTION_DOWN) {
9502            // Defensive cleanup for new gesture
9503            stopNestedScroll();
9504        }
9505
9506        if (onFilterTouchEventForSecurity(event)) {
9507            //noinspection SimplifiableIfStatement
9508            ListenerInfo li = mListenerInfo;
9509            if (li != null && li.mOnTouchListener != null
9510                    && (mViewFlags & ENABLED_MASK) == ENABLED
9511                    && li.mOnTouchListener.onTouch(this, event)) {
9512                result = true;
9513            }
9514
9515            if (!result && onTouchEvent(event)) {
9516                result = true;
9517            }
9518        }
9519
9520        if (!result && mInputEventConsistencyVerifier != null) {
9521            mInputEventConsistencyVerifier.onUnhandledEvent(event, 0);
9522        }
9523
9524        // Clean up after nested scrolls if this is the end of a gesture;
9525        // also cancel it if we tried an ACTION_DOWN but we didn't want the rest
9526        // of the gesture.
9527        if (actionMasked == MotionEvent.ACTION_UP ||
9528                actionMasked == MotionEvent.ACTION_CANCEL ||
9529                (actionMasked == MotionEvent.ACTION_DOWN && !result)) {
9530            stopNestedScroll();
9531        }
9532
9533        return result;
9534    }
9535
9536    boolean isAccessibilityFocusedViewOrHost() {
9537        return isAccessibilityFocused() || (getViewRootImpl() != null && getViewRootImpl()
9538                .getAccessibilityFocusedHost() == this);
9539    }
9540
9541    /**
9542     * Filter the touch event to apply security policies.
9543     *
9544     * @param event The motion event to be filtered.
9545     * @return True if the event should be dispatched, false if the event should be dropped.
9546     *
9547     * @see #getFilterTouchesWhenObscured
9548     */
9549    public boolean onFilterTouchEventForSecurity(MotionEvent event) {
9550        //noinspection RedundantIfStatement
9551        if ((mViewFlags & FILTER_TOUCHES_WHEN_OBSCURED) != 0
9552                && (event.getFlags() & MotionEvent.FLAG_WINDOW_IS_OBSCURED) != 0) {
9553            // Window is obscured, drop this touch.
9554            return false;
9555        }
9556        return true;
9557    }
9558
9559    /**
9560     * Pass a trackball motion event down to the focused view.
9561     *
9562     * @param event The motion event to be dispatched.
9563     * @return True if the event was handled by the view, false otherwise.
9564     */
9565    public boolean dispatchTrackballEvent(MotionEvent event) {
9566        if (mInputEventConsistencyVerifier != null) {
9567            mInputEventConsistencyVerifier.onTrackballEvent(event, 0);
9568        }
9569
9570        return onTrackballEvent(event);
9571    }
9572
9573    /**
9574     * Dispatch a generic motion event.
9575     * <p>
9576     * Generic motion events with source class {@link InputDevice#SOURCE_CLASS_POINTER}
9577     * are delivered to the view under the pointer.  All other generic motion events are
9578     * delivered to the focused view.  Hover events are handled specially and are delivered
9579     * to {@link #onHoverEvent(MotionEvent)}.
9580     * </p>
9581     *
9582     * @param event The motion event to be dispatched.
9583     * @return True if the event was handled by the view, false otherwise.
9584     */
9585    public boolean dispatchGenericMotionEvent(MotionEvent event) {
9586        if (mInputEventConsistencyVerifier != null) {
9587            mInputEventConsistencyVerifier.onGenericMotionEvent(event, 0);
9588        }
9589
9590        final int source = event.getSource();
9591        if ((source & InputDevice.SOURCE_CLASS_POINTER) != 0) {
9592            final int action = event.getAction();
9593            if (action == MotionEvent.ACTION_HOVER_ENTER
9594                    || action == MotionEvent.ACTION_HOVER_MOVE
9595                    || action == MotionEvent.ACTION_HOVER_EXIT) {
9596                if (dispatchHoverEvent(event)) {
9597                    return true;
9598                }
9599            } else if (dispatchGenericPointerEvent(event)) {
9600                return true;
9601            }
9602        } else if (dispatchGenericFocusedEvent(event)) {
9603            return true;
9604        }
9605
9606        if (dispatchGenericMotionEventInternal(event)) {
9607            return true;
9608        }
9609
9610        if (mInputEventConsistencyVerifier != null) {
9611            mInputEventConsistencyVerifier.onUnhandledEvent(event, 0);
9612        }
9613        return false;
9614    }
9615
9616    private boolean dispatchGenericMotionEventInternal(MotionEvent event) {
9617        //noinspection SimplifiableIfStatement
9618        ListenerInfo li = mListenerInfo;
9619        if (li != null && li.mOnGenericMotionListener != null
9620                && (mViewFlags & ENABLED_MASK) == ENABLED
9621                && li.mOnGenericMotionListener.onGenericMotion(this, event)) {
9622            return true;
9623        }
9624
9625        if (onGenericMotionEvent(event)) {
9626            return true;
9627        }
9628
9629        final int actionButton = event.getActionButton();
9630        switch (event.getActionMasked()) {
9631            case MotionEvent.ACTION_BUTTON_PRESS:
9632                if (isContextClickable() && !mInContextButtonPress && !mHasPerformedLongPress
9633                        && (actionButton == MotionEvent.BUTTON_STYLUS_PRIMARY
9634                        || actionButton == MotionEvent.BUTTON_SECONDARY)) {
9635                    if (performContextClick()) {
9636                        mInContextButtonPress = true;
9637                        setPressed(true, event.getX(), event.getY());
9638                        removeTapCallback();
9639                        removeLongPressCallback();
9640                        return true;
9641                    }
9642                }
9643                break;
9644
9645            case MotionEvent.ACTION_BUTTON_RELEASE:
9646                if (mInContextButtonPress && (actionButton == MotionEvent.BUTTON_STYLUS_PRIMARY
9647                        || actionButton == MotionEvent.BUTTON_SECONDARY)) {
9648                    mInContextButtonPress = false;
9649                    mIgnoreNextUpEvent = true;
9650                }
9651                break;
9652        }
9653
9654        if (mInputEventConsistencyVerifier != null) {
9655            mInputEventConsistencyVerifier.onUnhandledEvent(event, 0);
9656        }
9657        return false;
9658    }
9659
9660    /**
9661     * Dispatch a hover event.
9662     * <p>
9663     * Do not call this method directly.
9664     * Call {@link #dispatchGenericMotionEvent(MotionEvent)} instead.
9665     * </p>
9666     *
9667     * @param event The motion event to be dispatched.
9668     * @return True if the event was handled by the view, false otherwise.
9669     */
9670    protected boolean dispatchHoverEvent(MotionEvent event) {
9671        ListenerInfo li = mListenerInfo;
9672        //noinspection SimplifiableIfStatement
9673        if (li != null && li.mOnHoverListener != null
9674                && (mViewFlags & ENABLED_MASK) == ENABLED
9675                && li.mOnHoverListener.onHover(this, event)) {
9676            return true;
9677        }
9678
9679        return onHoverEvent(event);
9680    }
9681
9682    /**
9683     * Returns true if the view has a child to which it has recently sent
9684     * {@link MotionEvent#ACTION_HOVER_ENTER}.  If this view is hovered and
9685     * it does not have a hovered child, then it must be the innermost hovered view.
9686     * @hide
9687     */
9688    protected boolean hasHoveredChild() {
9689        return false;
9690    }
9691
9692    /**
9693     * Dispatch a generic motion event to the view under the first pointer.
9694     * <p>
9695     * Do not call this method directly.
9696     * Call {@link #dispatchGenericMotionEvent(MotionEvent)} instead.
9697     * </p>
9698     *
9699     * @param event The motion event to be dispatched.
9700     * @return True if the event was handled by the view, false otherwise.
9701     */
9702    protected boolean dispatchGenericPointerEvent(MotionEvent event) {
9703        return false;
9704    }
9705
9706    /**
9707     * Dispatch a generic motion event to the currently focused view.
9708     * <p>
9709     * Do not call this method directly.
9710     * Call {@link #dispatchGenericMotionEvent(MotionEvent)} instead.
9711     * </p>
9712     *
9713     * @param event The motion event to be dispatched.
9714     * @return True if the event was handled by the view, false otherwise.
9715     */
9716    protected boolean dispatchGenericFocusedEvent(MotionEvent event) {
9717        return false;
9718    }
9719
9720    /**
9721     * Dispatch a pointer event.
9722     * <p>
9723     * Dispatches touch related pointer events to {@link #onTouchEvent(MotionEvent)} and all
9724     * other events to {@link #onGenericMotionEvent(MotionEvent)}.  This separation of concerns
9725     * reinforces the invariant that {@link #onTouchEvent(MotionEvent)} is really about touches
9726     * and should not be expected to handle other pointing device features.
9727     * </p>
9728     *
9729     * @param event The motion event to be dispatched.
9730     * @return True if the event was handled by the view, false otherwise.
9731     * @hide
9732     */
9733    public final boolean dispatchPointerEvent(MotionEvent event) {
9734        if (event.isTouchEvent()) {
9735            return dispatchTouchEvent(event);
9736        } else {
9737            return dispatchGenericMotionEvent(event);
9738        }
9739    }
9740
9741    /**
9742     * Called when the window containing this view gains or loses window focus.
9743     * ViewGroups should override to route to their children.
9744     *
9745     * @param hasFocus True if the window containing this view now has focus,
9746     *        false otherwise.
9747     */
9748    public void dispatchWindowFocusChanged(boolean hasFocus) {
9749        onWindowFocusChanged(hasFocus);
9750    }
9751
9752    /**
9753     * Called when the window containing this view gains or loses focus.  Note
9754     * that this is separate from view focus: to receive key events, both
9755     * your view and its window must have focus.  If a window is displayed
9756     * on top of yours that takes input focus, then your own window will lose
9757     * focus but the view focus will remain unchanged.
9758     *
9759     * @param hasWindowFocus True if the window containing this view now has
9760     *        focus, false otherwise.
9761     */
9762    public void onWindowFocusChanged(boolean hasWindowFocus) {
9763        InputMethodManager imm = InputMethodManager.peekInstance();
9764        if (!hasWindowFocus) {
9765            if (isPressed()) {
9766                setPressed(false);
9767            }
9768            if (imm != null && (mPrivateFlags & PFLAG_FOCUSED) != 0) {
9769                imm.focusOut(this);
9770            }
9771            removeLongPressCallback();
9772            removeTapCallback();
9773            onFocusLost();
9774        } else if (imm != null && (mPrivateFlags & PFLAG_FOCUSED) != 0) {
9775            imm.focusIn(this);
9776        }
9777        refreshDrawableState();
9778    }
9779
9780    /**
9781     * Returns true if this view is in a window that currently has window focus.
9782     * Note that this is not the same as the view itself having focus.
9783     *
9784     * @return True if this view is in a window that currently has window focus.
9785     */
9786    public boolean hasWindowFocus() {
9787        return mAttachInfo != null && mAttachInfo.mHasWindowFocus;
9788    }
9789
9790    /**
9791     * Dispatch a view visibility change down the view hierarchy.
9792     * ViewGroups should override to route to their children.
9793     * @param changedView The view whose visibility changed. Could be 'this' or
9794     * an ancestor view.
9795     * @param visibility The new visibility of changedView: {@link #VISIBLE},
9796     * {@link #INVISIBLE} or {@link #GONE}.
9797     */
9798    protected void dispatchVisibilityChanged(@NonNull View changedView,
9799            @Visibility int visibility) {
9800        onVisibilityChanged(changedView, visibility);
9801    }
9802
9803    /**
9804     * Called when the visibility of the view or an ancestor of the view has
9805     * changed.
9806     *
9807     * @param changedView The view whose visibility changed. May be
9808     *                    {@code this} or an ancestor view.
9809     * @param visibility The new visibility, one of {@link #VISIBLE},
9810     *                   {@link #INVISIBLE} or {@link #GONE}.
9811     */
9812    protected void onVisibilityChanged(@NonNull View changedView, @Visibility int visibility) {
9813        final boolean visible = visibility == VISIBLE && getVisibility() == VISIBLE;
9814        if (visible && mAttachInfo != null) {
9815            initialAwakenScrollBars();
9816        }
9817
9818        final Drawable dr = mBackground;
9819        if (dr != null && visible != dr.isVisible()) {
9820            dr.setVisible(visible, false);
9821        }
9822        final Drawable fg = mForegroundInfo != null ? mForegroundInfo.mDrawable : null;
9823        if (fg != null && visible != fg.isVisible()) {
9824            fg.setVisible(visible, false);
9825        }
9826    }
9827
9828    /**
9829     * Dispatch a hint about whether this view is displayed. For instance, when
9830     * a View moves out of the screen, it might receives a display hint indicating
9831     * the view is not displayed. Applications should not <em>rely</em> on this hint
9832     * as there is no guarantee that they will receive one.
9833     *
9834     * @param hint A hint about whether or not this view is displayed:
9835     * {@link #VISIBLE} or {@link #INVISIBLE}.
9836     */
9837    public void dispatchDisplayHint(@Visibility int hint) {
9838        onDisplayHint(hint);
9839    }
9840
9841    /**
9842     * Gives this view a hint about whether is displayed or not. For instance, when
9843     * a View moves out of the screen, it might receives a display hint indicating
9844     * the view is not displayed. Applications should not <em>rely</em> on this hint
9845     * as there is no guarantee that they will receive one.
9846     *
9847     * @param hint A hint about whether or not this view is displayed:
9848     * {@link #VISIBLE} or {@link #INVISIBLE}.
9849     */
9850    protected void onDisplayHint(@Visibility int hint) {
9851    }
9852
9853    /**
9854     * Dispatch a window visibility change down the view hierarchy.
9855     * ViewGroups should override to route to their children.
9856     *
9857     * @param visibility The new visibility of the window.
9858     *
9859     * @see #onWindowVisibilityChanged(int)
9860     */
9861    public void dispatchWindowVisibilityChanged(@Visibility int visibility) {
9862        onWindowVisibilityChanged(visibility);
9863    }
9864
9865    /**
9866     * Called when the window containing has change its visibility
9867     * (between {@link #GONE}, {@link #INVISIBLE}, and {@link #VISIBLE}).  Note
9868     * that this tells you whether or not your window is being made visible
9869     * to the window manager; this does <em>not</em> tell you whether or not
9870     * your window is obscured by other windows on the screen, even if it
9871     * is itself visible.
9872     *
9873     * @param visibility The new visibility of the window.
9874     */
9875    protected void onWindowVisibilityChanged(@Visibility int visibility) {
9876        if (visibility == VISIBLE) {
9877            initialAwakenScrollBars();
9878        }
9879    }
9880
9881    /**
9882     * Returns the current visibility of the window this view is attached to
9883     * (either {@link #GONE}, {@link #INVISIBLE}, or {@link #VISIBLE}).
9884     *
9885     * @return Returns the current visibility of the view's window.
9886     */
9887    @Visibility
9888    public int getWindowVisibility() {
9889        return mAttachInfo != null ? mAttachInfo.mWindowVisibility : GONE;
9890    }
9891
9892    /**
9893     * Retrieve the overall visible display size in which the window this view is
9894     * attached to has been positioned in.  This takes into account screen
9895     * decorations above the window, for both cases where the window itself
9896     * is being position inside of them or the window is being placed under
9897     * then and covered insets are used for the window to position its content
9898     * inside.  In effect, this tells you the available area where content can
9899     * be placed and remain visible to users.
9900     *
9901     * <p>This function requires an IPC back to the window manager to retrieve
9902     * the requested information, so should not be used in performance critical
9903     * code like drawing.
9904     *
9905     * @param outRect Filled in with the visible display frame.  If the view
9906     * is not attached to a window, this is simply the raw display size.
9907     */
9908    public void getWindowVisibleDisplayFrame(Rect outRect) {
9909        if (mAttachInfo != null) {
9910            try {
9911                mAttachInfo.mSession.getDisplayFrame(mAttachInfo.mWindow, outRect);
9912            } catch (RemoteException e) {
9913                return;
9914            }
9915            // XXX This is really broken, and probably all needs to be done
9916            // in the window manager, and we need to know more about whether
9917            // we want the area behind or in front of the IME.
9918            final Rect insets = mAttachInfo.mVisibleInsets;
9919            outRect.left += insets.left;
9920            outRect.top += insets.top;
9921            outRect.right -= insets.right;
9922            outRect.bottom -= insets.bottom;
9923            return;
9924        }
9925        // The view is not attached to a display so we don't have a context.
9926        // Make a best guess about the display size.
9927        Display d = DisplayManagerGlobal.getInstance().getRealDisplay(Display.DEFAULT_DISPLAY);
9928        d.getRectSize(outRect);
9929    }
9930
9931    /**
9932     * Dispatch a notification about a resource configuration change down
9933     * the view hierarchy.
9934     * ViewGroups should override to route to their children.
9935     *
9936     * @param newConfig The new resource configuration.
9937     *
9938     * @see #onConfigurationChanged(android.content.res.Configuration)
9939     */
9940    public void dispatchConfigurationChanged(Configuration newConfig) {
9941        onConfigurationChanged(newConfig);
9942    }
9943
9944    /**
9945     * Called when the current configuration of the resources being used
9946     * by the application have changed.  You can use this to decide when
9947     * to reload resources that can changed based on orientation and other
9948     * configuration characteristics.  You only need to use this if you are
9949     * not relying on the normal {@link android.app.Activity} mechanism of
9950     * recreating the activity instance upon a configuration change.
9951     *
9952     * @param newConfig The new resource configuration.
9953     */
9954    protected void onConfigurationChanged(Configuration newConfig) {
9955    }
9956
9957    /**
9958     * Private function to aggregate all per-view attributes in to the view
9959     * root.
9960     */
9961    void dispatchCollectViewAttributes(AttachInfo attachInfo, int visibility) {
9962        performCollectViewAttributes(attachInfo, visibility);
9963    }
9964
9965    void performCollectViewAttributes(AttachInfo attachInfo, int visibility) {
9966        if ((visibility & VISIBILITY_MASK) == VISIBLE) {
9967            if ((mViewFlags & KEEP_SCREEN_ON) == KEEP_SCREEN_ON) {
9968                attachInfo.mKeepScreenOn = true;
9969            }
9970            attachInfo.mSystemUiVisibility |= mSystemUiVisibility;
9971            ListenerInfo li = mListenerInfo;
9972            if (li != null && li.mOnSystemUiVisibilityChangeListener != null) {
9973                attachInfo.mHasSystemUiListeners = true;
9974            }
9975        }
9976    }
9977
9978    void needGlobalAttributesUpdate(boolean force) {
9979        final AttachInfo ai = mAttachInfo;
9980        if (ai != null && !ai.mRecomputeGlobalAttributes) {
9981            if (force || ai.mKeepScreenOn || (ai.mSystemUiVisibility != 0)
9982                    || ai.mHasSystemUiListeners) {
9983                ai.mRecomputeGlobalAttributes = true;
9984            }
9985        }
9986    }
9987
9988    /**
9989     * Returns whether the device is currently in touch mode.  Touch mode is entered
9990     * once the user begins interacting with the device by touch, and affects various
9991     * things like whether focus is always visible to the user.
9992     *
9993     * @return Whether the device is in touch mode.
9994     */
9995    @ViewDebug.ExportedProperty
9996    public boolean isInTouchMode() {
9997        if (mAttachInfo != null) {
9998            return mAttachInfo.mInTouchMode;
9999        } else {
10000            return ViewRootImpl.isInTouchMode();
10001        }
10002    }
10003
10004    /**
10005     * Returns the context the view is running in, through which it can
10006     * access the current theme, resources, etc.
10007     *
10008     * @return The view's Context.
10009     */
10010    @ViewDebug.CapturedViewProperty
10011    public final Context getContext() {
10012        return mContext;
10013    }
10014
10015    /**
10016     * Handle a key event before it is processed by any input method
10017     * associated with the view hierarchy.  This can be used to intercept
10018     * key events in special situations before the IME consumes them; a
10019     * typical example would be handling the BACK key to update the application's
10020     * UI instead of allowing the IME to see it and close itself.
10021     *
10022     * @param keyCode The value in event.getKeyCode().
10023     * @param event Description of the key event.
10024     * @return If you handled the event, return true. If you want to allow the
10025     *         event to be handled by the next receiver, return false.
10026     */
10027    public boolean onKeyPreIme(int keyCode, KeyEvent event) {
10028        return false;
10029    }
10030
10031    /**
10032     * Default implementation of {@link KeyEvent.Callback#onKeyDown(int, KeyEvent)
10033     * KeyEvent.Callback.onKeyDown()}: perform press of the view
10034     * when {@link KeyEvent#KEYCODE_DPAD_CENTER} or {@link KeyEvent#KEYCODE_ENTER}
10035     * is released, if the view is enabled and clickable.
10036     *
10037     * <p>Key presses in software keyboards will generally NOT trigger this listener,
10038     * although some may elect to do so in some situations. Do not rely on this to
10039     * catch software key presses.
10040     *
10041     * @param keyCode A key code that represents the button pressed, from
10042     *                {@link android.view.KeyEvent}.
10043     * @param event   The KeyEvent object that defines the button action.
10044     */
10045    public boolean onKeyDown(int keyCode, KeyEvent event) {
10046        boolean result = false;
10047
10048        if (KeyEvent.isConfirmKey(keyCode)) {
10049            if ((mViewFlags & ENABLED_MASK) == DISABLED) {
10050                return true;
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                setPressed(true);
10057                checkForLongClick(0);
10058                return true;
10059            }
10060        }
10061        return result;
10062    }
10063
10064    /**
10065     * Default implementation of {@link KeyEvent.Callback#onKeyLongPress(int, KeyEvent)
10066     * KeyEvent.Callback.onKeyLongPress()}: always returns false (doesn't handle
10067     * the event).
10068     * <p>Key presses in software keyboards will generally NOT trigger this listener,
10069     * although some may elect to do so in some situations. Do not rely on this to
10070     * catch software key presses.
10071     */
10072    public boolean onKeyLongPress(int keyCode, KeyEvent event) {
10073        return false;
10074    }
10075
10076    /**
10077     * Default implementation of {@link KeyEvent.Callback#onKeyUp(int, KeyEvent)
10078     * KeyEvent.Callback.onKeyUp()}: perform clicking of the view
10079     * when {@link KeyEvent#KEYCODE_DPAD_CENTER} or
10080     * {@link KeyEvent#KEYCODE_ENTER} is released.
10081     * <p>Key presses in software keyboards will generally NOT trigger this listener,
10082     * although some may elect to do so in some situations. Do not rely on this to
10083     * catch software key presses.
10084     *
10085     * @param keyCode A key code that represents the button pressed, from
10086     *                {@link android.view.KeyEvent}.
10087     * @param event   The KeyEvent object that defines the button action.
10088     */
10089    public boolean onKeyUp(int keyCode, KeyEvent event) {
10090        if (KeyEvent.isConfirmKey(keyCode)) {
10091            if ((mViewFlags & ENABLED_MASK) == DISABLED) {
10092                return true;
10093            }
10094            if ((mViewFlags & CLICKABLE) == CLICKABLE && isPressed()) {
10095                setPressed(false);
10096
10097                if (!mHasPerformedLongPress) {
10098                    // This is a tap, so remove the longpress check
10099                    removeLongPressCallback();
10100                    return performClick();
10101                }
10102            }
10103        }
10104        return false;
10105    }
10106
10107    /**
10108     * Default implementation of {@link KeyEvent.Callback#onKeyMultiple(int, int, KeyEvent)
10109     * KeyEvent.Callback.onKeyMultiple()}: always returns false (doesn't handle
10110     * the event).
10111     * <p>Key presses in software keyboards will generally NOT trigger this listener,
10112     * although some may elect to do so in some situations. Do not rely on this to
10113     * catch software key presses.
10114     *
10115     * @param keyCode     A key code that represents the button pressed, from
10116     *                    {@link android.view.KeyEvent}.
10117     * @param repeatCount The number of times the action was made.
10118     * @param event       The KeyEvent object that defines the button action.
10119     */
10120    public boolean onKeyMultiple(int keyCode, int repeatCount, KeyEvent event) {
10121        return false;
10122    }
10123
10124    /**
10125     * Called on the focused view when a key shortcut event is not handled.
10126     * Override this method to implement local key shortcuts for the View.
10127     * Key shortcuts can also be implemented by setting the
10128     * {@link MenuItem#setShortcut(char, char) shortcut} property of menu items.
10129     *
10130     * @param keyCode The value in event.getKeyCode().
10131     * @param event Description of the key event.
10132     * @return If you handled the event, return true. If you want to allow the
10133     *         event to be handled by the next receiver, return false.
10134     */
10135    public boolean onKeyShortcut(int keyCode, KeyEvent event) {
10136        return false;
10137    }
10138
10139    /**
10140     * Check whether the called view is a text editor, in which case it
10141     * would make sense to automatically display a soft input window for
10142     * it.  Subclasses should override this if they implement
10143     * {@link #onCreateInputConnection(EditorInfo)} to return true if
10144     * a call on that method would return a non-null InputConnection, and
10145     * they are really a first-class editor that the user would normally
10146     * start typing on when the go into a window containing your view.
10147     *
10148     * <p>The default implementation always returns false.  This does
10149     * <em>not</em> mean that its {@link #onCreateInputConnection(EditorInfo)}
10150     * will not be called or the user can not otherwise perform edits on your
10151     * view; it is just a hint to the system that this is not the primary
10152     * purpose of this view.
10153     *
10154     * @return Returns true if this view is a text editor, else false.
10155     */
10156    public boolean onCheckIsTextEditor() {
10157        return false;
10158    }
10159
10160    /**
10161     * Create a new InputConnection for an InputMethod to interact
10162     * with the view.  The default implementation returns null, since it doesn't
10163     * support input methods.  You can override this to implement such support.
10164     * This is only needed for views that take focus and text input.
10165     *
10166     * <p>When implementing this, you probably also want to implement
10167     * {@link #onCheckIsTextEditor()} to indicate you will return a
10168     * non-null InputConnection.</p>
10169     *
10170     * <p>Also, take good care to fill in the {@link android.view.inputmethod.EditorInfo}
10171     * object correctly and in its entirety, so that the connected IME can rely
10172     * on its values. For example, {@link android.view.inputmethod.EditorInfo#initialSelStart}
10173     * and  {@link android.view.inputmethod.EditorInfo#initialSelEnd} members
10174     * must be filled in with the correct cursor position for IMEs to work correctly
10175     * with your application.</p>
10176     *
10177     * @param outAttrs Fill in with attribute information about the connection.
10178     */
10179    public InputConnection onCreateInputConnection(EditorInfo outAttrs) {
10180        return null;
10181    }
10182
10183    /**
10184     * Called by the {@link android.view.inputmethod.InputMethodManager}
10185     * when a view who is not the current
10186     * input connection target is trying to make a call on the manager.  The
10187     * default implementation returns false; you can override this to return
10188     * true for certain views if you are performing InputConnection proxying
10189     * to them.
10190     * @param view The View that is making the InputMethodManager call.
10191     * @return Return true to allow the call, false to reject.
10192     */
10193    public boolean checkInputConnectionProxy(View view) {
10194        return false;
10195    }
10196
10197    /**
10198     * Show the context menu for this view. It is not safe to hold on to the
10199     * menu after returning from this method.
10200     *
10201     * You should normally not overload this method. Overload
10202     * {@link #onCreateContextMenu(ContextMenu)} or define an
10203     * {@link OnCreateContextMenuListener} to add items to the context menu.
10204     *
10205     * @param menu The context menu to populate
10206     */
10207    public void createContextMenu(ContextMenu menu) {
10208        ContextMenuInfo menuInfo = getContextMenuInfo();
10209
10210        // Sets the current menu info so all items added to menu will have
10211        // my extra info set.
10212        ((MenuBuilder)menu).setCurrentMenuInfo(menuInfo);
10213
10214        onCreateContextMenu(menu);
10215        ListenerInfo li = mListenerInfo;
10216        if (li != null && li.mOnCreateContextMenuListener != null) {
10217            li.mOnCreateContextMenuListener.onCreateContextMenu(menu, this, menuInfo);
10218        }
10219
10220        // Clear the extra information so subsequent items that aren't mine don't
10221        // have my extra info.
10222        ((MenuBuilder)menu).setCurrentMenuInfo(null);
10223
10224        if (mParent != null) {
10225            mParent.createContextMenu(menu);
10226        }
10227    }
10228
10229    /**
10230     * Views should implement this if they have extra information to associate
10231     * with the context menu. The return result is supplied as a parameter to
10232     * the {@link OnCreateContextMenuListener#onCreateContextMenu(ContextMenu, View, ContextMenuInfo)}
10233     * callback.
10234     *
10235     * @return Extra information about the item for which the context menu
10236     *         should be shown. This information will vary across different
10237     *         subclasses of View.
10238     */
10239    protected ContextMenuInfo getContextMenuInfo() {
10240        return null;
10241    }
10242
10243    /**
10244     * Views should implement this if the view itself is going to add items to
10245     * the context menu.
10246     *
10247     * @param menu the context menu to populate
10248     */
10249    protected void onCreateContextMenu(ContextMenu menu) {
10250    }
10251
10252    /**
10253     * Implement this method to handle trackball motion events.  The
10254     * <em>relative</em> movement of the trackball since the last event
10255     * can be retrieve with {@link MotionEvent#getX MotionEvent.getX()} and
10256     * {@link MotionEvent#getY MotionEvent.getY()}.  These are normalized so
10257     * that a movement of 1 corresponds to the user pressing one DPAD key (so
10258     * they will often be fractional values, representing the more fine-grained
10259     * movement information available from a trackball).
10260     *
10261     * @param event The motion event.
10262     * @return True if the event was handled, false otherwise.
10263     */
10264    public boolean onTrackballEvent(MotionEvent event) {
10265        return false;
10266    }
10267
10268    /**
10269     * Implement this method to handle generic motion events.
10270     * <p>
10271     * Generic motion events describe joystick movements, mouse hovers, track pad
10272     * touches, scroll wheel movements and other input events.  The
10273     * {@link MotionEvent#getSource() source} of the motion event specifies
10274     * the class of input that was received.  Implementations of this method
10275     * must examine the bits in the source before processing the event.
10276     * The following code example shows how this is done.
10277     * </p><p>
10278     * Generic motion events with source class {@link InputDevice#SOURCE_CLASS_POINTER}
10279     * are delivered to the view under the pointer.  All other generic motion events are
10280     * delivered to the focused view.
10281     * </p>
10282     * <pre> public boolean onGenericMotionEvent(MotionEvent event) {
10283     *     if (event.isFromSource(InputDevice.SOURCE_CLASS_JOYSTICK)) {
10284     *         if (event.getAction() == MotionEvent.ACTION_MOVE) {
10285     *             // process the joystick movement...
10286     *             return true;
10287     *         }
10288     *     }
10289     *     if (event.isFromSource(InputDevice.SOURCE_CLASS_POINTER)) {
10290     *         switch (event.getAction()) {
10291     *             case MotionEvent.ACTION_HOVER_MOVE:
10292     *                 // process the mouse hover movement...
10293     *                 return true;
10294     *             case MotionEvent.ACTION_SCROLL:
10295     *                 // process the scroll wheel movement...
10296     *                 return true;
10297     *         }
10298     *     }
10299     *     return super.onGenericMotionEvent(event);
10300     * }</pre>
10301     *
10302     * @param event The generic motion event being processed.
10303     * @return True if the event was handled, false otherwise.
10304     */
10305    public boolean onGenericMotionEvent(MotionEvent event) {
10306        return false;
10307    }
10308
10309    /**
10310     * Implement this method to handle hover events.
10311     * <p>
10312     * This method is called whenever a pointer is hovering into, over, or out of the
10313     * bounds of a view and the view is not currently being touched.
10314     * Hover events are represented as pointer events with action
10315     * {@link MotionEvent#ACTION_HOVER_ENTER}, {@link MotionEvent#ACTION_HOVER_MOVE},
10316     * or {@link MotionEvent#ACTION_HOVER_EXIT}.
10317     * </p>
10318     * <ul>
10319     * <li>The view receives a hover event with action {@link MotionEvent#ACTION_HOVER_ENTER}
10320     * when the pointer enters the bounds of the view.</li>
10321     * <li>The view receives a hover event with action {@link MotionEvent#ACTION_HOVER_MOVE}
10322     * when the pointer has already entered the bounds of the view and has moved.</li>
10323     * <li>The view receives a hover event with action {@link MotionEvent#ACTION_HOVER_EXIT}
10324     * when the pointer has exited the bounds of the view or when the pointer is
10325     * about to go down due to a button click, tap, or similar user action that
10326     * causes the view to be touched.</li>
10327     * </ul>
10328     * <p>
10329     * The view should implement this method to return true to indicate that it is
10330     * handling the hover event, such as by changing its drawable state.
10331     * </p><p>
10332     * The default implementation calls {@link #setHovered} to update the hovered state
10333     * of the view when a hover enter or hover exit event is received, if the view
10334     * is enabled and is clickable.  The default implementation also sends hover
10335     * accessibility events.
10336     * </p>
10337     *
10338     * @param event The motion event that describes the hover.
10339     * @return True if the view handled the hover event.
10340     *
10341     * @see #isHovered
10342     * @see #setHovered
10343     * @see #onHoverChanged
10344     */
10345    public boolean onHoverEvent(MotionEvent event) {
10346        // The root view may receive hover (or touch) events that are outside the bounds of
10347        // the window.  This code ensures that we only send accessibility events for
10348        // hovers that are actually within the bounds of the root view.
10349        final int action = event.getActionMasked();
10350        if (!mSendingHoverAccessibilityEvents) {
10351            if ((action == MotionEvent.ACTION_HOVER_ENTER
10352                    || action == MotionEvent.ACTION_HOVER_MOVE)
10353                    && !hasHoveredChild()
10354                    && pointInView(event.getX(), event.getY())) {
10355                sendAccessibilityHoverEvent(AccessibilityEvent.TYPE_VIEW_HOVER_ENTER);
10356                mSendingHoverAccessibilityEvents = true;
10357            }
10358        } else {
10359            if (action == MotionEvent.ACTION_HOVER_EXIT
10360                    || (action == MotionEvent.ACTION_MOVE
10361                            && !pointInView(event.getX(), event.getY()))) {
10362                mSendingHoverAccessibilityEvents = false;
10363                sendAccessibilityHoverEvent(AccessibilityEvent.TYPE_VIEW_HOVER_EXIT);
10364            }
10365        }
10366
10367        if (isHoverable()) {
10368            switch (action) {
10369                case MotionEvent.ACTION_HOVER_ENTER:
10370                    setHovered(true);
10371                    break;
10372                case MotionEvent.ACTION_HOVER_EXIT:
10373                    setHovered(false);
10374                    break;
10375            }
10376
10377            // Dispatch the event to onGenericMotionEvent before returning true.
10378            // This is to provide compatibility with existing applications that
10379            // handled HOVER_MOVE events in onGenericMotionEvent and that would
10380            // break because of the new default handling for hoverable views
10381            // in onHoverEvent.
10382            // Note that onGenericMotionEvent will be called by default when
10383            // onHoverEvent returns false (refer to dispatchGenericMotionEvent).
10384            dispatchGenericMotionEventInternal(event);
10385            // The event was already handled by calling setHovered(), so always
10386            // return true.
10387            return true;
10388        }
10389
10390        return false;
10391    }
10392
10393    /**
10394     * Returns true if the view should handle {@link #onHoverEvent}
10395     * by calling {@link #setHovered} to change its hovered state.
10396     *
10397     * @return True if the view is hoverable.
10398     */
10399    private boolean isHoverable() {
10400        final int viewFlags = mViewFlags;
10401        if ((viewFlags & ENABLED_MASK) == DISABLED) {
10402            return false;
10403        }
10404
10405        return (viewFlags & CLICKABLE) == CLICKABLE
10406                || (viewFlags & LONG_CLICKABLE) == LONG_CLICKABLE
10407                || (viewFlags & CONTEXT_CLICKABLE) == CONTEXT_CLICKABLE;
10408    }
10409
10410    /**
10411     * Returns true if the view is currently hovered.
10412     *
10413     * @return True if the view is currently hovered.
10414     *
10415     * @see #setHovered
10416     * @see #onHoverChanged
10417     */
10418    @ViewDebug.ExportedProperty
10419    public boolean isHovered() {
10420        return (mPrivateFlags & PFLAG_HOVERED) != 0;
10421    }
10422
10423    /**
10424     * Sets whether the view is currently hovered.
10425     * <p>
10426     * Calling this method also changes the drawable state of the view.  This
10427     * enables the view to react to hover by using different drawable resources
10428     * to change its appearance.
10429     * </p><p>
10430     * The {@link #onHoverChanged} method is called when the hovered state changes.
10431     * </p>
10432     *
10433     * @param hovered True if the view is hovered.
10434     *
10435     * @see #isHovered
10436     * @see #onHoverChanged
10437     */
10438    public void setHovered(boolean hovered) {
10439        if (hovered) {
10440            if ((mPrivateFlags & PFLAG_HOVERED) == 0) {
10441                mPrivateFlags |= PFLAG_HOVERED;
10442                refreshDrawableState();
10443                onHoverChanged(true);
10444            }
10445        } else {
10446            if ((mPrivateFlags & PFLAG_HOVERED) != 0) {
10447                mPrivateFlags &= ~PFLAG_HOVERED;
10448                refreshDrawableState();
10449                onHoverChanged(false);
10450            }
10451        }
10452    }
10453
10454    /**
10455     * Implement this method to handle hover state changes.
10456     * <p>
10457     * This method is called whenever the hover state changes as a result of a
10458     * call to {@link #setHovered}.
10459     * </p>
10460     *
10461     * @param hovered The current hover state, as returned by {@link #isHovered}.
10462     *
10463     * @see #isHovered
10464     * @see #setHovered
10465     */
10466    public void onHoverChanged(boolean hovered) {
10467    }
10468
10469    /**
10470     * Implement this method to handle touch screen motion events.
10471     * <p>
10472     * If this method is used to detect click actions, it is recommended that
10473     * the actions be performed by implementing and calling
10474     * {@link #performClick()}. This will ensure consistent system behavior,
10475     * including:
10476     * <ul>
10477     * <li>obeying click sound preferences
10478     * <li>dispatching OnClickListener calls
10479     * <li>handling {@link AccessibilityNodeInfo#ACTION_CLICK ACTION_CLICK} when
10480     * accessibility features are enabled
10481     * </ul>
10482     *
10483     * @param event The motion event.
10484     * @return True if the event was handled, false otherwise.
10485     */
10486    public boolean onTouchEvent(MotionEvent event) {
10487        final float x = event.getX();
10488        final float y = event.getY();
10489        final int viewFlags = mViewFlags;
10490        final int action = event.getAction();
10491
10492        if ((viewFlags & ENABLED_MASK) == DISABLED) {
10493            if (action == MotionEvent.ACTION_UP && (mPrivateFlags & PFLAG_PRESSED) != 0) {
10494                setPressed(false);
10495            }
10496            // A disabled view that is clickable still consumes the touch
10497            // events, it just doesn't respond to them.
10498            return (((viewFlags & CLICKABLE) == CLICKABLE
10499                    || (viewFlags & LONG_CLICKABLE) == LONG_CLICKABLE)
10500                    || (viewFlags & CONTEXT_CLICKABLE) == CONTEXT_CLICKABLE);
10501        }
10502
10503        if (mTouchDelegate != null) {
10504            if (mTouchDelegate.onTouchEvent(event)) {
10505                return true;
10506            }
10507        }
10508
10509        if (((viewFlags & CLICKABLE) == CLICKABLE ||
10510                (viewFlags & LONG_CLICKABLE) == LONG_CLICKABLE) ||
10511                (viewFlags & CONTEXT_CLICKABLE) == CONTEXT_CLICKABLE) {
10512            switch (action) {
10513                case MotionEvent.ACTION_UP:
10514                    boolean prepressed = (mPrivateFlags & PFLAG_PREPRESSED) != 0;
10515                    if ((mPrivateFlags & PFLAG_PRESSED) != 0 || prepressed) {
10516                        // take focus if we don't have it already and we should in
10517                        // touch mode.
10518                        boolean focusTaken = false;
10519                        if (isFocusable() && isFocusableInTouchMode() && !isFocused()) {
10520                            focusTaken = requestFocus();
10521                        }
10522
10523                        if (prepressed) {
10524                            // The button is being released before we actually
10525                            // showed it as pressed.  Make it show the pressed
10526                            // state now (before scheduling the click) to ensure
10527                            // the user sees it.
10528                            setPressed(true, x, y);
10529                       }
10530
10531                        if (!mHasPerformedLongPress && !mIgnoreNextUpEvent) {
10532                            // This is a tap, so remove the longpress check
10533                            removeLongPressCallback();
10534
10535                            // Only perform take click actions if we were in the pressed state
10536                            if (!focusTaken) {
10537                                // Use a Runnable and post this rather than calling
10538                                // performClick directly. This lets other visual state
10539                                // of the view update before click actions start.
10540                                if (mPerformClick == null) {
10541                                    mPerformClick = new PerformClick();
10542                                }
10543                                if (!post(mPerformClick)) {
10544                                    performClick();
10545                                }
10546                            }
10547                        }
10548
10549                        if (mUnsetPressedState == null) {
10550                            mUnsetPressedState = new UnsetPressedState();
10551                        }
10552
10553                        if (prepressed) {
10554                            postDelayed(mUnsetPressedState,
10555                                    ViewConfiguration.getPressedStateDuration());
10556                        } else if (!post(mUnsetPressedState)) {
10557                            // If the post failed, unpress right now
10558                            mUnsetPressedState.run();
10559                        }
10560
10561                        removeTapCallback();
10562                    }
10563                    mIgnoreNextUpEvent = false;
10564                    break;
10565
10566                case MotionEvent.ACTION_DOWN:
10567                    mHasPerformedLongPress = false;
10568
10569                    if (performButtonActionOnTouchDown(event)) {
10570                        break;
10571                    }
10572
10573                    // Walk up the hierarchy to determine if we're inside a scrolling container.
10574                    boolean isInScrollingContainer = isInScrollingContainer();
10575
10576                    // For views inside a scrolling container, delay the pressed feedback for
10577                    // a short period in case this is a scroll.
10578                    if (isInScrollingContainer) {
10579                        mPrivateFlags |= PFLAG_PREPRESSED;
10580                        if (mPendingCheckForTap == null) {
10581                            mPendingCheckForTap = new CheckForTap();
10582                        }
10583                        mPendingCheckForTap.x = event.getX();
10584                        mPendingCheckForTap.y = event.getY();
10585                        postDelayed(mPendingCheckForTap, ViewConfiguration.getTapTimeout());
10586                    } else {
10587                        // Not inside a scrolling container, so show the feedback right away
10588                        setPressed(true, x, y);
10589                        checkForLongClick(0);
10590                    }
10591                    break;
10592
10593                case MotionEvent.ACTION_CANCEL:
10594                    setPressed(false);
10595                    removeTapCallback();
10596                    removeLongPressCallback();
10597                    mInContextButtonPress = false;
10598                    mHasPerformedLongPress = false;
10599                    mIgnoreNextUpEvent = false;
10600                    break;
10601
10602                case MotionEvent.ACTION_MOVE:
10603                    drawableHotspotChanged(x, y);
10604
10605                    // Be lenient about moving outside of buttons
10606                    if (!pointInView(x, y, mTouchSlop)) {
10607                        // Outside button
10608                        removeTapCallback();
10609                        if ((mPrivateFlags & PFLAG_PRESSED) != 0) {
10610                            // Remove any future long press/tap checks
10611                            removeLongPressCallback();
10612
10613                            setPressed(false);
10614                        }
10615                    }
10616                    break;
10617            }
10618
10619            return true;
10620        }
10621
10622        return false;
10623    }
10624
10625    /**
10626     * @hide
10627     */
10628    public boolean isInScrollingContainer() {
10629        ViewParent p = getParent();
10630        while (p != null && p instanceof ViewGroup) {
10631            if (((ViewGroup) p).shouldDelayChildPressedState()) {
10632                return true;
10633            }
10634            p = p.getParent();
10635        }
10636        return false;
10637    }
10638
10639    /**
10640     * Remove the longpress detection timer.
10641     */
10642    private void removeLongPressCallback() {
10643        if (mPendingCheckForLongPress != null) {
10644          removeCallbacks(mPendingCheckForLongPress);
10645        }
10646    }
10647
10648    /**
10649     * Remove the pending click action
10650     */
10651    private void removePerformClickCallback() {
10652        if (mPerformClick != null) {
10653            removeCallbacks(mPerformClick);
10654        }
10655    }
10656
10657    /**
10658     * Remove the prepress detection timer.
10659     */
10660    private void removeUnsetPressCallback() {
10661        if ((mPrivateFlags & PFLAG_PRESSED) != 0 && mUnsetPressedState != null) {
10662            setPressed(false);
10663            removeCallbacks(mUnsetPressedState);
10664        }
10665    }
10666
10667    /**
10668     * Remove the tap detection timer.
10669     */
10670    private void removeTapCallback() {
10671        if (mPendingCheckForTap != null) {
10672            mPrivateFlags &= ~PFLAG_PREPRESSED;
10673            removeCallbacks(mPendingCheckForTap);
10674        }
10675    }
10676
10677    /**
10678     * Cancels a pending long press.  Your subclass can use this if you
10679     * want the context menu to come up if the user presses and holds
10680     * at the same place, but you don't want it to come up if they press
10681     * and then move around enough to cause scrolling.
10682     */
10683    public void cancelLongPress() {
10684        removeLongPressCallback();
10685
10686        /*
10687         * The prepressed state handled by the tap callback is a display
10688         * construct, but the tap callback will post a long press callback
10689         * less its own timeout. Remove it here.
10690         */
10691        removeTapCallback();
10692    }
10693
10694    /**
10695     * Remove the pending callback for sending a
10696     * {@link AccessibilityEvent#TYPE_VIEW_SCROLLED} accessibility event.
10697     */
10698    private void removeSendViewScrolledAccessibilityEventCallback() {
10699        if (mSendViewScrolledAccessibilityEvent != null) {
10700            removeCallbacks(mSendViewScrolledAccessibilityEvent);
10701            mSendViewScrolledAccessibilityEvent.mIsPending = false;
10702        }
10703    }
10704
10705    /**
10706     * Sets the TouchDelegate for this View.
10707     */
10708    public void setTouchDelegate(TouchDelegate delegate) {
10709        mTouchDelegate = delegate;
10710    }
10711
10712    /**
10713     * Gets the TouchDelegate for this View.
10714     */
10715    public TouchDelegate getTouchDelegate() {
10716        return mTouchDelegate;
10717    }
10718
10719    /**
10720     * Request unbuffered dispatch of the given stream of MotionEvents to this View.
10721     *
10722     * Until this View receives a corresponding {@link MotionEvent#ACTION_UP}, ask that the input
10723     * system not batch {@link MotionEvent}s but instead deliver them as soon as they're
10724     * available. This method should only be called for touch events.
10725     *
10726     * <p class="note">This api is not intended for most applications. Buffered dispatch
10727     * provides many of benefits, and just requesting unbuffered dispatch on most MotionEvent
10728     * streams will not improve your input latency. Side effects include: increased latency,
10729     * jittery scrolls and inability to take advantage of system resampling. Talk to your input
10730     * professional to see if {@link #requestUnbufferedDispatch(MotionEvent)} is right for
10731     * you.</p>
10732     */
10733    public final void requestUnbufferedDispatch(MotionEvent event) {
10734        final int action = event.getAction();
10735        if (mAttachInfo == null
10736                || action != MotionEvent.ACTION_DOWN && action != MotionEvent.ACTION_MOVE
10737                || !event.isTouchEvent()) {
10738            return;
10739        }
10740        mAttachInfo.mUnbufferedDispatchRequested = true;
10741    }
10742
10743    /**
10744     * Set flags controlling behavior of this view.
10745     *
10746     * @param flags Constant indicating the value which should be set
10747     * @param mask Constant indicating the bit range that should be changed
10748     */
10749    void setFlags(int flags, int mask) {
10750        final boolean accessibilityEnabled =
10751                AccessibilityManager.getInstance(mContext).isEnabled();
10752        final boolean oldIncludeForAccessibility = accessibilityEnabled && includeForAccessibility();
10753
10754        int old = mViewFlags;
10755        mViewFlags = (mViewFlags & ~mask) | (flags & mask);
10756
10757        int changed = mViewFlags ^ old;
10758        if (changed == 0) {
10759            return;
10760        }
10761        int privateFlags = mPrivateFlags;
10762
10763        /* Check if the FOCUSABLE bit has changed */
10764        if (((changed & FOCUSABLE_MASK) != 0) &&
10765                ((privateFlags & PFLAG_HAS_BOUNDS) !=0)) {
10766            if (((old & FOCUSABLE_MASK) == FOCUSABLE)
10767                    && ((privateFlags & PFLAG_FOCUSED) != 0)) {
10768                /* Give up focus if we are no longer focusable */
10769                clearFocus();
10770            } else if (((old & FOCUSABLE_MASK) == NOT_FOCUSABLE)
10771                    && ((privateFlags & PFLAG_FOCUSED) == 0)) {
10772                /*
10773                 * Tell the view system that we are now available to take focus
10774                 * if no one else already has it.
10775                 */
10776                if (mParent != null) mParent.focusableViewAvailable(this);
10777            }
10778        }
10779
10780        final int newVisibility = flags & VISIBILITY_MASK;
10781        if (newVisibility == VISIBLE) {
10782            if ((changed & VISIBILITY_MASK) != 0) {
10783                /*
10784                 * If this view is becoming visible, invalidate it in case it changed while
10785                 * it was not visible. Marking it drawn ensures that the invalidation will
10786                 * go through.
10787                 */
10788                mPrivateFlags |= PFLAG_DRAWN;
10789                invalidate(true);
10790
10791                needGlobalAttributesUpdate(true);
10792
10793                // a view becoming visible is worth notifying the parent
10794                // about in case nothing has focus.  even if this specific view
10795                // isn't focusable, it may contain something that is, so let
10796                // the root view try to give this focus if nothing else does.
10797                if ((mParent != null) && (mBottom > mTop) && (mRight > mLeft)) {
10798                    mParent.focusableViewAvailable(this);
10799                }
10800            }
10801        }
10802
10803        /* Check if the GONE bit has changed */
10804        if ((changed & GONE) != 0) {
10805            needGlobalAttributesUpdate(false);
10806            requestLayout();
10807
10808            if (((mViewFlags & VISIBILITY_MASK) == GONE)) {
10809                if (hasFocus()) clearFocus();
10810                clearAccessibilityFocus();
10811                destroyDrawingCache();
10812                if (mParent instanceof View) {
10813                    // GONE views noop invalidation, so invalidate the parent
10814                    ((View) mParent).invalidate(true);
10815                }
10816                // Mark the view drawn to ensure that it gets invalidated properly the next
10817                // time it is visible and gets invalidated
10818                mPrivateFlags |= PFLAG_DRAWN;
10819            }
10820            if (mAttachInfo != null) {
10821                mAttachInfo.mViewVisibilityChanged = true;
10822            }
10823        }
10824
10825        /* Check if the VISIBLE bit has changed */
10826        if ((changed & INVISIBLE) != 0) {
10827            needGlobalAttributesUpdate(false);
10828            /*
10829             * If this view is becoming invisible, set the DRAWN flag so that
10830             * the next invalidate() will not be skipped.
10831             */
10832            mPrivateFlags |= PFLAG_DRAWN;
10833
10834            if (((mViewFlags & VISIBILITY_MASK) == INVISIBLE)) {
10835                // root view becoming invisible shouldn't clear focus and accessibility focus
10836                if (getRootView() != this) {
10837                    if (hasFocus()) clearFocus();
10838                    clearAccessibilityFocus();
10839                }
10840            }
10841            if (mAttachInfo != null) {
10842                mAttachInfo.mViewVisibilityChanged = true;
10843            }
10844        }
10845
10846        if ((changed & VISIBILITY_MASK) != 0) {
10847            // If the view is invisible, cleanup its display list to free up resources
10848            if (newVisibility != VISIBLE && mAttachInfo != null) {
10849                cleanupDraw();
10850            }
10851
10852            if (mParent instanceof ViewGroup) {
10853                ((ViewGroup) mParent).onChildVisibilityChanged(this,
10854                        (changed & VISIBILITY_MASK), newVisibility);
10855                ((View) mParent).invalidate(true);
10856            } else if (mParent != null) {
10857                mParent.invalidateChild(this, null);
10858            }
10859
10860            if (mAttachInfo != null) {
10861                dispatchVisibilityChanged(this, newVisibility);
10862                notifySubtreeAccessibilityStateChangedIfNeeded();
10863            }
10864        }
10865
10866        if ((changed & WILL_NOT_CACHE_DRAWING) != 0) {
10867            destroyDrawingCache();
10868        }
10869
10870        if ((changed & DRAWING_CACHE_ENABLED) != 0) {
10871            destroyDrawingCache();
10872            mPrivateFlags &= ~PFLAG_DRAWING_CACHE_VALID;
10873            invalidateParentCaches();
10874        }
10875
10876        if ((changed & DRAWING_CACHE_QUALITY_MASK) != 0) {
10877            destroyDrawingCache();
10878            mPrivateFlags &= ~PFLAG_DRAWING_CACHE_VALID;
10879        }
10880
10881        if ((changed & DRAW_MASK) != 0) {
10882            if ((mViewFlags & WILL_NOT_DRAW) != 0) {
10883                if (mBackground != null
10884                        || (mForegroundInfo != null && mForegroundInfo.mDrawable != null)) {
10885                    mPrivateFlags &= ~PFLAG_SKIP_DRAW;
10886                } else {
10887                    mPrivateFlags |= PFLAG_SKIP_DRAW;
10888                }
10889            } else {
10890                mPrivateFlags &= ~PFLAG_SKIP_DRAW;
10891            }
10892            requestLayout();
10893            invalidate(true);
10894        }
10895
10896        if ((changed & KEEP_SCREEN_ON) != 0) {
10897            if (mParent != null && mAttachInfo != null && !mAttachInfo.mRecomputeGlobalAttributes) {
10898                mParent.recomputeViewAttributes(this);
10899            }
10900        }
10901
10902        if (accessibilityEnabled) {
10903            if ((changed & FOCUSABLE_MASK) != 0 || (changed & VISIBILITY_MASK) != 0
10904                    || (changed & CLICKABLE) != 0 || (changed & LONG_CLICKABLE) != 0
10905                    || (changed & CONTEXT_CLICKABLE) != 0) {
10906                if (oldIncludeForAccessibility != includeForAccessibility()) {
10907                    notifySubtreeAccessibilityStateChangedIfNeeded();
10908                } else {
10909                    notifyViewAccessibilityStateChangedIfNeeded(
10910                            AccessibilityEvent.CONTENT_CHANGE_TYPE_UNDEFINED);
10911                }
10912            } else if ((changed & ENABLED_MASK) != 0) {
10913                notifyViewAccessibilityStateChangedIfNeeded(
10914                        AccessibilityEvent.CONTENT_CHANGE_TYPE_UNDEFINED);
10915            }
10916        }
10917    }
10918
10919    /**
10920     * Change the view's z order in the tree, so it's on top of other sibling
10921     * views. This ordering change may affect layout, if the parent container
10922     * uses an order-dependent layout scheme (e.g., LinearLayout). Prior
10923     * to {@link android.os.Build.VERSION_CODES#KITKAT} this
10924     * method should be followed by calls to {@link #requestLayout()} and
10925     * {@link View#invalidate()} on the view's parent to force the parent to redraw
10926     * with the new child ordering.
10927     *
10928     * @see ViewGroup#bringChildToFront(View)
10929     */
10930    public void bringToFront() {
10931        if (mParent != null) {
10932            mParent.bringChildToFront(this);
10933        }
10934    }
10935
10936    /**
10937     * This is called in response to an internal scroll in this view (i.e., the
10938     * view scrolled its own contents). This is typically as a result of
10939     * {@link #scrollBy(int, int)} or {@link #scrollTo(int, int)} having been
10940     * called.
10941     *
10942     * @param l Current horizontal scroll origin.
10943     * @param t Current vertical scroll origin.
10944     * @param oldl Previous horizontal scroll origin.
10945     * @param oldt Previous vertical scroll origin.
10946     */
10947    protected void onScrollChanged(int l, int t, int oldl, int oldt) {
10948        notifySubtreeAccessibilityStateChangedIfNeeded();
10949
10950        if (AccessibilityManager.getInstance(mContext).isEnabled()) {
10951            postSendViewScrolledAccessibilityEventCallback();
10952        }
10953
10954        mBackgroundSizeChanged = true;
10955        if (mForegroundInfo != null) {
10956            mForegroundInfo.mBoundsChanged = true;
10957        }
10958
10959        final AttachInfo ai = mAttachInfo;
10960        if (ai != null) {
10961            ai.mViewScrollChanged = true;
10962        }
10963
10964        if (mListenerInfo != null && mListenerInfo.mOnScrollChangeListener != null) {
10965            mListenerInfo.mOnScrollChangeListener.onScrollChange(this, l, t, oldl, oldt);
10966        }
10967    }
10968
10969    /**
10970     * Interface definition for a callback to be invoked when the scroll
10971     * X or Y positions of a view change.
10972     * <p>
10973     * <b>Note:</b> Some views handle scrolling independently from View and may
10974     * have their own separate listeners for scroll-type events. For example,
10975     * {@link android.widget.ListView ListView} allows clients to register an
10976     * {@link android.widget.ListView#setOnScrollListener(android.widget.AbsListView.OnScrollListener) AbsListView.OnScrollListener}
10977     * to listen for changes in list scroll position.
10978     *
10979     * @see #setOnScrollChangeListener(View.OnScrollChangeListener)
10980     */
10981    public interface OnScrollChangeListener {
10982        /**
10983         * Called when the scroll position of a view changes.
10984         *
10985         * @param v The view whose scroll position has changed.
10986         * @param scrollX Current horizontal scroll origin.
10987         * @param scrollY Current vertical scroll origin.
10988         * @param oldScrollX Previous horizontal scroll origin.
10989         * @param oldScrollY Previous vertical scroll origin.
10990         */
10991        void onScrollChange(View v, int scrollX, int scrollY, int oldScrollX, int oldScrollY);
10992    }
10993
10994    /**
10995     * Interface definition for a callback to be invoked when the layout bounds of a view
10996     * changes due to layout processing.
10997     */
10998    public interface OnLayoutChangeListener {
10999        /**
11000         * Called when the layout bounds of a view changes due to layout processing.
11001         *
11002         * @param v The view whose bounds have changed.
11003         * @param left The new value of the view's left property.
11004         * @param top The new value of the view's top property.
11005         * @param right The new value of the view's right property.
11006         * @param bottom The new value of the view's bottom property.
11007         * @param oldLeft The previous value of the view's left property.
11008         * @param oldTop The previous value of the view's top property.
11009         * @param oldRight The previous value of the view's right property.
11010         * @param oldBottom The previous value of the view's bottom property.
11011         */
11012        void onLayoutChange(View v, int left, int top, int right, int bottom,
11013            int oldLeft, int oldTop, int oldRight, int oldBottom);
11014    }
11015
11016    /**
11017     * This is called during layout when the size of this view has changed. If
11018     * you were just added to the view hierarchy, you're called with the old
11019     * values of 0.
11020     *
11021     * @param w Current width of this view.
11022     * @param h Current height of this view.
11023     * @param oldw Old width of this view.
11024     * @param oldh Old height of this view.
11025     */
11026    protected void onSizeChanged(int w, int h, int oldw, int oldh) {
11027    }
11028
11029    /**
11030     * Called by draw to draw the child views. This may be overridden
11031     * by derived classes to gain control just before its children are drawn
11032     * (but after its own view has been drawn).
11033     * @param canvas the canvas on which to draw the view
11034     */
11035    protected void dispatchDraw(Canvas canvas) {
11036
11037    }
11038
11039    /**
11040     * Gets the parent of this view. Note that the parent is a
11041     * ViewParent and not necessarily a View.
11042     *
11043     * @return Parent of this view.
11044     */
11045    public final ViewParent getParent() {
11046        return mParent;
11047    }
11048
11049    /**
11050     * Set the horizontal scrolled position of your view. This will cause a call to
11051     * {@link #onScrollChanged(int, int, int, int)} and the view will be
11052     * invalidated.
11053     * @param value the x position to scroll to
11054     */
11055    public void setScrollX(int value) {
11056        scrollTo(value, mScrollY);
11057    }
11058
11059    /**
11060     * Set the vertical scrolled position of your view. This will cause a call to
11061     * {@link #onScrollChanged(int, int, int, int)} and the view will be
11062     * invalidated.
11063     * @param value the y position to scroll to
11064     */
11065    public void setScrollY(int value) {
11066        scrollTo(mScrollX, value);
11067    }
11068
11069    /**
11070     * Return the scrolled left position of this view. This is the left edge of
11071     * the displayed part of your view. You do not need to draw any pixels
11072     * farther left, since those are outside of the frame of your view on
11073     * screen.
11074     *
11075     * @return The left edge of the displayed part of your view, in pixels.
11076     */
11077    public final int getScrollX() {
11078        return mScrollX;
11079    }
11080
11081    /**
11082     * Return the scrolled top position of this view. This is the top edge of
11083     * the displayed part of your view. You do not need to draw any pixels above
11084     * it, since those are outside of the frame of your view on screen.
11085     *
11086     * @return The top edge of the displayed part of your view, in pixels.
11087     */
11088    public final int getScrollY() {
11089        return mScrollY;
11090    }
11091
11092    /**
11093     * Return the width of the your view.
11094     *
11095     * @return The width of your view, in pixels.
11096     */
11097    @ViewDebug.ExportedProperty(category = "layout")
11098    public final int getWidth() {
11099        return mRight - mLeft;
11100    }
11101
11102    /**
11103     * Return the height of your view.
11104     *
11105     * @return The height of your view, in pixels.
11106     */
11107    @ViewDebug.ExportedProperty(category = "layout")
11108    public final int getHeight() {
11109        return mBottom - mTop;
11110    }
11111
11112    /**
11113     * Return the visible drawing bounds of your view. Fills in the output
11114     * rectangle with the values from getScrollX(), getScrollY(),
11115     * getWidth(), and getHeight(). These bounds do not account for any
11116     * transformation properties currently set on the view, such as
11117     * {@link #setScaleX(float)} or {@link #setRotation(float)}.
11118     *
11119     * @param outRect The (scrolled) drawing bounds of the view.
11120     */
11121    public void getDrawingRect(Rect outRect) {
11122        outRect.left = mScrollX;
11123        outRect.top = mScrollY;
11124        outRect.right = mScrollX + (mRight - mLeft);
11125        outRect.bottom = mScrollY + (mBottom - mTop);
11126    }
11127
11128    /**
11129     * Like {@link #getMeasuredWidthAndState()}, but only returns the
11130     * raw width component (that is the result is masked by
11131     * {@link #MEASURED_SIZE_MASK}).
11132     *
11133     * @return The raw measured width of this view.
11134     */
11135    public final int getMeasuredWidth() {
11136        return mMeasuredWidth & MEASURED_SIZE_MASK;
11137    }
11138
11139    /**
11140     * Return the full width measurement information for this view as computed
11141     * by the most recent call to {@link #measure(int, int)}.  This result is a bit mask
11142     * as defined by {@link #MEASURED_SIZE_MASK} and {@link #MEASURED_STATE_TOO_SMALL}.
11143     * This should be used during measurement and layout calculations only. Use
11144     * {@link #getWidth()} to see how wide a view is after layout.
11145     *
11146     * @return The measured width of this view as a bit mask.
11147     */
11148    @ViewDebug.ExportedProperty(category = "measurement", flagMapping = {
11149            @ViewDebug.FlagToString(mask = MEASURED_STATE_MASK, equals = MEASURED_STATE_TOO_SMALL,
11150                    name = "MEASURED_STATE_TOO_SMALL"),
11151    })
11152    public final int getMeasuredWidthAndState() {
11153        return mMeasuredWidth;
11154    }
11155
11156    /**
11157     * Like {@link #getMeasuredHeightAndState()}, but only returns the
11158     * raw width component (that is the result is masked by
11159     * {@link #MEASURED_SIZE_MASK}).
11160     *
11161     * @return The raw measured height of this view.
11162     */
11163    public final int getMeasuredHeight() {
11164        return mMeasuredHeight & MEASURED_SIZE_MASK;
11165    }
11166
11167    /**
11168     * Return the full height measurement information for this view as computed
11169     * by the most recent call to {@link #measure(int, int)}.  This result is a bit mask
11170     * as defined by {@link #MEASURED_SIZE_MASK} and {@link #MEASURED_STATE_TOO_SMALL}.
11171     * This should be used during measurement and layout calculations only. Use
11172     * {@link #getHeight()} to see how wide a view is after layout.
11173     *
11174     * @return The measured width of this view as a bit mask.
11175     */
11176    @ViewDebug.ExportedProperty(category = "measurement", flagMapping = {
11177            @ViewDebug.FlagToString(mask = MEASURED_STATE_MASK, equals = MEASURED_STATE_TOO_SMALL,
11178                    name = "MEASURED_STATE_TOO_SMALL"),
11179    })
11180    public final int getMeasuredHeightAndState() {
11181        return mMeasuredHeight;
11182    }
11183
11184    /**
11185     * Return only the state bits of {@link #getMeasuredWidthAndState()}
11186     * and {@link #getMeasuredHeightAndState()}, combined into one integer.
11187     * The width component is in the regular bits {@link #MEASURED_STATE_MASK}
11188     * and the height component is at the shifted bits
11189     * {@link #MEASURED_HEIGHT_STATE_SHIFT}>>{@link #MEASURED_STATE_MASK}.
11190     */
11191    public final int getMeasuredState() {
11192        return (mMeasuredWidth&MEASURED_STATE_MASK)
11193                | ((mMeasuredHeight>>MEASURED_HEIGHT_STATE_SHIFT)
11194                        & (MEASURED_STATE_MASK>>MEASURED_HEIGHT_STATE_SHIFT));
11195    }
11196
11197    /**
11198     * The transform matrix of this view, which is calculated based on the current
11199     * rotation, scale, and pivot properties.
11200     *
11201     * @see #getRotation()
11202     * @see #getScaleX()
11203     * @see #getScaleY()
11204     * @see #getPivotX()
11205     * @see #getPivotY()
11206     * @return The current transform matrix for the view
11207     */
11208    public Matrix getMatrix() {
11209        ensureTransformationInfo();
11210        final Matrix matrix = mTransformationInfo.mMatrix;
11211        mRenderNode.getMatrix(matrix);
11212        return matrix;
11213    }
11214
11215    /**
11216     * Returns true if the transform matrix is the identity matrix.
11217     * Recomputes the matrix if necessary.
11218     *
11219     * @return True if the transform matrix is the identity matrix, false otherwise.
11220     */
11221    final boolean hasIdentityMatrix() {
11222        return mRenderNode.hasIdentityMatrix();
11223    }
11224
11225    void ensureTransformationInfo() {
11226        if (mTransformationInfo == null) {
11227            mTransformationInfo = new TransformationInfo();
11228        }
11229    }
11230
11231   /**
11232     * Utility method to retrieve the inverse of the current mMatrix property.
11233     * We cache the matrix to avoid recalculating it when transform properties
11234     * have not changed.
11235     *
11236     * @return The inverse of the current matrix of this view.
11237     * @hide
11238     */
11239    public final Matrix getInverseMatrix() {
11240        ensureTransformationInfo();
11241        if (mTransformationInfo.mInverseMatrix == null) {
11242            mTransformationInfo.mInverseMatrix = new Matrix();
11243        }
11244        final Matrix matrix = mTransformationInfo.mInverseMatrix;
11245        mRenderNode.getInverseMatrix(matrix);
11246        return matrix;
11247    }
11248
11249    /**
11250     * Gets the distance along the Z axis from the camera to this view.
11251     *
11252     * @see #setCameraDistance(float)
11253     *
11254     * @return The distance along the Z axis.
11255     */
11256    public float getCameraDistance() {
11257        final float dpi = mResources.getDisplayMetrics().densityDpi;
11258        return -(mRenderNode.getCameraDistance() * dpi);
11259    }
11260
11261    /**
11262     * <p>Sets the distance along the Z axis (orthogonal to the X/Y plane on which
11263     * views are drawn) from the camera to this view. The camera's distance
11264     * affects 3D transformations, for instance rotations around the X and Y
11265     * axis. If the rotationX or rotationY properties are changed and this view is
11266     * large (more than half the size of the screen), it is recommended to always
11267     * use a camera distance that's greater than the height (X axis rotation) or
11268     * the width (Y axis rotation) of this view.</p>
11269     *
11270     * <p>The distance of the camera from the view plane can have an affect on the
11271     * perspective distortion of the view when it is rotated around the x or y axis.
11272     * For example, a large distance will result in a large viewing angle, and there
11273     * will not be much perspective distortion of the view as it rotates. A short
11274     * distance may cause much more perspective distortion upon rotation, and can
11275     * also result in some drawing artifacts if the rotated view ends up partially
11276     * behind the camera (which is why the recommendation is to use a distance at
11277     * least as far as the size of the view, if the view is to be rotated.)</p>
11278     *
11279     * <p>The distance is expressed in "depth pixels." The default distance depends
11280     * on the screen density. For instance, on a medium density display, the
11281     * default distance is 1280. On a high density display, the default distance
11282     * is 1920.</p>
11283     *
11284     * <p>If you want to specify a distance that leads to visually consistent
11285     * results across various densities, use the following formula:</p>
11286     * <pre>
11287     * float scale = context.getResources().getDisplayMetrics().density;
11288     * view.setCameraDistance(distance * scale);
11289     * </pre>
11290     *
11291     * <p>The density scale factor of a high density display is 1.5,
11292     * and 1920 = 1280 * 1.5.</p>
11293     *
11294     * @param distance The distance in "depth pixels", if negative the opposite
11295     *        value is used
11296     *
11297     * @see #setRotationX(float)
11298     * @see #setRotationY(float)
11299     */
11300    public void setCameraDistance(float distance) {
11301        final float dpi = mResources.getDisplayMetrics().densityDpi;
11302
11303        invalidateViewProperty(true, false);
11304        mRenderNode.setCameraDistance(-Math.abs(distance) / dpi);
11305        invalidateViewProperty(false, false);
11306
11307        invalidateParentIfNeededAndWasQuickRejected();
11308    }
11309
11310    /**
11311     * The degrees that the view is rotated around the pivot point.
11312     *
11313     * @see #setRotation(float)
11314     * @see #getPivotX()
11315     * @see #getPivotY()
11316     *
11317     * @return The degrees of rotation.
11318     */
11319    @ViewDebug.ExportedProperty(category = "drawing")
11320    public float getRotation() {
11321        return mRenderNode.getRotation();
11322    }
11323
11324    /**
11325     * Sets the degrees that the view is rotated around the pivot point. Increasing values
11326     * result in clockwise rotation.
11327     *
11328     * @param rotation The degrees of rotation.
11329     *
11330     * @see #getRotation()
11331     * @see #getPivotX()
11332     * @see #getPivotY()
11333     * @see #setRotationX(float)
11334     * @see #setRotationY(float)
11335     *
11336     * @attr ref android.R.styleable#View_rotation
11337     */
11338    public void setRotation(float rotation) {
11339        if (rotation != getRotation()) {
11340            // Double-invalidation is necessary to capture view's old and new areas
11341            invalidateViewProperty(true, false);
11342            mRenderNode.setRotation(rotation);
11343            invalidateViewProperty(false, true);
11344
11345            invalidateParentIfNeededAndWasQuickRejected();
11346            notifySubtreeAccessibilityStateChangedIfNeeded();
11347        }
11348    }
11349
11350    /**
11351     * The degrees that the view is rotated around the vertical axis through the pivot point.
11352     *
11353     * @see #getPivotX()
11354     * @see #getPivotY()
11355     * @see #setRotationY(float)
11356     *
11357     * @return The degrees of Y rotation.
11358     */
11359    @ViewDebug.ExportedProperty(category = "drawing")
11360    public float getRotationY() {
11361        return mRenderNode.getRotationY();
11362    }
11363
11364    /**
11365     * Sets the degrees that the view is rotated around the vertical axis through the pivot point.
11366     * Increasing values result in counter-clockwise rotation from the viewpoint of looking
11367     * down the y axis.
11368     *
11369     * When rotating large views, it is recommended to adjust the camera distance
11370     * accordingly. Refer to {@link #setCameraDistance(float)} for more information.
11371     *
11372     * @param rotationY The degrees of Y rotation.
11373     *
11374     * @see #getRotationY()
11375     * @see #getPivotX()
11376     * @see #getPivotY()
11377     * @see #setRotation(float)
11378     * @see #setRotationX(float)
11379     * @see #setCameraDistance(float)
11380     *
11381     * @attr ref android.R.styleable#View_rotationY
11382     */
11383    public void setRotationY(float rotationY) {
11384        if (rotationY != getRotationY()) {
11385            invalidateViewProperty(true, false);
11386            mRenderNode.setRotationY(rotationY);
11387            invalidateViewProperty(false, true);
11388
11389            invalidateParentIfNeededAndWasQuickRejected();
11390            notifySubtreeAccessibilityStateChangedIfNeeded();
11391        }
11392    }
11393
11394    /**
11395     * The degrees that the view is rotated around the horizontal axis through the pivot point.
11396     *
11397     * @see #getPivotX()
11398     * @see #getPivotY()
11399     * @see #setRotationX(float)
11400     *
11401     * @return The degrees of X rotation.
11402     */
11403    @ViewDebug.ExportedProperty(category = "drawing")
11404    public float getRotationX() {
11405        return mRenderNode.getRotationX();
11406    }
11407
11408    /**
11409     * Sets the degrees that the view is rotated around the horizontal axis through the pivot point.
11410     * Increasing values result in clockwise rotation from the viewpoint of looking down the
11411     * x axis.
11412     *
11413     * When rotating large views, it is recommended to adjust the camera distance
11414     * accordingly. Refer to {@link #setCameraDistance(float)} for more information.
11415     *
11416     * @param rotationX The degrees of X rotation.
11417     *
11418     * @see #getRotationX()
11419     * @see #getPivotX()
11420     * @see #getPivotY()
11421     * @see #setRotation(float)
11422     * @see #setRotationY(float)
11423     * @see #setCameraDistance(float)
11424     *
11425     * @attr ref android.R.styleable#View_rotationX
11426     */
11427    public void setRotationX(float rotationX) {
11428        if (rotationX != getRotationX()) {
11429            invalidateViewProperty(true, false);
11430            mRenderNode.setRotationX(rotationX);
11431            invalidateViewProperty(false, true);
11432
11433            invalidateParentIfNeededAndWasQuickRejected();
11434            notifySubtreeAccessibilityStateChangedIfNeeded();
11435        }
11436    }
11437
11438    /**
11439     * The amount that the view is scaled in x around the pivot point, as a proportion of
11440     * the view's unscaled width. A value of 1, the default, means that no scaling is applied.
11441     *
11442     * <p>By default, this is 1.0f.
11443     *
11444     * @see #getPivotX()
11445     * @see #getPivotY()
11446     * @return The scaling factor.
11447     */
11448    @ViewDebug.ExportedProperty(category = "drawing")
11449    public float getScaleX() {
11450        return mRenderNode.getScaleX();
11451    }
11452
11453    /**
11454     * Sets the amount that the view is scaled in x around the pivot point, as a proportion of
11455     * the view's unscaled width. A value of 1 means that no scaling is applied.
11456     *
11457     * @param scaleX The scaling factor.
11458     * @see #getPivotX()
11459     * @see #getPivotY()
11460     *
11461     * @attr ref android.R.styleable#View_scaleX
11462     */
11463    public void setScaleX(float scaleX) {
11464        if (scaleX != getScaleX()) {
11465            invalidateViewProperty(true, false);
11466            mRenderNode.setScaleX(scaleX);
11467            invalidateViewProperty(false, true);
11468
11469            invalidateParentIfNeededAndWasQuickRejected();
11470            notifySubtreeAccessibilityStateChangedIfNeeded();
11471        }
11472    }
11473
11474    /**
11475     * The amount that the view is scaled in y around the pivot point, as a proportion of
11476     * the view's unscaled height. A value of 1, the default, means that no scaling is applied.
11477     *
11478     * <p>By default, this is 1.0f.
11479     *
11480     * @see #getPivotX()
11481     * @see #getPivotY()
11482     * @return The scaling factor.
11483     */
11484    @ViewDebug.ExportedProperty(category = "drawing")
11485    public float getScaleY() {
11486        return mRenderNode.getScaleY();
11487    }
11488
11489    /**
11490     * Sets the amount that the view is scaled in Y around the pivot point, as a proportion of
11491     * the view's unscaled width. A value of 1 means that no scaling is applied.
11492     *
11493     * @param scaleY The scaling factor.
11494     * @see #getPivotX()
11495     * @see #getPivotY()
11496     *
11497     * @attr ref android.R.styleable#View_scaleY
11498     */
11499    public void setScaleY(float scaleY) {
11500        if (scaleY != getScaleY()) {
11501            invalidateViewProperty(true, false);
11502            mRenderNode.setScaleY(scaleY);
11503            invalidateViewProperty(false, true);
11504
11505            invalidateParentIfNeededAndWasQuickRejected();
11506            notifySubtreeAccessibilityStateChangedIfNeeded();
11507        }
11508    }
11509
11510    /**
11511     * The x location of the point around which the view is {@link #setRotation(float) rotated}
11512     * and {@link #setScaleX(float) scaled}.
11513     *
11514     * @see #getRotation()
11515     * @see #getScaleX()
11516     * @see #getScaleY()
11517     * @see #getPivotY()
11518     * @return The x location of the pivot point.
11519     *
11520     * @attr ref android.R.styleable#View_transformPivotX
11521     */
11522    @ViewDebug.ExportedProperty(category = "drawing")
11523    public float getPivotX() {
11524        return mRenderNode.getPivotX();
11525    }
11526
11527    /**
11528     * Sets the x location of the point around which the view is
11529     * {@link #setRotation(float) rotated} and {@link #setScaleX(float) scaled}.
11530     * By default, the pivot point is centered on the object.
11531     * Setting this property disables this behavior and causes the view to use only the
11532     * explicitly set pivotX and pivotY values.
11533     *
11534     * @param pivotX The x location of the pivot point.
11535     * @see #getRotation()
11536     * @see #getScaleX()
11537     * @see #getScaleY()
11538     * @see #getPivotY()
11539     *
11540     * @attr ref android.R.styleable#View_transformPivotX
11541     */
11542    public void setPivotX(float pivotX) {
11543        if (!mRenderNode.isPivotExplicitlySet() || pivotX != getPivotX()) {
11544            invalidateViewProperty(true, false);
11545            mRenderNode.setPivotX(pivotX);
11546            invalidateViewProperty(false, true);
11547
11548            invalidateParentIfNeededAndWasQuickRejected();
11549        }
11550    }
11551
11552    /**
11553     * The y location of the point around which the view is {@link #setRotation(float) rotated}
11554     * and {@link #setScaleY(float) scaled}.
11555     *
11556     * @see #getRotation()
11557     * @see #getScaleX()
11558     * @see #getScaleY()
11559     * @see #getPivotY()
11560     * @return The y location of the pivot point.
11561     *
11562     * @attr ref android.R.styleable#View_transformPivotY
11563     */
11564    @ViewDebug.ExportedProperty(category = "drawing")
11565    public float getPivotY() {
11566        return mRenderNode.getPivotY();
11567    }
11568
11569    /**
11570     * Sets the y location of the point around which the view is {@link #setRotation(float) rotated}
11571     * and {@link #setScaleY(float) scaled}. By default, the pivot point is centered on the object.
11572     * Setting this property disables this behavior and causes the view to use only the
11573     * explicitly set pivotX and pivotY values.
11574     *
11575     * @param pivotY The y location of the pivot point.
11576     * @see #getRotation()
11577     * @see #getScaleX()
11578     * @see #getScaleY()
11579     * @see #getPivotY()
11580     *
11581     * @attr ref android.R.styleable#View_transformPivotY
11582     */
11583    public void setPivotY(float pivotY) {
11584        if (!mRenderNode.isPivotExplicitlySet() || pivotY != getPivotY()) {
11585            invalidateViewProperty(true, false);
11586            mRenderNode.setPivotY(pivotY);
11587            invalidateViewProperty(false, true);
11588
11589            invalidateParentIfNeededAndWasQuickRejected();
11590        }
11591    }
11592
11593    /**
11594     * The opacity of the view. This is a value from 0 to 1, where 0 means the view is
11595     * completely transparent and 1 means the view is completely opaque.
11596     *
11597     * <p>By default this is 1.0f.
11598     * @return The opacity of the view.
11599     */
11600    @ViewDebug.ExportedProperty(category = "drawing")
11601    public float getAlpha() {
11602        return mTransformationInfo != null ? mTransformationInfo.mAlpha : 1;
11603    }
11604
11605    /**
11606     * Returns whether this View has content which overlaps.
11607     *
11608     * <p>This function, intended to be overridden by specific View types, is an optimization when
11609     * alpha is set on a view. If rendering overlaps in a view with alpha < 1, that view is drawn to
11610     * an offscreen buffer and then composited into place, which can be expensive. If the view has
11611     * no overlapping rendering, the view can draw each primitive with the appropriate alpha value
11612     * directly. An example of overlapping rendering is a TextView with a background image, such as
11613     * a Button. An example of non-overlapping rendering is a TextView with no background, or an
11614     * ImageView with only the foreground image. The default implementation returns true; subclasses
11615     * should override if they have cases which can be optimized.</p>
11616     *
11617     * <p>The current implementation of the saveLayer and saveLayerAlpha methods in {@link Canvas}
11618     * necessitates that a View return true if it uses the methods internally without passing the
11619     * {@link Canvas#CLIP_TO_LAYER_SAVE_FLAG}.</p>
11620     *
11621     * @return true if the content in this view might overlap, false otherwise.
11622     */
11623    @ViewDebug.ExportedProperty(category = "drawing")
11624    public boolean hasOverlappingRendering() {
11625        return true;
11626    }
11627
11628    /**
11629     * Sets the opacity of the view to a value from 0 to 1, where 0 means the view is
11630     * completely transparent and 1 means the view is completely opaque.
11631     *
11632     * <p class="note"><strong>Note:</strong> setting alpha to a translucent value (0 < alpha < 1)
11633     * can have significant performance implications, especially for large views. It is best to use
11634     * the alpha property sparingly and transiently, as in the case of fading animations.</p>
11635     *
11636     * <p>For a view with a frequently changing alpha, such as during a fading animation, it is
11637     * strongly recommended for performance reasons to either override
11638     * {@link #hasOverlappingRendering()} to return <code>false</code> if appropriate, or setting a
11639     * {@link #setLayerType(int, android.graphics.Paint) layer type} on the view for the duration
11640     * of the animation. On versions {@link android.os.Build.VERSION_CODES#M} and below,
11641     * the default path for rendering an unlayered View with alpha could add multiple milliseconds
11642     * of rendering cost, even for simple or small views. Starting with
11643     * {@link android.os.Build.VERSION_CODES#M}, {@link #LAYER_TYPE_HARDWARE} is automatically
11644     * applied to the view at the rendering level.</p>
11645     *
11646     * <p>If this view overrides {@link #onSetAlpha(int)} to return true, then this view is
11647     * responsible for applying the opacity itself.</p>
11648     *
11649     * <p>On versions {@link android.os.Build.VERSION_CODES#LOLLIPOP_MR1} and below, note that if
11650     * the view is backed by a {@link #setLayerType(int, android.graphics.Paint) layer} and is
11651     * associated with a {@link #setLayerPaint(android.graphics.Paint) layer paint}, setting an
11652     * alpha value less than 1.0 will supersede the alpha of the layer paint.</p>
11653     *
11654     * <p>Starting with {@link android.os.Build.VERSION_CODES#M}, setting a translucent alpha
11655     * value will clip a View to its bounds, unless the View returns <code>false</code> from
11656     * {@link #hasOverlappingRendering}.</p>
11657     *
11658     * @param alpha The opacity of the view.
11659     *
11660     * @see #hasOverlappingRendering()
11661     * @see #setLayerType(int, android.graphics.Paint)
11662     *
11663     * @attr ref android.R.styleable#View_alpha
11664     */
11665    public void setAlpha(@FloatRange(from=0.0, to=1.0) float alpha) {
11666        ensureTransformationInfo();
11667        if (mTransformationInfo.mAlpha != alpha) {
11668            mTransformationInfo.mAlpha = alpha;
11669            if (onSetAlpha((int) (alpha * 255))) {
11670                mPrivateFlags |= PFLAG_ALPHA_SET;
11671                // subclass is handling alpha - don't optimize rendering cache invalidation
11672                invalidateParentCaches();
11673                invalidate(true);
11674            } else {
11675                mPrivateFlags &= ~PFLAG_ALPHA_SET;
11676                invalidateViewProperty(true, false);
11677                mRenderNode.setAlpha(getFinalAlpha());
11678                notifyViewAccessibilityStateChangedIfNeeded(
11679                        AccessibilityEvent.CONTENT_CHANGE_TYPE_UNDEFINED);
11680            }
11681        }
11682    }
11683
11684    /**
11685     * Faster version of setAlpha() which performs the same steps except there are
11686     * no calls to invalidate(). The caller of this function should perform proper invalidation
11687     * on the parent and this object. The return value indicates whether the subclass handles
11688     * alpha (the return value for onSetAlpha()).
11689     *
11690     * @param alpha The new value for the alpha property
11691     * @return true if the View subclass handles alpha (the return value for onSetAlpha()) and
11692     *         the new value for the alpha property is different from the old value
11693     */
11694    boolean setAlphaNoInvalidation(float alpha) {
11695        ensureTransformationInfo();
11696        if (mTransformationInfo.mAlpha != alpha) {
11697            mTransformationInfo.mAlpha = alpha;
11698            boolean subclassHandlesAlpha = onSetAlpha((int) (alpha * 255));
11699            if (subclassHandlesAlpha) {
11700                mPrivateFlags |= PFLAG_ALPHA_SET;
11701                return true;
11702            } else {
11703                mPrivateFlags &= ~PFLAG_ALPHA_SET;
11704                mRenderNode.setAlpha(getFinalAlpha());
11705            }
11706        }
11707        return false;
11708    }
11709
11710    /**
11711     * This property is hidden and intended only for use by the Fade transition, which
11712     * animates it to produce a visual translucency that does not side-effect (or get
11713     * affected by) the real alpha property. This value is composited with the other
11714     * alpha value (and the AlphaAnimation value, when that is present) to produce
11715     * a final visual translucency result, which is what is passed into the DisplayList.
11716     *
11717     * @hide
11718     */
11719    public void setTransitionAlpha(float alpha) {
11720        ensureTransformationInfo();
11721        if (mTransformationInfo.mTransitionAlpha != alpha) {
11722            mTransformationInfo.mTransitionAlpha = alpha;
11723            mPrivateFlags &= ~PFLAG_ALPHA_SET;
11724            invalidateViewProperty(true, false);
11725            mRenderNode.setAlpha(getFinalAlpha());
11726        }
11727    }
11728
11729    /**
11730     * Calculates the visual alpha of this view, which is a combination of the actual
11731     * alpha value and the transitionAlpha value (if set).
11732     */
11733    private float getFinalAlpha() {
11734        if (mTransformationInfo != null) {
11735            return mTransformationInfo.mAlpha * mTransformationInfo.mTransitionAlpha;
11736        }
11737        return 1;
11738    }
11739
11740    /**
11741     * This property is hidden and intended only for use by the Fade transition, which
11742     * animates it to produce a visual translucency that does not side-effect (or get
11743     * affected by) the real alpha property. This value is composited with the other
11744     * alpha value (and the AlphaAnimation value, when that is present) to produce
11745     * a final visual translucency result, which is what is passed into the DisplayList.
11746     *
11747     * @hide
11748     */
11749    @ViewDebug.ExportedProperty(category = "drawing")
11750    public float getTransitionAlpha() {
11751        return mTransformationInfo != null ? mTransformationInfo.mTransitionAlpha : 1;
11752    }
11753
11754    /**
11755     * Top position of this view relative to its parent.
11756     *
11757     * @return The top of this view, in pixels.
11758     */
11759    @ViewDebug.CapturedViewProperty
11760    public final int getTop() {
11761        return mTop;
11762    }
11763
11764    /**
11765     * Sets the top position of this view relative to its parent. This method is meant to be called
11766     * by the layout system and should not generally be called otherwise, because the property
11767     * may be changed at any time by the layout.
11768     *
11769     * @param top The top of this view, in pixels.
11770     */
11771    public final void setTop(int top) {
11772        if (top != mTop) {
11773            final boolean matrixIsIdentity = hasIdentityMatrix();
11774            if (matrixIsIdentity) {
11775                if (mAttachInfo != null) {
11776                    int minTop;
11777                    int yLoc;
11778                    if (top < mTop) {
11779                        minTop = top;
11780                        yLoc = top - mTop;
11781                    } else {
11782                        minTop = mTop;
11783                        yLoc = 0;
11784                    }
11785                    invalidate(0, yLoc, mRight - mLeft, mBottom - minTop);
11786                }
11787            } else {
11788                // Double-invalidation is necessary to capture view's old and new areas
11789                invalidate(true);
11790            }
11791
11792            int width = mRight - mLeft;
11793            int oldHeight = mBottom - mTop;
11794
11795            mTop = top;
11796            mRenderNode.setTop(mTop);
11797
11798            sizeChange(width, mBottom - mTop, width, oldHeight);
11799
11800            if (!matrixIsIdentity) {
11801                mPrivateFlags |= PFLAG_DRAWN; // force another invalidation with the new orientation
11802                invalidate(true);
11803            }
11804            mBackgroundSizeChanged = true;
11805            if (mForegroundInfo != null) {
11806                mForegroundInfo.mBoundsChanged = true;
11807            }
11808            invalidateParentIfNeeded();
11809            if ((mPrivateFlags2 & PFLAG2_VIEW_QUICK_REJECTED) == PFLAG2_VIEW_QUICK_REJECTED) {
11810                // View was rejected last time it was drawn by its parent; this may have changed
11811                invalidateParentIfNeeded();
11812            }
11813        }
11814    }
11815
11816    /**
11817     * Bottom position of this view relative to its parent.
11818     *
11819     * @return The bottom of this view, in pixels.
11820     */
11821    @ViewDebug.CapturedViewProperty
11822    public final int getBottom() {
11823        return mBottom;
11824    }
11825
11826    /**
11827     * True if this view has changed since the last time being drawn.
11828     *
11829     * @return The dirty state of this view.
11830     */
11831    public boolean isDirty() {
11832        return (mPrivateFlags & PFLAG_DIRTY_MASK) != 0;
11833    }
11834
11835    /**
11836     * Sets the bottom position of this view relative to its parent. This method is meant to be
11837     * called by the layout system and should not generally be called otherwise, because the
11838     * property may be changed at any time by the layout.
11839     *
11840     * @param bottom The bottom of this view, in pixels.
11841     */
11842    public final void setBottom(int bottom) {
11843        if (bottom != mBottom) {
11844            final boolean matrixIsIdentity = hasIdentityMatrix();
11845            if (matrixIsIdentity) {
11846                if (mAttachInfo != null) {
11847                    int maxBottom;
11848                    if (bottom < mBottom) {
11849                        maxBottom = mBottom;
11850                    } else {
11851                        maxBottom = bottom;
11852                    }
11853                    invalidate(0, 0, mRight - mLeft, maxBottom - mTop);
11854                }
11855            } else {
11856                // Double-invalidation is necessary to capture view's old and new areas
11857                invalidate(true);
11858            }
11859
11860            int width = mRight - mLeft;
11861            int oldHeight = mBottom - mTop;
11862
11863            mBottom = bottom;
11864            mRenderNode.setBottom(mBottom);
11865
11866            sizeChange(width, mBottom - mTop, width, oldHeight);
11867
11868            if (!matrixIsIdentity) {
11869                mPrivateFlags |= PFLAG_DRAWN; // force another invalidation with the new orientation
11870                invalidate(true);
11871            }
11872            mBackgroundSizeChanged = true;
11873            if (mForegroundInfo != null) {
11874                mForegroundInfo.mBoundsChanged = true;
11875            }
11876            invalidateParentIfNeeded();
11877            if ((mPrivateFlags2 & PFLAG2_VIEW_QUICK_REJECTED) == PFLAG2_VIEW_QUICK_REJECTED) {
11878                // View was rejected last time it was drawn by its parent; this may have changed
11879                invalidateParentIfNeeded();
11880            }
11881        }
11882    }
11883
11884    /**
11885     * Left position of this view relative to its parent.
11886     *
11887     * @return The left edge of this view, in pixels.
11888     */
11889    @ViewDebug.CapturedViewProperty
11890    public final int getLeft() {
11891        return mLeft;
11892    }
11893
11894    /**
11895     * Sets the left position of this view relative to its parent. This method is meant to be called
11896     * by the layout system and should not generally be called otherwise, because the property
11897     * may be changed at any time by the layout.
11898     *
11899     * @param left The left of this view, in pixels.
11900     */
11901    public final void setLeft(int left) {
11902        if (left != mLeft) {
11903            final boolean matrixIsIdentity = hasIdentityMatrix();
11904            if (matrixIsIdentity) {
11905                if (mAttachInfo != null) {
11906                    int minLeft;
11907                    int xLoc;
11908                    if (left < mLeft) {
11909                        minLeft = left;
11910                        xLoc = left - mLeft;
11911                    } else {
11912                        minLeft = mLeft;
11913                        xLoc = 0;
11914                    }
11915                    invalidate(xLoc, 0, mRight - minLeft, mBottom - mTop);
11916                }
11917            } else {
11918                // Double-invalidation is necessary to capture view's old and new areas
11919                invalidate(true);
11920            }
11921
11922            int oldWidth = mRight - mLeft;
11923            int height = mBottom - mTop;
11924
11925            mLeft = left;
11926            mRenderNode.setLeft(left);
11927
11928            sizeChange(mRight - mLeft, height, oldWidth, height);
11929
11930            if (!matrixIsIdentity) {
11931                mPrivateFlags |= PFLAG_DRAWN; // force another invalidation with the new orientation
11932                invalidate(true);
11933            }
11934            mBackgroundSizeChanged = true;
11935            if (mForegroundInfo != null) {
11936                mForegroundInfo.mBoundsChanged = true;
11937            }
11938            invalidateParentIfNeeded();
11939            if ((mPrivateFlags2 & PFLAG2_VIEW_QUICK_REJECTED) == PFLAG2_VIEW_QUICK_REJECTED) {
11940                // View was rejected last time it was drawn by its parent; this may have changed
11941                invalidateParentIfNeeded();
11942            }
11943        }
11944    }
11945
11946    /**
11947     * Right position of this view relative to its parent.
11948     *
11949     * @return The right edge of this view, in pixels.
11950     */
11951    @ViewDebug.CapturedViewProperty
11952    public final int getRight() {
11953        return mRight;
11954    }
11955
11956    /**
11957     * Sets the right position of this view relative to its parent. This method is meant to be called
11958     * by the layout system and should not generally be called otherwise, because the property
11959     * may be changed at any time by the layout.
11960     *
11961     * @param right The right of this view, in pixels.
11962     */
11963    public final void setRight(int right) {
11964        if (right != mRight) {
11965            final boolean matrixIsIdentity = hasIdentityMatrix();
11966            if (matrixIsIdentity) {
11967                if (mAttachInfo != null) {
11968                    int maxRight;
11969                    if (right < mRight) {
11970                        maxRight = mRight;
11971                    } else {
11972                        maxRight = right;
11973                    }
11974                    invalidate(0, 0, maxRight - mLeft, mBottom - mTop);
11975                }
11976            } else {
11977                // Double-invalidation is necessary to capture view's old and new areas
11978                invalidate(true);
11979            }
11980
11981            int oldWidth = mRight - mLeft;
11982            int height = mBottom - mTop;
11983
11984            mRight = right;
11985            mRenderNode.setRight(mRight);
11986
11987            sizeChange(mRight - mLeft, height, oldWidth, height);
11988
11989            if (!matrixIsIdentity) {
11990                mPrivateFlags |= PFLAG_DRAWN; // force another invalidation with the new orientation
11991                invalidate(true);
11992            }
11993            mBackgroundSizeChanged = true;
11994            if (mForegroundInfo != null) {
11995                mForegroundInfo.mBoundsChanged = true;
11996            }
11997            invalidateParentIfNeeded();
11998            if ((mPrivateFlags2 & PFLAG2_VIEW_QUICK_REJECTED) == PFLAG2_VIEW_QUICK_REJECTED) {
11999                // View was rejected last time it was drawn by its parent; this may have changed
12000                invalidateParentIfNeeded();
12001            }
12002        }
12003    }
12004
12005    /**
12006     * The visual x position of this view, in pixels. This is equivalent to the
12007     * {@link #setTranslationX(float) translationX} property plus the current
12008     * {@link #getLeft() left} property.
12009     *
12010     * @return The visual x position of this view, in pixels.
12011     */
12012    @ViewDebug.ExportedProperty(category = "drawing")
12013    public float getX() {
12014        return mLeft + getTranslationX();
12015    }
12016
12017    /**
12018     * Sets the visual x position of this view, in pixels. This is equivalent to setting the
12019     * {@link #setTranslationX(float) translationX} property to be the difference between
12020     * the x value passed in and the current {@link #getLeft() left} property.
12021     *
12022     * @param x The visual x position of this view, in pixels.
12023     */
12024    public void setX(float x) {
12025        setTranslationX(x - mLeft);
12026    }
12027
12028    /**
12029     * The visual y position of this view, in pixels. This is equivalent to the
12030     * {@link #setTranslationY(float) translationY} property plus the current
12031     * {@link #getTop() top} property.
12032     *
12033     * @return The visual y position of this view, in pixels.
12034     */
12035    @ViewDebug.ExportedProperty(category = "drawing")
12036    public float getY() {
12037        return mTop + getTranslationY();
12038    }
12039
12040    /**
12041     * Sets the visual y position of this view, in pixels. This is equivalent to setting the
12042     * {@link #setTranslationY(float) translationY} property to be the difference between
12043     * the y value passed in and the current {@link #getTop() top} property.
12044     *
12045     * @param y The visual y position of this view, in pixels.
12046     */
12047    public void setY(float y) {
12048        setTranslationY(y - mTop);
12049    }
12050
12051    /**
12052     * The visual z position of this view, in pixels. This is equivalent to the
12053     * {@link #setTranslationZ(float) translationZ} property plus the current
12054     * {@link #getElevation() elevation} property.
12055     *
12056     * @return The visual z position of this view, in pixels.
12057     */
12058    @ViewDebug.ExportedProperty(category = "drawing")
12059    public float getZ() {
12060        return getElevation() + getTranslationZ();
12061    }
12062
12063    /**
12064     * Sets the visual z position of this view, in pixels. This is equivalent to setting the
12065     * {@link #setTranslationZ(float) translationZ} property to be the difference between
12066     * the x value passed in and the current {@link #getElevation() elevation} property.
12067     *
12068     * @param z The visual z position of this view, in pixels.
12069     */
12070    public void setZ(float z) {
12071        setTranslationZ(z - getElevation());
12072    }
12073
12074    /**
12075     * The base elevation of this view relative to its parent, in pixels.
12076     *
12077     * @return The base depth position of the view, in pixels.
12078     */
12079    @ViewDebug.ExportedProperty(category = "drawing")
12080    public float getElevation() {
12081        return mRenderNode.getElevation();
12082    }
12083
12084    /**
12085     * Sets the base elevation of this view, in pixels.
12086     *
12087     * @attr ref android.R.styleable#View_elevation
12088     */
12089    public void setElevation(float elevation) {
12090        if (elevation != getElevation()) {
12091            invalidateViewProperty(true, false);
12092            mRenderNode.setElevation(elevation);
12093            invalidateViewProperty(false, true);
12094
12095            invalidateParentIfNeededAndWasQuickRejected();
12096        }
12097    }
12098
12099    /**
12100     * The horizontal location of this view relative to its {@link #getLeft() left} position.
12101     * This position is post-layout, in addition to wherever the object's
12102     * layout placed it.
12103     *
12104     * @return The horizontal position of this view relative to its left position, in pixels.
12105     */
12106    @ViewDebug.ExportedProperty(category = "drawing")
12107    public float getTranslationX() {
12108        return mRenderNode.getTranslationX();
12109    }
12110
12111    /**
12112     * Sets the horizontal location of this view relative to its {@link #getLeft() left} position.
12113     * This effectively positions the object post-layout, in addition to wherever the object's
12114     * layout placed it.
12115     *
12116     * @param translationX The horizontal position of this view relative to its left position,
12117     * in pixels.
12118     *
12119     * @attr ref android.R.styleable#View_translationX
12120     */
12121    public void setTranslationX(float translationX) {
12122        if (translationX != getTranslationX()) {
12123            invalidateViewProperty(true, false);
12124            mRenderNode.setTranslationX(translationX);
12125            invalidateViewProperty(false, true);
12126
12127            invalidateParentIfNeededAndWasQuickRejected();
12128            notifySubtreeAccessibilityStateChangedIfNeeded();
12129        }
12130    }
12131
12132    /**
12133     * The vertical location of this view relative to its {@link #getTop() top} position.
12134     * This position is post-layout, in addition to wherever the object's
12135     * layout placed it.
12136     *
12137     * @return The vertical position of this view relative to its top position,
12138     * in pixels.
12139     */
12140    @ViewDebug.ExportedProperty(category = "drawing")
12141    public float getTranslationY() {
12142        return mRenderNode.getTranslationY();
12143    }
12144
12145    /**
12146     * Sets the vertical location of this view relative to its {@link #getTop() top} position.
12147     * This effectively positions the object post-layout, in addition to wherever the object's
12148     * layout placed it.
12149     *
12150     * @param translationY The vertical position of this view relative to its top position,
12151     * in pixels.
12152     *
12153     * @attr ref android.R.styleable#View_translationY
12154     */
12155    public void setTranslationY(float translationY) {
12156        if (translationY != getTranslationY()) {
12157            invalidateViewProperty(true, false);
12158            mRenderNode.setTranslationY(translationY);
12159            invalidateViewProperty(false, true);
12160
12161            invalidateParentIfNeededAndWasQuickRejected();
12162            notifySubtreeAccessibilityStateChangedIfNeeded();
12163        }
12164    }
12165
12166    /**
12167     * The depth location of this view relative to its {@link #getElevation() elevation}.
12168     *
12169     * @return The depth of this view relative to its elevation.
12170     */
12171    @ViewDebug.ExportedProperty(category = "drawing")
12172    public float getTranslationZ() {
12173        return mRenderNode.getTranslationZ();
12174    }
12175
12176    /**
12177     * Sets the depth location of this view relative to its {@link #getElevation() elevation}.
12178     *
12179     * @attr ref android.R.styleable#View_translationZ
12180     */
12181    public void setTranslationZ(float translationZ) {
12182        if (translationZ != getTranslationZ()) {
12183            invalidateViewProperty(true, false);
12184            mRenderNode.setTranslationZ(translationZ);
12185            invalidateViewProperty(false, true);
12186
12187            invalidateParentIfNeededAndWasQuickRejected();
12188        }
12189    }
12190
12191    /** @hide */
12192    public void setAnimationMatrix(Matrix matrix) {
12193        invalidateViewProperty(true, false);
12194        mRenderNode.setAnimationMatrix(matrix);
12195        invalidateViewProperty(false, true);
12196
12197        invalidateParentIfNeededAndWasQuickRejected();
12198    }
12199
12200    /**
12201     * Returns the current StateListAnimator if exists.
12202     *
12203     * @return StateListAnimator or null if it does not exists
12204     * @see    #setStateListAnimator(android.animation.StateListAnimator)
12205     */
12206    public StateListAnimator getStateListAnimator() {
12207        return mStateListAnimator;
12208    }
12209
12210    /**
12211     * Attaches the provided StateListAnimator to this View.
12212     * <p>
12213     * Any previously attached StateListAnimator will be detached.
12214     *
12215     * @param stateListAnimator The StateListAnimator to update the view
12216     * @see {@link android.animation.StateListAnimator}
12217     */
12218    public void setStateListAnimator(StateListAnimator stateListAnimator) {
12219        if (mStateListAnimator == stateListAnimator) {
12220            return;
12221        }
12222        if (mStateListAnimator != null) {
12223            mStateListAnimator.setTarget(null);
12224        }
12225        mStateListAnimator = stateListAnimator;
12226        if (stateListAnimator != null) {
12227            stateListAnimator.setTarget(this);
12228            if (isAttachedToWindow()) {
12229                stateListAnimator.setState(getDrawableState());
12230            }
12231        }
12232    }
12233
12234    /**
12235     * Returns whether the Outline should be used to clip the contents of the View.
12236     * <p>
12237     * Note that this flag will only be respected if the View's Outline returns true from
12238     * {@link Outline#canClip()}.
12239     *
12240     * @see #setOutlineProvider(ViewOutlineProvider)
12241     * @see #setClipToOutline(boolean)
12242     */
12243    public final boolean getClipToOutline() {
12244        return mRenderNode.getClipToOutline();
12245    }
12246
12247    /**
12248     * Sets whether the View's Outline should be used to clip the contents of the View.
12249     * <p>
12250     * Only a single non-rectangular clip can be applied on a View at any time.
12251     * Circular clips from a {@link ViewAnimationUtils#createCircularReveal(View, int, int, float, float)
12252     * circular reveal} animation take priority over Outline clipping, and
12253     * child Outline clipping takes priority over Outline clipping done by a
12254     * parent.
12255     * <p>
12256     * Note that this flag will only be respected if the View's Outline returns true from
12257     * {@link Outline#canClip()}.
12258     *
12259     * @see #setOutlineProvider(ViewOutlineProvider)
12260     * @see #getClipToOutline()
12261     */
12262    public void setClipToOutline(boolean clipToOutline) {
12263        damageInParent();
12264        if (getClipToOutline() != clipToOutline) {
12265            mRenderNode.setClipToOutline(clipToOutline);
12266        }
12267    }
12268
12269    // correspond to the enum values of View_outlineProvider
12270    private static final int PROVIDER_BACKGROUND = 0;
12271    private static final int PROVIDER_NONE = 1;
12272    private static final int PROVIDER_BOUNDS = 2;
12273    private static final int PROVIDER_PADDED_BOUNDS = 3;
12274    private void setOutlineProviderFromAttribute(int providerInt) {
12275        switch (providerInt) {
12276            case PROVIDER_BACKGROUND:
12277                setOutlineProvider(ViewOutlineProvider.BACKGROUND);
12278                break;
12279            case PROVIDER_NONE:
12280                setOutlineProvider(null);
12281                break;
12282            case PROVIDER_BOUNDS:
12283                setOutlineProvider(ViewOutlineProvider.BOUNDS);
12284                break;
12285            case PROVIDER_PADDED_BOUNDS:
12286                setOutlineProvider(ViewOutlineProvider.PADDED_BOUNDS);
12287                break;
12288        }
12289    }
12290
12291    /**
12292     * Sets the {@link ViewOutlineProvider} of the view, which generates the Outline that defines
12293     * the shape of the shadow it casts, and enables outline clipping.
12294     * <p>
12295     * The default ViewOutlineProvider, {@link ViewOutlineProvider#BACKGROUND}, queries the Outline
12296     * from the View's background drawable, via {@link Drawable#getOutline(Outline)}. Changing the
12297     * outline provider with this method allows this behavior to be overridden.
12298     * <p>
12299     * If the ViewOutlineProvider is null, if querying it for an outline returns false,
12300     * or if the produced Outline is {@link Outline#isEmpty()}, shadows will not be cast.
12301     * <p>
12302     * Only outlines that return true from {@link Outline#canClip()} may be used for clipping.
12303     *
12304     * @see #setClipToOutline(boolean)
12305     * @see #getClipToOutline()
12306     * @see #getOutlineProvider()
12307     */
12308    public void setOutlineProvider(ViewOutlineProvider provider) {
12309        mOutlineProvider = provider;
12310        invalidateOutline();
12311    }
12312
12313    /**
12314     * Returns the current {@link ViewOutlineProvider} of the view, which generates the Outline
12315     * that defines the shape of the shadow it casts, and enables outline clipping.
12316     *
12317     * @see #setOutlineProvider(ViewOutlineProvider)
12318     */
12319    public ViewOutlineProvider getOutlineProvider() {
12320        return mOutlineProvider;
12321    }
12322
12323    /**
12324     * Called to rebuild this View's Outline from its {@link ViewOutlineProvider outline provider}
12325     *
12326     * @see #setOutlineProvider(ViewOutlineProvider)
12327     */
12328    public void invalidateOutline() {
12329        rebuildOutline();
12330
12331        notifySubtreeAccessibilityStateChangedIfNeeded();
12332        invalidateViewProperty(false, false);
12333    }
12334
12335    /**
12336     * Internal version of {@link #invalidateOutline()} which invalidates the
12337     * outline without invalidating the view itself. This is intended to be called from
12338     * within methods in the View class itself which are the result of the view being
12339     * invalidated already. For example, when we are drawing the background of a View,
12340     * we invalidate the outline in case it changed in the meantime, but we do not
12341     * need to invalidate the view because we're already drawing the background as part
12342     * of drawing the view in response to an earlier invalidation of the view.
12343     */
12344    private void rebuildOutline() {
12345        // Unattached views ignore this signal, and outline is recomputed in onAttachedToWindow()
12346        if (mAttachInfo == null) return;
12347
12348        if (mOutlineProvider == null) {
12349            // no provider, remove outline
12350            mRenderNode.setOutline(null);
12351        } else {
12352            final Outline outline = mAttachInfo.mTmpOutline;
12353            outline.setEmpty();
12354            outline.setAlpha(1.0f);
12355
12356            mOutlineProvider.getOutline(this, outline);
12357            mRenderNode.setOutline(outline);
12358        }
12359    }
12360
12361    /**
12362     * HierarchyViewer only
12363     *
12364     * @hide
12365     */
12366    @ViewDebug.ExportedProperty(category = "drawing")
12367    public boolean hasShadow() {
12368        return mRenderNode.hasShadow();
12369    }
12370
12371
12372    /** @hide */
12373    public void setRevealClip(boolean shouldClip, float x, float y, float radius) {
12374        mRenderNode.setRevealClip(shouldClip, x, y, radius);
12375        invalidateViewProperty(false, false);
12376    }
12377
12378    /**
12379     * Hit rectangle in parent's coordinates
12380     *
12381     * @param outRect The hit rectangle of the view.
12382     */
12383    public void getHitRect(Rect outRect) {
12384        if (hasIdentityMatrix() || mAttachInfo == null) {
12385            outRect.set(mLeft, mTop, mRight, mBottom);
12386        } else {
12387            final RectF tmpRect = mAttachInfo.mTmpTransformRect;
12388            tmpRect.set(0, 0, getWidth(), getHeight());
12389            getMatrix().mapRect(tmpRect); // TODO: mRenderNode.mapRect(tmpRect)
12390            outRect.set((int) tmpRect.left + mLeft, (int) tmpRect.top + mTop,
12391                    (int) tmpRect.right + mLeft, (int) tmpRect.bottom + mTop);
12392        }
12393    }
12394
12395    /**
12396     * Determines whether the given point, in local coordinates is inside the view.
12397     */
12398    /*package*/ final boolean pointInView(float localX, float localY) {
12399        return localX >= 0 && localX < (mRight - mLeft)
12400                && localY >= 0 && localY < (mBottom - mTop);
12401    }
12402
12403    /**
12404     * Utility method to determine whether the given point, in local coordinates,
12405     * is inside the view, where the area of the view is expanded by the slop factor.
12406     * This method is called while processing touch-move events to determine if the event
12407     * is still within the view.
12408     *
12409     * @hide
12410     */
12411    public boolean pointInView(float localX, float localY, float slop) {
12412        return localX >= -slop && localY >= -slop && localX < ((mRight - mLeft) + slop) &&
12413                localY < ((mBottom - mTop) + slop);
12414    }
12415
12416    /**
12417     * When a view has focus and the user navigates away from it, the next view is searched for
12418     * starting from the rectangle filled in by this method.
12419     *
12420     * By default, the rectangle is the {@link #getDrawingRect(android.graphics.Rect)})
12421     * of the view.  However, if your view maintains some idea of internal selection,
12422     * such as a cursor, or a selected row or column, you should override this method and
12423     * fill in a more specific rectangle.
12424     *
12425     * @param r The rectangle to fill in, in this view's coordinates.
12426     */
12427    public void getFocusedRect(Rect r) {
12428        getDrawingRect(r);
12429    }
12430
12431    /**
12432     * If some part of this view is not clipped by any of its parents, then
12433     * return that area in r in global (root) coordinates. To convert r to local
12434     * coordinates (without taking possible View rotations into account), offset
12435     * it by -globalOffset (e.g. r.offset(-globalOffset.x, -globalOffset.y)).
12436     * If the view is completely clipped or translated out, return false.
12437     *
12438     * @param r If true is returned, r holds the global coordinates of the
12439     *        visible portion of this view.
12440     * @param globalOffset If true is returned, globalOffset holds the dx,dy
12441     *        between this view and its root. globalOffet may be null.
12442     * @return true if r is non-empty (i.e. part of the view is visible at the
12443     *         root level.
12444     */
12445    public boolean getGlobalVisibleRect(Rect r, Point globalOffset) {
12446        int width = mRight - mLeft;
12447        int height = mBottom - mTop;
12448        if (width > 0 && height > 0) {
12449            r.set(0, 0, width, height);
12450            if (globalOffset != null) {
12451                globalOffset.set(-mScrollX, -mScrollY);
12452            }
12453            return mParent == null || mParent.getChildVisibleRect(this, r, globalOffset);
12454        }
12455        return false;
12456    }
12457
12458    public final boolean getGlobalVisibleRect(Rect r) {
12459        return getGlobalVisibleRect(r, null);
12460    }
12461
12462    public final boolean getLocalVisibleRect(Rect r) {
12463        final Point offset = mAttachInfo != null ? mAttachInfo.mPoint : new Point();
12464        if (getGlobalVisibleRect(r, offset)) {
12465            r.offset(-offset.x, -offset.y); // make r local
12466            return true;
12467        }
12468        return false;
12469    }
12470
12471    /**
12472     * Offset this view's vertical location by the specified number of pixels.
12473     *
12474     * @param offset the number of pixels to offset the view by
12475     */
12476    public void offsetTopAndBottom(int offset) {
12477        if (offset != 0) {
12478            final boolean matrixIsIdentity = hasIdentityMatrix();
12479            if (matrixIsIdentity) {
12480                if (isHardwareAccelerated()) {
12481                    invalidateViewProperty(false, false);
12482                } else {
12483                    final ViewParent p = mParent;
12484                    if (p != null && mAttachInfo != null) {
12485                        final Rect r = mAttachInfo.mTmpInvalRect;
12486                        int minTop;
12487                        int maxBottom;
12488                        int yLoc;
12489                        if (offset < 0) {
12490                            minTop = mTop + offset;
12491                            maxBottom = mBottom;
12492                            yLoc = offset;
12493                        } else {
12494                            minTop = mTop;
12495                            maxBottom = mBottom + offset;
12496                            yLoc = 0;
12497                        }
12498                        r.set(0, yLoc, mRight - mLeft, maxBottom - minTop);
12499                        p.invalidateChild(this, r);
12500                    }
12501                }
12502            } else {
12503                invalidateViewProperty(false, false);
12504            }
12505
12506            mTop += offset;
12507            mBottom += offset;
12508            mRenderNode.offsetTopAndBottom(offset);
12509            if (isHardwareAccelerated()) {
12510                invalidateViewProperty(false, false);
12511                invalidateParentIfNeededAndWasQuickRejected();
12512            } else {
12513                if (!matrixIsIdentity) {
12514                    invalidateViewProperty(false, true);
12515                }
12516                invalidateParentIfNeeded();
12517            }
12518            notifySubtreeAccessibilityStateChangedIfNeeded();
12519        }
12520    }
12521
12522    /**
12523     * Offset this view's horizontal location by the specified amount of pixels.
12524     *
12525     * @param offset the number of pixels to offset the view by
12526     */
12527    public void offsetLeftAndRight(int offset) {
12528        if (offset != 0) {
12529            final boolean matrixIsIdentity = hasIdentityMatrix();
12530            if (matrixIsIdentity) {
12531                if (isHardwareAccelerated()) {
12532                    invalidateViewProperty(false, false);
12533                } else {
12534                    final ViewParent p = mParent;
12535                    if (p != null && mAttachInfo != null) {
12536                        final Rect r = mAttachInfo.mTmpInvalRect;
12537                        int minLeft;
12538                        int maxRight;
12539                        if (offset < 0) {
12540                            minLeft = mLeft + offset;
12541                            maxRight = mRight;
12542                        } else {
12543                            minLeft = mLeft;
12544                            maxRight = mRight + offset;
12545                        }
12546                        r.set(0, 0, maxRight - minLeft, mBottom - mTop);
12547                        p.invalidateChild(this, r);
12548                    }
12549                }
12550            } else {
12551                invalidateViewProperty(false, false);
12552            }
12553
12554            mLeft += offset;
12555            mRight += offset;
12556            mRenderNode.offsetLeftAndRight(offset);
12557            if (isHardwareAccelerated()) {
12558                invalidateViewProperty(false, false);
12559                invalidateParentIfNeededAndWasQuickRejected();
12560            } else {
12561                if (!matrixIsIdentity) {
12562                    invalidateViewProperty(false, true);
12563                }
12564                invalidateParentIfNeeded();
12565            }
12566            notifySubtreeAccessibilityStateChangedIfNeeded();
12567        }
12568    }
12569
12570    /**
12571     * Get the LayoutParams associated with this view. All views should have
12572     * layout parameters. These supply parameters to the <i>parent</i> of this
12573     * view specifying how it should be arranged. There are many subclasses of
12574     * ViewGroup.LayoutParams, and these correspond to the different subclasses
12575     * of ViewGroup that are responsible for arranging their children.
12576     *
12577     * This method may return null if this View is not attached to a parent
12578     * ViewGroup or {@link #setLayoutParams(android.view.ViewGroup.LayoutParams)}
12579     * was not invoked successfully. When a View is attached to a parent
12580     * ViewGroup, this method must not return null.
12581     *
12582     * @return The LayoutParams associated with this view, or null if no
12583     *         parameters have been set yet
12584     */
12585    @ViewDebug.ExportedProperty(deepExport = true, prefix = "layout_")
12586    public ViewGroup.LayoutParams getLayoutParams() {
12587        return mLayoutParams;
12588    }
12589
12590    /**
12591     * Set the layout parameters associated with this view. These supply
12592     * parameters to the <i>parent</i> of this view specifying how it should be
12593     * arranged. There are many subclasses of ViewGroup.LayoutParams, and these
12594     * correspond to the different subclasses of ViewGroup that are responsible
12595     * for arranging their children.
12596     *
12597     * @param params The layout parameters for this view, cannot be null
12598     */
12599    public void setLayoutParams(ViewGroup.LayoutParams params) {
12600        if (params == null) {
12601            throw new NullPointerException("Layout parameters cannot be null");
12602        }
12603        mLayoutParams = params;
12604        resolveLayoutParams();
12605        if (mParent instanceof ViewGroup) {
12606            ((ViewGroup) mParent).onSetLayoutParams(this, params);
12607        }
12608        requestLayout();
12609    }
12610
12611    /**
12612     * Resolve the layout parameters depending on the resolved layout direction
12613     *
12614     * @hide
12615     */
12616    public void resolveLayoutParams() {
12617        if (mLayoutParams != null) {
12618            mLayoutParams.resolveLayoutDirection(getLayoutDirection());
12619        }
12620    }
12621
12622    /**
12623     * Set the scrolled position of your view. This will cause a call to
12624     * {@link #onScrollChanged(int, int, int, int)} and the view will be
12625     * invalidated.
12626     * @param x the x position to scroll to
12627     * @param y the y position to scroll to
12628     */
12629    public void scrollTo(int x, int y) {
12630        if (mScrollX != x || mScrollY != y) {
12631            int oldX = mScrollX;
12632            int oldY = mScrollY;
12633            mScrollX = x;
12634            mScrollY = y;
12635            invalidateParentCaches();
12636            onScrollChanged(mScrollX, mScrollY, oldX, oldY);
12637            if (!awakenScrollBars()) {
12638                postInvalidateOnAnimation();
12639            }
12640        }
12641    }
12642
12643    /**
12644     * Move the scrolled position of your view. This will cause a call to
12645     * {@link #onScrollChanged(int, int, int, int)} and the view will be
12646     * invalidated.
12647     * @param x the amount of pixels to scroll by horizontally
12648     * @param y the amount of pixels to scroll by vertically
12649     */
12650    public void scrollBy(int x, int y) {
12651        scrollTo(mScrollX + x, mScrollY + y);
12652    }
12653
12654    /**
12655     * <p>Trigger the scrollbars to draw. When invoked this method starts an
12656     * animation to fade the scrollbars out after a default delay. If a subclass
12657     * provides animated scrolling, the start delay should equal the duration
12658     * of the scrolling animation.</p>
12659     *
12660     * <p>The animation starts only if at least one of the scrollbars is
12661     * enabled, as specified by {@link #isHorizontalScrollBarEnabled()} and
12662     * {@link #isVerticalScrollBarEnabled()}. When the animation is started,
12663     * this method returns true, and false otherwise. If the animation is
12664     * started, this method calls {@link #invalidate()}; in that case the
12665     * caller should not call {@link #invalidate()}.</p>
12666     *
12667     * <p>This method should be invoked every time a subclass directly updates
12668     * the scroll parameters.</p>
12669     *
12670     * <p>This method is automatically invoked by {@link #scrollBy(int, int)}
12671     * and {@link #scrollTo(int, int)}.</p>
12672     *
12673     * @return true if the animation is played, false otherwise
12674     *
12675     * @see #awakenScrollBars(int)
12676     * @see #scrollBy(int, int)
12677     * @see #scrollTo(int, int)
12678     * @see #isHorizontalScrollBarEnabled()
12679     * @see #isVerticalScrollBarEnabled()
12680     * @see #setHorizontalScrollBarEnabled(boolean)
12681     * @see #setVerticalScrollBarEnabled(boolean)
12682     */
12683    protected boolean awakenScrollBars() {
12684        return mScrollCache != null &&
12685                awakenScrollBars(mScrollCache.scrollBarDefaultDelayBeforeFade, true);
12686    }
12687
12688    /**
12689     * Trigger the scrollbars to draw.
12690     * This method differs from awakenScrollBars() only in its default duration.
12691     * initialAwakenScrollBars() will show the scroll bars for longer than
12692     * usual to give the user more of a chance to notice them.
12693     *
12694     * @return true if the animation is played, false otherwise.
12695     */
12696    private boolean initialAwakenScrollBars() {
12697        return mScrollCache != null &&
12698                awakenScrollBars(mScrollCache.scrollBarDefaultDelayBeforeFade * 4, true);
12699    }
12700
12701    /**
12702     * <p>
12703     * Trigger the scrollbars to draw. When invoked this method starts an
12704     * animation to fade the scrollbars out after a fixed delay. If a subclass
12705     * provides animated scrolling, the start delay should equal the duration of
12706     * the scrolling animation.
12707     * </p>
12708     *
12709     * <p>
12710     * The animation starts only if at least one of the scrollbars is enabled,
12711     * as specified by {@link #isHorizontalScrollBarEnabled()} and
12712     * {@link #isVerticalScrollBarEnabled()}. When the animation is started,
12713     * this method returns true, and false otherwise. If the animation is
12714     * started, this method calls {@link #invalidate()}; in that case the caller
12715     * should not call {@link #invalidate()}.
12716     * </p>
12717     *
12718     * <p>
12719     * This method should be invoked every time a subclass directly updates the
12720     * scroll parameters.
12721     * </p>
12722     *
12723     * @param startDelay the delay, in milliseconds, after which the animation
12724     *        should start; when the delay is 0, the animation starts
12725     *        immediately
12726     * @return true if the animation is played, false otherwise
12727     *
12728     * @see #scrollBy(int, int)
12729     * @see #scrollTo(int, int)
12730     * @see #isHorizontalScrollBarEnabled()
12731     * @see #isVerticalScrollBarEnabled()
12732     * @see #setHorizontalScrollBarEnabled(boolean)
12733     * @see #setVerticalScrollBarEnabled(boolean)
12734     */
12735    protected boolean awakenScrollBars(int startDelay) {
12736        return awakenScrollBars(startDelay, true);
12737    }
12738
12739    /**
12740     * <p>
12741     * Trigger the scrollbars to draw. When invoked this method starts an
12742     * animation to fade the scrollbars out after a fixed delay. If a subclass
12743     * provides animated scrolling, the start delay should equal the duration of
12744     * the scrolling animation.
12745     * </p>
12746     *
12747     * <p>
12748     * The animation starts only if at least one of the scrollbars is enabled,
12749     * as specified by {@link #isHorizontalScrollBarEnabled()} and
12750     * {@link #isVerticalScrollBarEnabled()}. When the animation is started,
12751     * this method returns true, and false otherwise. If the animation is
12752     * started, this method calls {@link #invalidate()} if the invalidate parameter
12753     * is set to true; in that case the caller
12754     * should not call {@link #invalidate()}.
12755     * </p>
12756     *
12757     * <p>
12758     * This method should be invoked every time a subclass directly updates the
12759     * scroll parameters.
12760     * </p>
12761     *
12762     * @param startDelay the delay, in milliseconds, after which the animation
12763     *        should start; when the delay is 0, the animation starts
12764     *        immediately
12765     *
12766     * @param invalidate Whether this method should call invalidate
12767     *
12768     * @return true if the animation is played, false otherwise
12769     *
12770     * @see #scrollBy(int, int)
12771     * @see #scrollTo(int, int)
12772     * @see #isHorizontalScrollBarEnabled()
12773     * @see #isVerticalScrollBarEnabled()
12774     * @see #setHorizontalScrollBarEnabled(boolean)
12775     * @see #setVerticalScrollBarEnabled(boolean)
12776     */
12777    protected boolean awakenScrollBars(int startDelay, boolean invalidate) {
12778        final ScrollabilityCache scrollCache = mScrollCache;
12779
12780        if (scrollCache == null || !scrollCache.fadeScrollBars) {
12781            return false;
12782        }
12783
12784        if (scrollCache.scrollBar == null) {
12785            scrollCache.scrollBar = new ScrollBarDrawable();
12786            scrollCache.scrollBar.setCallback(this);
12787            scrollCache.scrollBar.setState(getDrawableState());
12788        }
12789
12790        if (isHorizontalScrollBarEnabled() || isVerticalScrollBarEnabled()) {
12791
12792            if (invalidate) {
12793                // Invalidate to show the scrollbars
12794                postInvalidateOnAnimation();
12795            }
12796
12797            if (scrollCache.state == ScrollabilityCache.OFF) {
12798                // FIXME: this is copied from WindowManagerService.
12799                // We should get this value from the system when it
12800                // is possible to do so.
12801                final int KEY_REPEAT_FIRST_DELAY = 750;
12802                startDelay = Math.max(KEY_REPEAT_FIRST_DELAY, startDelay);
12803            }
12804
12805            // Tell mScrollCache when we should start fading. This may
12806            // extend the fade start time if one was already scheduled
12807            long fadeStartTime = AnimationUtils.currentAnimationTimeMillis() + startDelay;
12808            scrollCache.fadeStartTime = fadeStartTime;
12809            scrollCache.state = ScrollabilityCache.ON;
12810
12811            // Schedule our fader to run, unscheduling any old ones first
12812            if (mAttachInfo != null) {
12813                mAttachInfo.mHandler.removeCallbacks(scrollCache);
12814                mAttachInfo.mHandler.postAtTime(scrollCache, fadeStartTime);
12815            }
12816
12817            return true;
12818        }
12819
12820        return false;
12821    }
12822
12823    /**
12824     * Do not invalidate views which are not visible and which are not running an animation. They
12825     * will not get drawn and they should not set dirty flags as if they will be drawn
12826     */
12827    private boolean skipInvalidate() {
12828        return (mViewFlags & VISIBILITY_MASK) != VISIBLE && mCurrentAnimation == null &&
12829                (!(mParent instanceof ViewGroup) ||
12830                        !((ViewGroup) mParent).isViewTransitioning(this));
12831    }
12832
12833    /**
12834     * Mark the area defined by dirty as needing to be drawn. If the view is
12835     * visible, {@link #onDraw(android.graphics.Canvas)} will be called at some
12836     * point in the future.
12837     * <p>
12838     * This must be called from a UI thread. To call from a non-UI thread, call
12839     * {@link #postInvalidate()}.
12840     * <p>
12841     * <b>WARNING:</b> In API 19 and below, this method may be destructive to
12842     * {@code dirty}.
12843     *
12844     * @param dirty the rectangle representing the bounds of the dirty region
12845     */
12846    public void invalidate(Rect dirty) {
12847        final int scrollX = mScrollX;
12848        final int scrollY = mScrollY;
12849        invalidateInternal(dirty.left - scrollX, dirty.top - scrollY,
12850                dirty.right - scrollX, dirty.bottom - scrollY, true, false);
12851    }
12852
12853    /**
12854     * Mark the area defined by the rect (l,t,r,b) as needing to be drawn. The
12855     * coordinates of the dirty rect are relative to the view. If the view is
12856     * visible, {@link #onDraw(android.graphics.Canvas)} will be called at some
12857     * point in the future.
12858     * <p>
12859     * This must be called from a UI thread. To call from a non-UI thread, call
12860     * {@link #postInvalidate()}.
12861     *
12862     * @param l the left position of the dirty region
12863     * @param t the top position of the dirty region
12864     * @param r the right position of the dirty region
12865     * @param b the bottom position of the dirty region
12866     */
12867    public void invalidate(int l, int t, int r, int b) {
12868        final int scrollX = mScrollX;
12869        final int scrollY = mScrollY;
12870        invalidateInternal(l - scrollX, t - scrollY, r - scrollX, b - scrollY, true, false);
12871    }
12872
12873    /**
12874     * Invalidate the whole view. If the view is visible,
12875     * {@link #onDraw(android.graphics.Canvas)} will be called at some point in
12876     * the future.
12877     * <p>
12878     * This must be called from a UI thread. To call from a non-UI thread, call
12879     * {@link #postInvalidate()}.
12880     */
12881    public void invalidate() {
12882        invalidate(true);
12883    }
12884
12885    /**
12886     * This is where the invalidate() work actually happens. A full invalidate()
12887     * causes the drawing cache to be invalidated, but this function can be
12888     * called with invalidateCache set to false to skip that invalidation step
12889     * for cases that do not need it (for example, a component that remains at
12890     * the same dimensions with the same content).
12891     *
12892     * @param invalidateCache Whether the drawing cache for this view should be
12893     *            invalidated as well. This is usually true for a full
12894     *            invalidate, but may be set to false if the View's contents or
12895     *            dimensions have not changed.
12896     */
12897    void invalidate(boolean invalidateCache) {
12898        invalidateInternal(0, 0, mRight - mLeft, mBottom - mTop, invalidateCache, true);
12899    }
12900
12901    void invalidateInternal(int l, int t, int r, int b, boolean invalidateCache,
12902            boolean fullInvalidate) {
12903        if (mGhostView != null) {
12904            mGhostView.invalidate(true);
12905            return;
12906        }
12907
12908        if (skipInvalidate()) {
12909            return;
12910        }
12911
12912        if ((mPrivateFlags & (PFLAG_DRAWN | PFLAG_HAS_BOUNDS)) == (PFLAG_DRAWN | PFLAG_HAS_BOUNDS)
12913                || (invalidateCache && (mPrivateFlags & PFLAG_DRAWING_CACHE_VALID) == PFLAG_DRAWING_CACHE_VALID)
12914                || (mPrivateFlags & PFLAG_INVALIDATED) != PFLAG_INVALIDATED
12915                || (fullInvalidate && isOpaque() != mLastIsOpaque)) {
12916            if (fullInvalidate) {
12917                mLastIsOpaque = isOpaque();
12918                mPrivateFlags &= ~PFLAG_DRAWN;
12919            }
12920
12921            mPrivateFlags |= PFLAG_DIRTY;
12922
12923            // Release any resources in-case we don't end up drawing again
12924            // as anything cached is no longer valid
12925            resetDisplayList();
12926
12927            if (invalidateCache) {
12928                mPrivateFlags |= PFLAG_INVALIDATED;
12929                mPrivateFlags &= ~PFLAG_DRAWING_CACHE_VALID;
12930            }
12931
12932            // Propagate the damage rectangle to the parent view.
12933            final AttachInfo ai = mAttachInfo;
12934            final ViewParent p = mParent;
12935            if (p != null && ai != null && l < r && t < b) {
12936                final Rect damage = ai.mTmpInvalRect;
12937                damage.set(l, t, r, b);
12938                p.invalidateChild(this, damage);
12939            }
12940
12941            // Damage the entire projection receiver, if necessary.
12942            if (mBackground != null && mBackground.isProjected()) {
12943                final View receiver = getProjectionReceiver();
12944                if (receiver != null) {
12945                    receiver.damageInParent();
12946                }
12947            }
12948
12949            // Damage the entire IsolatedZVolume receiving this view's shadow.
12950            if (isHardwareAccelerated() && getZ() != 0) {
12951                damageShadowReceiver();
12952            }
12953        }
12954    }
12955
12956    /**
12957     * @return this view's projection receiver, or {@code null} if none exists
12958     */
12959    private View getProjectionReceiver() {
12960        ViewParent p = getParent();
12961        while (p != null && p instanceof View) {
12962            final View v = (View) p;
12963            if (v.isProjectionReceiver()) {
12964                return v;
12965            }
12966            p = p.getParent();
12967        }
12968
12969        return null;
12970    }
12971
12972    /**
12973     * @return whether the view is a projection receiver
12974     */
12975    private boolean isProjectionReceiver() {
12976        return mBackground != null;
12977    }
12978
12979    /**
12980     * Damage area of the screen that can be covered by this View's shadow.
12981     *
12982     * This method will guarantee that any changes to shadows cast by a View
12983     * are damaged on the screen for future redraw.
12984     */
12985    private void damageShadowReceiver() {
12986        final AttachInfo ai = mAttachInfo;
12987        if (ai != null) {
12988            ViewParent p = getParent();
12989            if (p != null && p instanceof ViewGroup) {
12990                final ViewGroup vg = (ViewGroup) p;
12991                vg.damageInParent();
12992            }
12993        }
12994    }
12995
12996    /**
12997     * Quick invalidation for View property changes (alpha, translationXY, etc.). We don't want to
12998     * set any flags or handle all of the cases handled by the default invalidation methods.
12999     * Instead, we just want to schedule a traversal in ViewRootImpl with the appropriate
13000     * dirty rect. This method calls into fast invalidation methods in ViewGroup that
13001     * walk up the hierarchy, transforming the dirty rect as necessary.
13002     *
13003     * The method also handles normal invalidation logic if display list properties are not
13004     * being used in this view. The invalidateParent and forceRedraw flags are used by that
13005     * backup approach, to handle these cases used in the various property-setting methods.
13006     *
13007     * @param invalidateParent Force a call to invalidateParentCaches() if display list properties
13008     * are not being used in this view
13009     * @param forceRedraw Mark the view as DRAWN to force the invalidation to propagate, if display
13010     * list properties are not being used in this view
13011     */
13012    void invalidateViewProperty(boolean invalidateParent, boolean forceRedraw) {
13013        if (!isHardwareAccelerated()
13014                || !mRenderNode.isValid()
13015                || (mPrivateFlags & PFLAG_DRAW_ANIMATION) != 0) {
13016            if (invalidateParent) {
13017                invalidateParentCaches();
13018            }
13019            if (forceRedraw) {
13020                mPrivateFlags |= PFLAG_DRAWN; // force another invalidation with the new orientation
13021            }
13022            invalidate(false);
13023        } else {
13024            damageInParent();
13025        }
13026        if (isHardwareAccelerated() && invalidateParent && getZ() != 0) {
13027            damageShadowReceiver();
13028        }
13029    }
13030
13031    /**
13032     * Tells the parent view to damage this view's bounds.
13033     *
13034     * @hide
13035     */
13036    protected void damageInParent() {
13037        final AttachInfo ai = mAttachInfo;
13038        final ViewParent p = mParent;
13039        if (p != null && ai != null) {
13040            final Rect r = ai.mTmpInvalRect;
13041            r.set(0, 0, mRight - mLeft, mBottom - mTop);
13042            if (mParent instanceof ViewGroup) {
13043                ((ViewGroup) mParent).damageChild(this, r);
13044            } else {
13045                mParent.invalidateChild(this, r);
13046            }
13047        }
13048    }
13049
13050    /**
13051     * Utility method to transform a given Rect by the current matrix of this view.
13052     */
13053    void transformRect(final Rect rect) {
13054        if (!getMatrix().isIdentity()) {
13055            RectF boundingRect = mAttachInfo.mTmpTransformRect;
13056            boundingRect.set(rect);
13057            getMatrix().mapRect(boundingRect);
13058            rect.set((int) Math.floor(boundingRect.left),
13059                    (int) Math.floor(boundingRect.top),
13060                    (int) Math.ceil(boundingRect.right),
13061                    (int) Math.ceil(boundingRect.bottom));
13062        }
13063    }
13064
13065    /**
13066     * Used to indicate that the parent of this view should clear its caches. This functionality
13067     * is used to force the parent to rebuild its display list (when hardware-accelerated),
13068     * which is necessary when various parent-managed properties of the view change, such as
13069     * alpha, translationX/Y, scrollX/Y, scaleX/Y, and rotation/X/Y. This method only
13070     * clears the parent caches and does not causes an invalidate event.
13071     *
13072     * @hide
13073     */
13074    protected void invalidateParentCaches() {
13075        if (mParent instanceof View) {
13076            ((View) mParent).mPrivateFlags |= PFLAG_INVALIDATED;
13077        }
13078    }
13079
13080    /**
13081     * Used to indicate that the parent of this view should be invalidated. This functionality
13082     * is used to force the parent to rebuild its display list (when hardware-accelerated),
13083     * which is necessary when various parent-managed properties of the view change, such as
13084     * alpha, translationX/Y, scrollX/Y, scaleX/Y, and rotation/X/Y. This method will propagate
13085     * an invalidation event to the parent.
13086     *
13087     * @hide
13088     */
13089    protected void invalidateParentIfNeeded() {
13090        if (isHardwareAccelerated() && mParent instanceof View) {
13091            ((View) mParent).invalidate(true);
13092        }
13093    }
13094
13095    /**
13096     * @hide
13097     */
13098    protected void invalidateParentIfNeededAndWasQuickRejected() {
13099        if ((mPrivateFlags2 & PFLAG2_VIEW_QUICK_REJECTED) != 0) {
13100            // View was rejected last time it was drawn by its parent; this may have changed
13101            invalidateParentIfNeeded();
13102        }
13103    }
13104
13105    /**
13106     * Indicates whether this View is opaque. An opaque View guarantees that it will
13107     * draw all the pixels overlapping its bounds using a fully opaque color.
13108     *
13109     * Subclasses of View should override this method whenever possible to indicate
13110     * whether an instance is opaque. Opaque Views are treated in a special way by
13111     * the View hierarchy, possibly allowing it to perform optimizations during
13112     * invalidate/draw passes.
13113     *
13114     * @return True if this View is guaranteed to be fully opaque, false otherwise.
13115     */
13116    @ViewDebug.ExportedProperty(category = "drawing")
13117    public boolean isOpaque() {
13118        return (mPrivateFlags & PFLAG_OPAQUE_MASK) == PFLAG_OPAQUE_MASK &&
13119                getFinalAlpha() >= 1.0f;
13120    }
13121
13122    /**
13123     * @hide
13124     */
13125    protected void computeOpaqueFlags() {
13126        // Opaque if:
13127        //   - Has a background
13128        //   - Background is opaque
13129        //   - Doesn't have scrollbars or scrollbars overlay
13130
13131        if (mBackground != null && mBackground.getOpacity() == PixelFormat.OPAQUE) {
13132            mPrivateFlags |= PFLAG_OPAQUE_BACKGROUND;
13133        } else {
13134            mPrivateFlags &= ~PFLAG_OPAQUE_BACKGROUND;
13135        }
13136
13137        final int flags = mViewFlags;
13138        if (((flags & SCROLLBARS_VERTICAL) == 0 && (flags & SCROLLBARS_HORIZONTAL) == 0) ||
13139                (flags & SCROLLBARS_STYLE_MASK) == SCROLLBARS_INSIDE_OVERLAY ||
13140                (flags & SCROLLBARS_STYLE_MASK) == SCROLLBARS_OUTSIDE_OVERLAY) {
13141            mPrivateFlags |= PFLAG_OPAQUE_SCROLLBARS;
13142        } else {
13143            mPrivateFlags &= ~PFLAG_OPAQUE_SCROLLBARS;
13144        }
13145    }
13146
13147    /**
13148     * @hide
13149     */
13150    protected boolean hasOpaqueScrollbars() {
13151        return (mPrivateFlags & PFLAG_OPAQUE_SCROLLBARS) == PFLAG_OPAQUE_SCROLLBARS;
13152    }
13153
13154    /**
13155     * @return A handler associated with the thread running the View. This
13156     * handler can be used to pump events in the UI events queue.
13157     */
13158    public Handler getHandler() {
13159        final AttachInfo attachInfo = mAttachInfo;
13160        if (attachInfo != null) {
13161            return attachInfo.mHandler;
13162        }
13163        return null;
13164    }
13165
13166    /**
13167     * Returns the queue of runnable for this view.
13168     *
13169     * @return the queue of runnables for this view
13170     */
13171    private HandlerActionQueue getRunQueue() {
13172        if (mRunQueue == null) {
13173            mRunQueue = new HandlerActionQueue();
13174        }
13175        return mRunQueue;
13176    }
13177
13178    /**
13179     * Gets the view root associated with the View.
13180     * @return The view root, or null if none.
13181     * @hide
13182     */
13183    public ViewRootImpl getViewRootImpl() {
13184        if (mAttachInfo != null) {
13185            return mAttachInfo.mViewRootImpl;
13186        }
13187        return null;
13188    }
13189
13190    /**
13191     * @hide
13192     */
13193    public HardwareRenderer getHardwareRenderer() {
13194        return mAttachInfo != null ? mAttachInfo.mHardwareRenderer : null;
13195    }
13196
13197    /**
13198     * <p>Causes the Runnable to be added to the message queue.
13199     * The runnable will be run on the user interface thread.</p>
13200     *
13201     * @param action The Runnable that will be executed.
13202     *
13203     * @return Returns true if the Runnable was successfully placed in to the
13204     *         message queue.  Returns false on failure, usually because the
13205     *         looper processing the message queue is exiting.
13206     *
13207     * @see #postDelayed
13208     * @see #removeCallbacks
13209     */
13210    public boolean post(Runnable action) {
13211        final AttachInfo attachInfo = mAttachInfo;
13212        if (attachInfo != null) {
13213            return attachInfo.mHandler.post(action);
13214        }
13215
13216        // Postpone the runnable until we know on which thread it needs to run.
13217        // Assume that the runnable will be successfully placed after attach.
13218        getRunQueue().post(action);
13219        return true;
13220    }
13221
13222    /**
13223     * <p>Causes the Runnable to be added to the message queue, to be run
13224     * after the specified amount of time elapses.
13225     * The runnable will be run on the user interface thread.</p>
13226     *
13227     * @param action The Runnable that will be executed.
13228     * @param delayMillis The delay (in milliseconds) until the Runnable
13229     *        will be executed.
13230     *
13231     * @return true if the Runnable was successfully placed in to the
13232     *         message queue.  Returns false on failure, usually because the
13233     *         looper processing the message queue is exiting.  Note that a
13234     *         result of true does not mean the Runnable will be processed --
13235     *         if the looper is quit before the delivery time of the message
13236     *         occurs then the message will be dropped.
13237     *
13238     * @see #post
13239     * @see #removeCallbacks
13240     */
13241    public boolean postDelayed(Runnable action, long delayMillis) {
13242        final AttachInfo attachInfo = mAttachInfo;
13243        if (attachInfo != null) {
13244            return attachInfo.mHandler.postDelayed(action, delayMillis);
13245        }
13246
13247        // Postpone the runnable until we know on which thread it needs to run.
13248        // Assume that the runnable will be successfully placed after attach.
13249        getRunQueue().postDelayed(action, delayMillis);
13250        return true;
13251    }
13252
13253    /**
13254     * <p>Causes the Runnable to execute on the next animation time step.
13255     * The runnable will be run on the user interface thread.</p>
13256     *
13257     * @param action The Runnable that will be executed.
13258     *
13259     * @see #postOnAnimationDelayed
13260     * @see #removeCallbacks
13261     */
13262    public void postOnAnimation(Runnable action) {
13263        final AttachInfo attachInfo = mAttachInfo;
13264        if (attachInfo != null) {
13265            attachInfo.mViewRootImpl.mChoreographer.postCallback(
13266                    Choreographer.CALLBACK_ANIMATION, action, null);
13267        } else {
13268            // Postpone the runnable until we know
13269            // on which thread it needs to run.
13270            getRunQueue().post(action);
13271        }
13272    }
13273
13274    /**
13275     * <p>Causes the Runnable to execute on the next animation time step,
13276     * after the specified amount of time elapses.
13277     * The runnable will be run on the user interface thread.</p>
13278     *
13279     * @param action The Runnable that will be executed.
13280     * @param delayMillis The delay (in milliseconds) until the Runnable
13281     *        will be executed.
13282     *
13283     * @see #postOnAnimation
13284     * @see #removeCallbacks
13285     */
13286    public void postOnAnimationDelayed(Runnable action, long delayMillis) {
13287        final AttachInfo attachInfo = mAttachInfo;
13288        if (attachInfo != null) {
13289            attachInfo.mViewRootImpl.mChoreographer.postCallbackDelayed(
13290                    Choreographer.CALLBACK_ANIMATION, action, null, delayMillis);
13291        } else {
13292            // Postpone the runnable until we know
13293            // on which thread it needs to run.
13294            getRunQueue().postDelayed(action, delayMillis);
13295        }
13296    }
13297
13298    /**
13299     * <p>Removes the specified Runnable from the message queue.</p>
13300     *
13301     * @param action The Runnable to remove from the message handling queue
13302     *
13303     * @return true if this view could ask the Handler to remove the Runnable,
13304     *         false otherwise. When the returned value is true, the Runnable
13305     *         may or may not have been actually removed from the message queue
13306     *         (for instance, if the Runnable was not in the queue already.)
13307     *
13308     * @see #post
13309     * @see #postDelayed
13310     * @see #postOnAnimation
13311     * @see #postOnAnimationDelayed
13312     */
13313    public boolean removeCallbacks(Runnable action) {
13314        if (action != null) {
13315            final AttachInfo attachInfo = mAttachInfo;
13316            if (attachInfo != null) {
13317                attachInfo.mHandler.removeCallbacks(action);
13318                attachInfo.mViewRootImpl.mChoreographer.removeCallbacks(
13319                        Choreographer.CALLBACK_ANIMATION, action, null);
13320            }
13321            getRunQueue().removeCallbacks(action);
13322        }
13323        return true;
13324    }
13325
13326    /**
13327     * <p>Cause an invalidate to happen on a subsequent cycle through the event loop.
13328     * Use this to invalidate the View from a non-UI thread.</p>
13329     *
13330     * <p>This method can be invoked from outside of the UI thread
13331     * only when this View is attached to a window.</p>
13332     *
13333     * @see #invalidate()
13334     * @see #postInvalidateDelayed(long)
13335     */
13336    public void postInvalidate() {
13337        postInvalidateDelayed(0);
13338    }
13339
13340    /**
13341     * <p>Cause an invalidate of the specified area to happen on a subsequent cycle
13342     * through the event loop. Use this to invalidate the View from a non-UI thread.</p>
13343     *
13344     * <p>This method can be invoked from outside of the UI thread
13345     * only when this View is attached to a window.</p>
13346     *
13347     * @param left The left coordinate of the rectangle to invalidate.
13348     * @param top The top coordinate of the rectangle to invalidate.
13349     * @param right The right coordinate of the rectangle to invalidate.
13350     * @param bottom The bottom coordinate of the rectangle to invalidate.
13351     *
13352     * @see #invalidate(int, int, int, int)
13353     * @see #invalidate(Rect)
13354     * @see #postInvalidateDelayed(long, int, int, int, int)
13355     */
13356    public void postInvalidate(int left, int top, int right, int bottom) {
13357        postInvalidateDelayed(0, left, top, right, bottom);
13358    }
13359
13360    /**
13361     * <p>Cause an invalidate to happen on a subsequent cycle through the event
13362     * loop. Waits for the specified amount of time.</p>
13363     *
13364     * <p>This method can be invoked from outside of the UI thread
13365     * only when this View is attached to a window.</p>
13366     *
13367     * @param delayMilliseconds the duration in milliseconds to delay the
13368     *         invalidation by
13369     *
13370     * @see #invalidate()
13371     * @see #postInvalidate()
13372     */
13373    public void postInvalidateDelayed(long delayMilliseconds) {
13374        // We try only with the AttachInfo because there's no point in invalidating
13375        // if we are not attached to our window
13376        final AttachInfo attachInfo = mAttachInfo;
13377        if (attachInfo != null) {
13378            attachInfo.mViewRootImpl.dispatchInvalidateDelayed(this, delayMilliseconds);
13379        }
13380    }
13381
13382    /**
13383     * <p>Cause an invalidate of the specified area to happen on a subsequent cycle
13384     * through the event loop. Waits for the specified amount of time.</p>
13385     *
13386     * <p>This method can be invoked from outside of the UI thread
13387     * only when this View is attached to a window.</p>
13388     *
13389     * @param delayMilliseconds the duration in milliseconds to delay the
13390     *         invalidation by
13391     * @param left The left coordinate of the rectangle to invalidate.
13392     * @param top The top coordinate of the rectangle to invalidate.
13393     * @param right The right coordinate of the rectangle to invalidate.
13394     * @param bottom The bottom coordinate of the rectangle to invalidate.
13395     *
13396     * @see #invalidate(int, int, int, int)
13397     * @see #invalidate(Rect)
13398     * @see #postInvalidate(int, int, int, int)
13399     */
13400    public void postInvalidateDelayed(long delayMilliseconds, int left, int top,
13401            int right, int bottom) {
13402
13403        // We try only with the AttachInfo because there's no point in invalidating
13404        // if we are not attached to our window
13405        final AttachInfo attachInfo = mAttachInfo;
13406        if (attachInfo != null) {
13407            final AttachInfo.InvalidateInfo info = AttachInfo.InvalidateInfo.obtain();
13408            info.target = this;
13409            info.left = left;
13410            info.top = top;
13411            info.right = right;
13412            info.bottom = bottom;
13413
13414            attachInfo.mViewRootImpl.dispatchInvalidateRectDelayed(info, delayMilliseconds);
13415        }
13416    }
13417
13418    /**
13419     * <p>Cause an invalidate to happen on the next animation time step, typically the
13420     * next display frame.</p>
13421     *
13422     * <p>This method can be invoked from outside of the UI thread
13423     * only when this View is attached to a window.</p>
13424     *
13425     * @see #invalidate()
13426     */
13427    public void postInvalidateOnAnimation() {
13428        // We try only with the AttachInfo because there's no point in invalidating
13429        // if we are not attached to our window
13430        final AttachInfo attachInfo = mAttachInfo;
13431        if (attachInfo != null) {
13432            attachInfo.mViewRootImpl.dispatchInvalidateOnAnimation(this);
13433        }
13434    }
13435
13436    /**
13437     * <p>Cause an invalidate of the specified area to happen on the next animation
13438     * time step, typically the next display frame.</p>
13439     *
13440     * <p>This method can be invoked from outside of the UI thread
13441     * only when this View is attached to a window.</p>
13442     *
13443     * @param left The left coordinate of the rectangle to invalidate.
13444     * @param top The top coordinate of the rectangle to invalidate.
13445     * @param right The right coordinate of the rectangle to invalidate.
13446     * @param bottom The bottom coordinate of the rectangle to invalidate.
13447     *
13448     * @see #invalidate(int, int, int, int)
13449     * @see #invalidate(Rect)
13450     */
13451    public void postInvalidateOnAnimation(int left, int top, int right, int bottom) {
13452        // We try only with the AttachInfo because there's no point in invalidating
13453        // if we are not attached to our window
13454        final AttachInfo attachInfo = mAttachInfo;
13455        if (attachInfo != null) {
13456            final AttachInfo.InvalidateInfo info = AttachInfo.InvalidateInfo.obtain();
13457            info.target = this;
13458            info.left = left;
13459            info.top = top;
13460            info.right = right;
13461            info.bottom = bottom;
13462
13463            attachInfo.mViewRootImpl.dispatchInvalidateRectOnAnimation(info);
13464        }
13465    }
13466
13467    /**
13468     * Post a callback to send a {@link AccessibilityEvent#TYPE_VIEW_SCROLLED} event.
13469     * This event is sent at most once every
13470     * {@link ViewConfiguration#getSendRecurringAccessibilityEventsInterval()}.
13471     */
13472    private void postSendViewScrolledAccessibilityEventCallback() {
13473        if (mSendViewScrolledAccessibilityEvent == null) {
13474            mSendViewScrolledAccessibilityEvent = new SendViewScrolledAccessibilityEvent();
13475        }
13476        if (!mSendViewScrolledAccessibilityEvent.mIsPending) {
13477            mSendViewScrolledAccessibilityEvent.mIsPending = true;
13478            postDelayed(mSendViewScrolledAccessibilityEvent,
13479                    ViewConfiguration.getSendRecurringAccessibilityEventsInterval());
13480        }
13481    }
13482
13483    /**
13484     * Called by a parent to request that a child update its values for mScrollX
13485     * and mScrollY if necessary. This will typically be done if the child is
13486     * animating a scroll using a {@link android.widget.Scroller Scroller}
13487     * object.
13488     */
13489    public void computeScroll() {
13490    }
13491
13492    /**
13493     * <p>Indicate whether the horizontal edges are faded when the view is
13494     * scrolled horizontally.</p>
13495     *
13496     * @return true if the horizontal edges should are faded on scroll, false
13497     *         otherwise
13498     *
13499     * @see #setHorizontalFadingEdgeEnabled(boolean)
13500     *
13501     * @attr ref android.R.styleable#View_requiresFadingEdge
13502     */
13503    public boolean isHorizontalFadingEdgeEnabled() {
13504        return (mViewFlags & FADING_EDGE_HORIZONTAL) == FADING_EDGE_HORIZONTAL;
13505    }
13506
13507    /**
13508     * <p>Define whether the horizontal edges should be faded when this view
13509     * is scrolled horizontally.</p>
13510     *
13511     * @param horizontalFadingEdgeEnabled true if the horizontal edges should
13512     *                                    be faded when the view is scrolled
13513     *                                    horizontally
13514     *
13515     * @see #isHorizontalFadingEdgeEnabled()
13516     *
13517     * @attr ref android.R.styleable#View_requiresFadingEdge
13518     */
13519    public void setHorizontalFadingEdgeEnabled(boolean horizontalFadingEdgeEnabled) {
13520        if (isHorizontalFadingEdgeEnabled() != horizontalFadingEdgeEnabled) {
13521            if (horizontalFadingEdgeEnabled) {
13522                initScrollCache();
13523            }
13524
13525            mViewFlags ^= FADING_EDGE_HORIZONTAL;
13526        }
13527    }
13528
13529    /**
13530     * <p>Indicate whether the vertical edges are faded when the view is
13531     * scrolled horizontally.</p>
13532     *
13533     * @return true if the vertical edges should are faded on scroll, false
13534     *         otherwise
13535     *
13536     * @see #setVerticalFadingEdgeEnabled(boolean)
13537     *
13538     * @attr ref android.R.styleable#View_requiresFadingEdge
13539     */
13540    public boolean isVerticalFadingEdgeEnabled() {
13541        return (mViewFlags & FADING_EDGE_VERTICAL) == FADING_EDGE_VERTICAL;
13542    }
13543
13544    /**
13545     * <p>Define whether the vertical edges should be faded when this view
13546     * is scrolled vertically.</p>
13547     *
13548     * @param verticalFadingEdgeEnabled true if the vertical edges should
13549     *                                  be faded when the view is scrolled
13550     *                                  vertically
13551     *
13552     * @see #isVerticalFadingEdgeEnabled()
13553     *
13554     * @attr ref android.R.styleable#View_requiresFadingEdge
13555     */
13556    public void setVerticalFadingEdgeEnabled(boolean verticalFadingEdgeEnabled) {
13557        if (isVerticalFadingEdgeEnabled() != verticalFadingEdgeEnabled) {
13558            if (verticalFadingEdgeEnabled) {
13559                initScrollCache();
13560            }
13561
13562            mViewFlags ^= FADING_EDGE_VERTICAL;
13563        }
13564    }
13565
13566    /**
13567     * Returns the strength, or intensity, of the top faded edge. The strength is
13568     * a value between 0.0 (no fade) and 1.0 (full fade). The default implementation
13569     * returns 0.0 or 1.0 but no value in between.
13570     *
13571     * Subclasses should override this method to provide a smoother fade transition
13572     * when scrolling occurs.
13573     *
13574     * @return the intensity of the top fade as a float between 0.0f and 1.0f
13575     */
13576    protected float getTopFadingEdgeStrength() {
13577        return computeVerticalScrollOffset() > 0 ? 1.0f : 0.0f;
13578    }
13579
13580    /**
13581     * Returns the strength, or intensity, of the bottom faded edge. The strength is
13582     * a value between 0.0 (no fade) and 1.0 (full fade). The default implementation
13583     * returns 0.0 or 1.0 but no value in between.
13584     *
13585     * Subclasses should override this method to provide a smoother fade transition
13586     * when scrolling occurs.
13587     *
13588     * @return the intensity of the bottom fade as a float between 0.0f and 1.0f
13589     */
13590    protected float getBottomFadingEdgeStrength() {
13591        return computeVerticalScrollOffset() + computeVerticalScrollExtent() <
13592                computeVerticalScrollRange() ? 1.0f : 0.0f;
13593    }
13594
13595    /**
13596     * Returns the strength, or intensity, of the left faded edge. The strength is
13597     * a value between 0.0 (no fade) and 1.0 (full fade). The default implementation
13598     * returns 0.0 or 1.0 but no value in between.
13599     *
13600     * Subclasses should override this method to provide a smoother fade transition
13601     * when scrolling occurs.
13602     *
13603     * @return the intensity of the left fade as a float between 0.0f and 1.0f
13604     */
13605    protected float getLeftFadingEdgeStrength() {
13606        return computeHorizontalScrollOffset() > 0 ? 1.0f : 0.0f;
13607    }
13608
13609    /**
13610     * Returns the strength, or intensity, of the right faded edge. The strength is
13611     * a value between 0.0 (no fade) and 1.0 (full fade). The default implementation
13612     * returns 0.0 or 1.0 but no value in between.
13613     *
13614     * Subclasses should override this method to provide a smoother fade transition
13615     * when scrolling occurs.
13616     *
13617     * @return the intensity of the right fade as a float between 0.0f and 1.0f
13618     */
13619    protected float getRightFadingEdgeStrength() {
13620        return computeHorizontalScrollOffset() + computeHorizontalScrollExtent() <
13621                computeHorizontalScrollRange() ? 1.0f : 0.0f;
13622    }
13623
13624    /**
13625     * <p>Indicate whether the horizontal scrollbar should be drawn or not. The
13626     * scrollbar is not drawn by default.</p>
13627     *
13628     * @return true if the horizontal scrollbar should be painted, false
13629     *         otherwise
13630     *
13631     * @see #setHorizontalScrollBarEnabled(boolean)
13632     */
13633    public boolean isHorizontalScrollBarEnabled() {
13634        return (mViewFlags & SCROLLBARS_HORIZONTAL) == SCROLLBARS_HORIZONTAL;
13635    }
13636
13637    /**
13638     * <p>Define whether the horizontal scrollbar should be drawn or not. The
13639     * scrollbar is not drawn by default.</p>
13640     *
13641     * @param horizontalScrollBarEnabled true if the horizontal scrollbar should
13642     *                                   be painted
13643     *
13644     * @see #isHorizontalScrollBarEnabled()
13645     */
13646    public void setHorizontalScrollBarEnabled(boolean horizontalScrollBarEnabled) {
13647        if (isHorizontalScrollBarEnabled() != horizontalScrollBarEnabled) {
13648            mViewFlags ^= SCROLLBARS_HORIZONTAL;
13649            computeOpaqueFlags();
13650            resolvePadding();
13651        }
13652    }
13653
13654    /**
13655     * <p>Indicate whether the vertical scrollbar should be drawn or not. The
13656     * scrollbar is not drawn by default.</p>
13657     *
13658     * @return true if the vertical scrollbar should be painted, false
13659     *         otherwise
13660     *
13661     * @see #setVerticalScrollBarEnabled(boolean)
13662     */
13663    public boolean isVerticalScrollBarEnabled() {
13664        return (mViewFlags & SCROLLBARS_VERTICAL) == SCROLLBARS_VERTICAL;
13665    }
13666
13667    /**
13668     * <p>Define whether the vertical scrollbar should be drawn or not. The
13669     * scrollbar is not drawn by default.</p>
13670     *
13671     * @param verticalScrollBarEnabled true if the vertical scrollbar should
13672     *                                 be painted
13673     *
13674     * @see #isVerticalScrollBarEnabled()
13675     */
13676    public void setVerticalScrollBarEnabled(boolean verticalScrollBarEnabled) {
13677        if (isVerticalScrollBarEnabled() != verticalScrollBarEnabled) {
13678            mViewFlags ^= SCROLLBARS_VERTICAL;
13679            computeOpaqueFlags();
13680            resolvePadding();
13681        }
13682    }
13683
13684    /**
13685     * @hide
13686     */
13687    protected void recomputePadding() {
13688        internalSetPadding(mUserPaddingLeft, mPaddingTop, mUserPaddingRight, mUserPaddingBottom);
13689    }
13690
13691    /**
13692     * Define whether scrollbars will fade when the view is not scrolling.
13693     *
13694     * @param fadeScrollbars whether to enable fading
13695     *
13696     * @attr ref android.R.styleable#View_fadeScrollbars
13697     */
13698    public void setScrollbarFadingEnabled(boolean fadeScrollbars) {
13699        initScrollCache();
13700        final ScrollabilityCache scrollabilityCache = mScrollCache;
13701        scrollabilityCache.fadeScrollBars = fadeScrollbars;
13702        if (fadeScrollbars) {
13703            scrollabilityCache.state = ScrollabilityCache.OFF;
13704        } else {
13705            scrollabilityCache.state = ScrollabilityCache.ON;
13706        }
13707    }
13708
13709    /**
13710     *
13711     * Returns true if scrollbars will fade when this view is not scrolling
13712     *
13713     * @return true if scrollbar fading is enabled
13714     *
13715     * @attr ref android.R.styleable#View_fadeScrollbars
13716     */
13717    public boolean isScrollbarFadingEnabled() {
13718        return mScrollCache != null && mScrollCache.fadeScrollBars;
13719    }
13720
13721    /**
13722     *
13723     * Returns the delay before scrollbars fade.
13724     *
13725     * @return the delay before scrollbars fade
13726     *
13727     * @attr ref android.R.styleable#View_scrollbarDefaultDelayBeforeFade
13728     */
13729    public int getScrollBarDefaultDelayBeforeFade() {
13730        return mScrollCache == null ? ViewConfiguration.getScrollDefaultDelay() :
13731                mScrollCache.scrollBarDefaultDelayBeforeFade;
13732    }
13733
13734    /**
13735     * Define the delay before scrollbars fade.
13736     *
13737     * @param scrollBarDefaultDelayBeforeFade - the delay before scrollbars fade
13738     *
13739     * @attr ref android.R.styleable#View_scrollbarDefaultDelayBeforeFade
13740     */
13741    public void setScrollBarDefaultDelayBeforeFade(int scrollBarDefaultDelayBeforeFade) {
13742        getScrollCache().scrollBarDefaultDelayBeforeFade = scrollBarDefaultDelayBeforeFade;
13743    }
13744
13745    /**
13746     *
13747     * Returns the scrollbar fade duration.
13748     *
13749     * @return the scrollbar fade duration
13750     *
13751     * @attr ref android.R.styleable#View_scrollbarFadeDuration
13752     */
13753    public int getScrollBarFadeDuration() {
13754        return mScrollCache == null ? ViewConfiguration.getScrollBarFadeDuration() :
13755                mScrollCache.scrollBarFadeDuration;
13756    }
13757
13758    /**
13759     * Define the scrollbar fade duration.
13760     *
13761     * @param scrollBarFadeDuration - the scrollbar fade duration
13762     *
13763     * @attr ref android.R.styleable#View_scrollbarFadeDuration
13764     */
13765    public void setScrollBarFadeDuration(int scrollBarFadeDuration) {
13766        getScrollCache().scrollBarFadeDuration = scrollBarFadeDuration;
13767    }
13768
13769    /**
13770     *
13771     * Returns the scrollbar size.
13772     *
13773     * @return the scrollbar size
13774     *
13775     * @attr ref android.R.styleable#View_scrollbarSize
13776     */
13777    public int getScrollBarSize() {
13778        return mScrollCache == null ? ViewConfiguration.get(mContext).getScaledScrollBarSize() :
13779                mScrollCache.scrollBarSize;
13780    }
13781
13782    /**
13783     * Define the scrollbar size.
13784     *
13785     * @param scrollBarSize - the scrollbar size
13786     *
13787     * @attr ref android.R.styleable#View_scrollbarSize
13788     */
13789    public void setScrollBarSize(int scrollBarSize) {
13790        getScrollCache().scrollBarSize = scrollBarSize;
13791    }
13792
13793    /**
13794     * <p>Specify the style of the scrollbars. The scrollbars can be overlaid or
13795     * inset. When inset, they add to the padding of the view. And the scrollbars
13796     * can be drawn inside the padding area or on the edge of the view. For example,
13797     * if a view has a background drawable and you want to draw the scrollbars
13798     * inside the padding specified by the drawable, you can use
13799     * SCROLLBARS_INSIDE_OVERLAY or SCROLLBARS_INSIDE_INSET. If you want them to
13800     * appear at the edge of the view, ignoring the padding, then you can use
13801     * SCROLLBARS_OUTSIDE_OVERLAY or SCROLLBARS_OUTSIDE_INSET.</p>
13802     * @param style the style of the scrollbars. Should be one of
13803     * SCROLLBARS_INSIDE_OVERLAY, SCROLLBARS_INSIDE_INSET,
13804     * SCROLLBARS_OUTSIDE_OVERLAY or SCROLLBARS_OUTSIDE_INSET.
13805     * @see #SCROLLBARS_INSIDE_OVERLAY
13806     * @see #SCROLLBARS_INSIDE_INSET
13807     * @see #SCROLLBARS_OUTSIDE_OVERLAY
13808     * @see #SCROLLBARS_OUTSIDE_INSET
13809     *
13810     * @attr ref android.R.styleable#View_scrollbarStyle
13811     */
13812    public void setScrollBarStyle(@ScrollBarStyle int style) {
13813        if (style != (mViewFlags & SCROLLBARS_STYLE_MASK)) {
13814            mViewFlags = (mViewFlags & ~SCROLLBARS_STYLE_MASK) | (style & SCROLLBARS_STYLE_MASK);
13815            computeOpaqueFlags();
13816            resolvePadding();
13817        }
13818    }
13819
13820    /**
13821     * <p>Returns the current scrollbar style.</p>
13822     * @return the current scrollbar style
13823     * @see #SCROLLBARS_INSIDE_OVERLAY
13824     * @see #SCROLLBARS_INSIDE_INSET
13825     * @see #SCROLLBARS_OUTSIDE_OVERLAY
13826     * @see #SCROLLBARS_OUTSIDE_INSET
13827     *
13828     * @attr ref android.R.styleable#View_scrollbarStyle
13829     */
13830    @ViewDebug.ExportedProperty(mapping = {
13831            @ViewDebug.IntToString(from = SCROLLBARS_INSIDE_OVERLAY, to = "INSIDE_OVERLAY"),
13832            @ViewDebug.IntToString(from = SCROLLBARS_INSIDE_INSET, to = "INSIDE_INSET"),
13833            @ViewDebug.IntToString(from = SCROLLBARS_OUTSIDE_OVERLAY, to = "OUTSIDE_OVERLAY"),
13834            @ViewDebug.IntToString(from = SCROLLBARS_OUTSIDE_INSET, to = "OUTSIDE_INSET")
13835    })
13836    @ScrollBarStyle
13837    public int getScrollBarStyle() {
13838        return mViewFlags & SCROLLBARS_STYLE_MASK;
13839    }
13840
13841    /**
13842     * <p>Compute the horizontal range that the horizontal scrollbar
13843     * represents.</p>
13844     *
13845     * <p>The range is expressed in arbitrary units that must be the same as the
13846     * units used by {@link #computeHorizontalScrollExtent()} and
13847     * {@link #computeHorizontalScrollOffset()}.</p>
13848     *
13849     * <p>The default range is the drawing width of this view.</p>
13850     *
13851     * @return the total horizontal range represented by the horizontal
13852     *         scrollbar
13853     *
13854     * @see #computeHorizontalScrollExtent()
13855     * @see #computeHorizontalScrollOffset()
13856     * @see android.widget.ScrollBarDrawable
13857     */
13858    protected int computeHorizontalScrollRange() {
13859        return getWidth();
13860    }
13861
13862    /**
13863     * <p>Compute the horizontal offset of the horizontal scrollbar's thumb
13864     * within the horizontal range. This value is used to compute the position
13865     * of the thumb within the scrollbar's track.</p>
13866     *
13867     * <p>The range is expressed in arbitrary units that must be the same as the
13868     * units used by {@link #computeHorizontalScrollRange()} and
13869     * {@link #computeHorizontalScrollExtent()}.</p>
13870     *
13871     * <p>The default offset is the scroll offset of this view.</p>
13872     *
13873     * @return the horizontal offset of the scrollbar's thumb
13874     *
13875     * @see #computeHorizontalScrollRange()
13876     * @see #computeHorizontalScrollExtent()
13877     * @see android.widget.ScrollBarDrawable
13878     */
13879    protected int computeHorizontalScrollOffset() {
13880        return mScrollX;
13881    }
13882
13883    /**
13884     * <p>Compute the horizontal extent of the horizontal scrollbar's thumb
13885     * within the horizontal range. This value is used to compute the length
13886     * of the thumb within the scrollbar's track.</p>
13887     *
13888     * <p>The range is expressed in arbitrary units that must be the same as the
13889     * units used by {@link #computeHorizontalScrollRange()} and
13890     * {@link #computeHorizontalScrollOffset()}.</p>
13891     *
13892     * <p>The default extent is the drawing width of this view.</p>
13893     *
13894     * @return the horizontal extent of the scrollbar's thumb
13895     *
13896     * @see #computeHorizontalScrollRange()
13897     * @see #computeHorizontalScrollOffset()
13898     * @see android.widget.ScrollBarDrawable
13899     */
13900    protected int computeHorizontalScrollExtent() {
13901        return getWidth();
13902    }
13903
13904    /**
13905     * <p>Compute the vertical range that the vertical scrollbar represents.</p>
13906     *
13907     * <p>The range is expressed in arbitrary units that must be the same as the
13908     * units used by {@link #computeVerticalScrollExtent()} and
13909     * {@link #computeVerticalScrollOffset()}.</p>
13910     *
13911     * @return the total vertical range represented by the vertical scrollbar
13912     *
13913     * <p>The default range is the drawing height of this view.</p>
13914     *
13915     * @see #computeVerticalScrollExtent()
13916     * @see #computeVerticalScrollOffset()
13917     * @see android.widget.ScrollBarDrawable
13918     */
13919    protected int computeVerticalScrollRange() {
13920        return getHeight();
13921    }
13922
13923    /**
13924     * <p>Compute the vertical offset of the vertical scrollbar's thumb
13925     * within the horizontal range. This value is used to compute the position
13926     * of the thumb within the scrollbar's track.</p>
13927     *
13928     * <p>The range is expressed in arbitrary units that must be the same as the
13929     * units used by {@link #computeVerticalScrollRange()} and
13930     * {@link #computeVerticalScrollExtent()}.</p>
13931     *
13932     * <p>The default offset is the scroll offset of this view.</p>
13933     *
13934     * @return the vertical offset of the scrollbar's thumb
13935     *
13936     * @see #computeVerticalScrollRange()
13937     * @see #computeVerticalScrollExtent()
13938     * @see android.widget.ScrollBarDrawable
13939     */
13940    protected int computeVerticalScrollOffset() {
13941        return mScrollY;
13942    }
13943
13944    /**
13945     * <p>Compute the vertical extent of the vertical scrollbar's thumb
13946     * within the vertical range. This value is used to compute the length
13947     * of the thumb within the scrollbar's track.</p>
13948     *
13949     * <p>The range is expressed in arbitrary units that must be the same as the
13950     * units used by {@link #computeVerticalScrollRange()} and
13951     * {@link #computeVerticalScrollOffset()}.</p>
13952     *
13953     * <p>The default extent is the drawing height of this view.</p>
13954     *
13955     * @return the vertical extent of the scrollbar's thumb
13956     *
13957     * @see #computeVerticalScrollRange()
13958     * @see #computeVerticalScrollOffset()
13959     * @see android.widget.ScrollBarDrawable
13960     */
13961    protected int computeVerticalScrollExtent() {
13962        return getHeight();
13963    }
13964
13965    /**
13966     * Check if this view can be scrolled horizontally in a certain direction.
13967     *
13968     * @param direction Negative to check scrolling left, positive to check scrolling right.
13969     * @return true if this view can be scrolled in the specified direction, false otherwise.
13970     */
13971    public boolean canScrollHorizontally(int direction) {
13972        final int offset = computeHorizontalScrollOffset();
13973        final int range = computeHorizontalScrollRange() - computeHorizontalScrollExtent();
13974        if (range == 0) return false;
13975        if (direction < 0) {
13976            return offset > 0;
13977        } else {
13978            return offset < range - 1;
13979        }
13980    }
13981
13982    /**
13983     * Check if this view can be scrolled vertically in a certain direction.
13984     *
13985     * @param direction Negative to check scrolling up, positive to check scrolling down.
13986     * @return true if this view can be scrolled in the specified direction, false otherwise.
13987     */
13988    public boolean canScrollVertically(int direction) {
13989        final int offset = computeVerticalScrollOffset();
13990        final int range = computeVerticalScrollRange() - computeVerticalScrollExtent();
13991        if (range == 0) return false;
13992        if (direction < 0) {
13993            return offset > 0;
13994        } else {
13995            return offset < range - 1;
13996        }
13997    }
13998
13999    void getScrollIndicatorBounds(@NonNull Rect out) {
14000        out.left = mScrollX;
14001        out.right = mScrollX + mRight - mLeft;
14002        out.top = mScrollY;
14003        out.bottom = mScrollY + mBottom - mTop;
14004    }
14005
14006    private void onDrawScrollIndicators(Canvas c) {
14007        if ((mPrivateFlags3 & SCROLL_INDICATORS_PFLAG3_MASK) == 0) {
14008            // No scroll indicators enabled.
14009            return;
14010        }
14011
14012        final Drawable dr = mScrollIndicatorDrawable;
14013        if (dr == null) {
14014            // Scroll indicators aren't supported here.
14015            return;
14016        }
14017
14018        final int h = dr.getIntrinsicHeight();
14019        final int w = dr.getIntrinsicWidth();
14020        final Rect rect = mAttachInfo.mTmpInvalRect;
14021        getScrollIndicatorBounds(rect);
14022
14023        if ((mPrivateFlags3 & PFLAG3_SCROLL_INDICATOR_TOP) != 0) {
14024            final boolean canScrollUp = canScrollVertically(-1);
14025            if (canScrollUp) {
14026                dr.setBounds(rect.left, rect.top, rect.right, rect.top + h);
14027                dr.draw(c);
14028            }
14029        }
14030
14031        if ((mPrivateFlags3 & PFLAG3_SCROLL_INDICATOR_BOTTOM) != 0) {
14032            final boolean canScrollDown = canScrollVertically(1);
14033            if (canScrollDown) {
14034                dr.setBounds(rect.left, rect.bottom - h, rect.right, rect.bottom);
14035                dr.draw(c);
14036            }
14037        }
14038
14039        final int leftRtl;
14040        final int rightRtl;
14041        if (getLayoutDirection() == LAYOUT_DIRECTION_RTL) {
14042            leftRtl = PFLAG3_SCROLL_INDICATOR_END;
14043            rightRtl = PFLAG3_SCROLL_INDICATOR_START;
14044        } else {
14045            leftRtl = PFLAG3_SCROLL_INDICATOR_START;
14046            rightRtl = PFLAG3_SCROLL_INDICATOR_END;
14047        }
14048
14049        final int leftMask = PFLAG3_SCROLL_INDICATOR_LEFT | leftRtl;
14050        if ((mPrivateFlags3 & leftMask) != 0) {
14051            final boolean canScrollLeft = canScrollHorizontally(-1);
14052            if (canScrollLeft) {
14053                dr.setBounds(rect.left, rect.top, rect.left + w, rect.bottom);
14054                dr.draw(c);
14055            }
14056        }
14057
14058        final int rightMask = PFLAG3_SCROLL_INDICATOR_RIGHT | rightRtl;
14059        if ((mPrivateFlags3 & rightMask) != 0) {
14060            final boolean canScrollRight = canScrollHorizontally(1);
14061            if (canScrollRight) {
14062                dr.setBounds(rect.right - w, rect.top, rect.right, rect.bottom);
14063                dr.draw(c);
14064            }
14065        }
14066    }
14067
14068    /**
14069     * <p>Request the drawing of the horizontal and the vertical scrollbar. The
14070     * scrollbars are painted only if they have been awakened first.</p>
14071     *
14072     * @param canvas the canvas on which to draw the scrollbars
14073     *
14074     * @see #awakenScrollBars(int)
14075     */
14076    protected final void onDrawScrollBars(Canvas canvas) {
14077        // scrollbars are drawn only when the animation is running
14078        final ScrollabilityCache cache = mScrollCache;
14079        if (cache != null) {
14080
14081            int state = cache.state;
14082
14083            if (state == ScrollabilityCache.OFF) {
14084                return;
14085            }
14086
14087            boolean invalidate = false;
14088
14089            if (state == ScrollabilityCache.FADING) {
14090                // We're fading -- get our fade interpolation
14091                if (cache.interpolatorValues == null) {
14092                    cache.interpolatorValues = new float[1];
14093                }
14094
14095                float[] values = cache.interpolatorValues;
14096
14097                // Stops the animation if we're done
14098                if (cache.scrollBarInterpolator.timeToValues(values) ==
14099                        Interpolator.Result.FREEZE_END) {
14100                    cache.state = ScrollabilityCache.OFF;
14101                } else {
14102                    cache.scrollBar.mutate().setAlpha(Math.round(values[0]));
14103                }
14104
14105                // This will make the scroll bars inval themselves after
14106                // drawing. We only want this when we're fading so that
14107                // we prevent excessive redraws
14108                invalidate = true;
14109            } else {
14110                // We're just on -- but we may have been fading before so
14111                // reset alpha
14112                cache.scrollBar.mutate().setAlpha(255);
14113            }
14114
14115
14116            final int viewFlags = mViewFlags;
14117
14118            final boolean drawHorizontalScrollBar =
14119                (viewFlags & SCROLLBARS_HORIZONTAL) == SCROLLBARS_HORIZONTAL;
14120            final boolean drawVerticalScrollBar =
14121                (viewFlags & SCROLLBARS_VERTICAL) == SCROLLBARS_VERTICAL
14122                && !isVerticalScrollBarHidden();
14123
14124            if (drawVerticalScrollBar || drawHorizontalScrollBar) {
14125                final int width = mRight - mLeft;
14126                final int height = mBottom - mTop;
14127
14128                final ScrollBarDrawable scrollBar = cache.scrollBar;
14129
14130                final int scrollX = mScrollX;
14131                final int scrollY = mScrollY;
14132                final int inside = (viewFlags & SCROLLBARS_OUTSIDE_MASK) == 0 ? ~0 : 0;
14133
14134                int left;
14135                int top;
14136                int right;
14137                int bottom;
14138
14139                if (drawHorizontalScrollBar) {
14140                    int size = scrollBar.getSize(false);
14141                    if (size <= 0) {
14142                        size = cache.scrollBarSize;
14143                    }
14144
14145                    scrollBar.setParameters(computeHorizontalScrollRange(),
14146                                            computeHorizontalScrollOffset(),
14147                                            computeHorizontalScrollExtent(), false);
14148                    final int verticalScrollBarGap = drawVerticalScrollBar ?
14149                            getVerticalScrollbarWidth() : 0;
14150                    top = scrollY + height - size - (mUserPaddingBottom & inside);
14151                    left = scrollX + (mPaddingLeft & inside);
14152                    right = scrollX + width - (mUserPaddingRight & inside) - verticalScrollBarGap;
14153                    bottom = top + size;
14154                    onDrawHorizontalScrollBar(canvas, scrollBar, left, top, right, bottom);
14155                    if (invalidate) {
14156                        invalidate(left, top, right, bottom);
14157                    }
14158                }
14159
14160                if (drawVerticalScrollBar) {
14161                    int size = scrollBar.getSize(true);
14162                    if (size <= 0) {
14163                        size = cache.scrollBarSize;
14164                    }
14165
14166                    scrollBar.setParameters(computeVerticalScrollRange(),
14167                                            computeVerticalScrollOffset(),
14168                                            computeVerticalScrollExtent(), true);
14169                    int verticalScrollbarPosition = mVerticalScrollbarPosition;
14170                    if (verticalScrollbarPosition == SCROLLBAR_POSITION_DEFAULT) {
14171                        verticalScrollbarPosition = isLayoutRtl() ?
14172                                SCROLLBAR_POSITION_LEFT : SCROLLBAR_POSITION_RIGHT;
14173                    }
14174                    switch (verticalScrollbarPosition) {
14175                        default:
14176                        case SCROLLBAR_POSITION_RIGHT:
14177                            left = scrollX + width - size - (mUserPaddingRight & inside);
14178                            break;
14179                        case SCROLLBAR_POSITION_LEFT:
14180                            left = scrollX + (mUserPaddingLeft & inside);
14181                            break;
14182                    }
14183                    top = scrollY + (mPaddingTop & inside);
14184                    right = left + size;
14185                    bottom = scrollY + height - (mUserPaddingBottom & inside);
14186                    onDrawVerticalScrollBar(canvas, scrollBar, left, top, right, bottom);
14187                    if (invalidate) {
14188                        invalidate(left, top, right, bottom);
14189                    }
14190                }
14191            }
14192        }
14193    }
14194
14195    /**
14196     * Override this if the vertical scrollbar needs to be hidden in a subclass, like when
14197     * FastScroller is visible.
14198     * @return whether to temporarily hide the vertical scrollbar
14199     * @hide
14200     */
14201    protected boolean isVerticalScrollBarHidden() {
14202        return false;
14203    }
14204
14205    /**
14206     * <p>Draw the horizontal scrollbar if
14207     * {@link #isHorizontalScrollBarEnabled()} returns true.</p>
14208     *
14209     * @param canvas the canvas on which to draw the scrollbar
14210     * @param scrollBar the scrollbar's drawable
14211     *
14212     * @see #isHorizontalScrollBarEnabled()
14213     * @see #computeHorizontalScrollRange()
14214     * @see #computeHorizontalScrollExtent()
14215     * @see #computeHorizontalScrollOffset()
14216     * @see android.widget.ScrollBarDrawable
14217     * @hide
14218     */
14219    protected void onDrawHorizontalScrollBar(Canvas canvas, Drawable scrollBar,
14220            int l, int t, int r, int b) {
14221        scrollBar.setBounds(l, t, r, b);
14222        scrollBar.draw(canvas);
14223    }
14224
14225    /**
14226     * <p>Draw the vertical scrollbar if {@link #isVerticalScrollBarEnabled()}
14227     * returns true.</p>
14228     *
14229     * @param canvas the canvas on which to draw the scrollbar
14230     * @param scrollBar the scrollbar's drawable
14231     *
14232     * @see #isVerticalScrollBarEnabled()
14233     * @see #computeVerticalScrollRange()
14234     * @see #computeVerticalScrollExtent()
14235     * @see #computeVerticalScrollOffset()
14236     * @see android.widget.ScrollBarDrawable
14237     * @hide
14238     */
14239    protected void onDrawVerticalScrollBar(Canvas canvas, Drawable scrollBar,
14240            int l, int t, int r, int b) {
14241        scrollBar.setBounds(l, t, r, b);
14242        scrollBar.draw(canvas);
14243    }
14244
14245    /**
14246     * Implement this to do your drawing.
14247     *
14248     * @param canvas the canvas on which the background will be drawn
14249     */
14250    protected void onDraw(Canvas canvas) {
14251    }
14252
14253    /*
14254     * Caller is responsible for calling requestLayout if necessary.
14255     * (This allows addViewInLayout to not request a new layout.)
14256     */
14257    void assignParent(ViewParent parent) {
14258        if (mParent == null) {
14259            mParent = parent;
14260        } else if (parent == null) {
14261            mParent = null;
14262        } else {
14263            throw new RuntimeException("view " + this + " being added, but"
14264                    + " it already has a parent");
14265        }
14266    }
14267
14268    /**
14269     * This is called when the view is attached to a window.  At this point it
14270     * has a Surface and will start drawing.  Note that this function is
14271     * guaranteed to be called before {@link #onDraw(android.graphics.Canvas)},
14272     * however it may be called any time before the first onDraw -- including
14273     * before or after {@link #onMeasure(int, int)}.
14274     *
14275     * @see #onDetachedFromWindow()
14276     */
14277    @CallSuper
14278    protected void onAttachedToWindow() {
14279        if ((mPrivateFlags & PFLAG_REQUEST_TRANSPARENT_REGIONS) != 0) {
14280            mParent.requestTransparentRegion(this);
14281        }
14282
14283        mPrivateFlags3 &= ~PFLAG3_IS_LAID_OUT;
14284
14285        jumpDrawablesToCurrentState();
14286
14287        resetSubtreeAccessibilityStateChanged();
14288
14289        // rebuild, since Outline not maintained while View is detached
14290        rebuildOutline();
14291
14292        if (isFocused()) {
14293            InputMethodManager imm = InputMethodManager.peekInstance();
14294            if (imm != null) {
14295                imm.focusIn(this);
14296            }
14297        }
14298    }
14299
14300    /**
14301     * Resolve all RTL related properties.
14302     *
14303     * @return true if resolution of RTL properties has been done
14304     *
14305     * @hide
14306     */
14307    public boolean resolveRtlPropertiesIfNeeded() {
14308        if (!needRtlPropertiesResolution()) return false;
14309
14310        // Order is important here: LayoutDirection MUST be resolved first
14311        if (!isLayoutDirectionResolved()) {
14312            resolveLayoutDirection();
14313            resolveLayoutParams();
14314        }
14315        // ... then we can resolve the others properties depending on the resolved LayoutDirection.
14316        if (!isTextDirectionResolved()) {
14317            resolveTextDirection();
14318        }
14319        if (!isTextAlignmentResolved()) {
14320            resolveTextAlignment();
14321        }
14322        // Should resolve Drawables before Padding because we need the layout direction of the
14323        // Drawable to correctly resolve Padding.
14324        if (!areDrawablesResolved()) {
14325            resolveDrawables();
14326        }
14327        if (!isPaddingResolved()) {
14328            resolvePadding();
14329        }
14330        onRtlPropertiesChanged(getLayoutDirection());
14331        return true;
14332    }
14333
14334    /**
14335     * Reset resolution of all RTL related properties.
14336     *
14337     * @hide
14338     */
14339    public void resetRtlProperties() {
14340        resetResolvedLayoutDirection();
14341        resetResolvedTextDirection();
14342        resetResolvedTextAlignment();
14343        resetResolvedPadding();
14344        resetResolvedDrawables();
14345    }
14346
14347    /**
14348     * @see #onScreenStateChanged(int)
14349     */
14350    void dispatchScreenStateChanged(int screenState) {
14351        onScreenStateChanged(screenState);
14352    }
14353
14354    /**
14355     * This method is called whenever the state of the screen this view is
14356     * attached to changes. A state change will usually occurs when the screen
14357     * turns on or off (whether it happens automatically or the user does it
14358     * manually.)
14359     *
14360     * @param screenState The new state of the screen. Can be either
14361     *                    {@link #SCREEN_STATE_ON} or {@link #SCREEN_STATE_OFF}
14362     */
14363    public void onScreenStateChanged(int screenState) {
14364    }
14365
14366    /**
14367     * Return true if the application tag in the AndroidManifest has set "supportRtl" to true
14368     */
14369    private boolean hasRtlSupport() {
14370        return mContext.getApplicationInfo().hasRtlSupport();
14371    }
14372
14373    /**
14374     * Return true if we are in RTL compatibility mode (either before Jelly Bean MR1 or
14375     * RTL not supported)
14376     */
14377    private boolean isRtlCompatibilityMode() {
14378        final int targetSdkVersion = getContext().getApplicationInfo().targetSdkVersion;
14379        return targetSdkVersion < JELLY_BEAN_MR1 || !hasRtlSupport();
14380    }
14381
14382    /**
14383     * @return true if RTL properties need resolution.
14384     *
14385     */
14386    private boolean needRtlPropertiesResolution() {
14387        return (mPrivateFlags2 & ALL_RTL_PROPERTIES_RESOLVED) != ALL_RTL_PROPERTIES_RESOLVED;
14388    }
14389
14390    /**
14391     * Called when any RTL property (layout direction or text direction or text alignment) has
14392     * been changed.
14393     *
14394     * Subclasses need to override this method to take care of cached information that depends on the
14395     * resolved layout direction, or to inform child views that inherit their layout direction.
14396     *
14397     * The default implementation does nothing.
14398     *
14399     * @param layoutDirection the direction of the layout
14400     *
14401     * @see #LAYOUT_DIRECTION_LTR
14402     * @see #LAYOUT_DIRECTION_RTL
14403     */
14404    public void onRtlPropertiesChanged(@ResolvedLayoutDir int layoutDirection) {
14405    }
14406
14407    /**
14408     * Resolve and cache the layout direction. LTR is set initially. This is implicitly supposing
14409     * that the parent directionality can and will be resolved before its children.
14410     *
14411     * @return true if resolution has been done, false otherwise.
14412     *
14413     * @hide
14414     */
14415    public boolean resolveLayoutDirection() {
14416        // Clear any previous layout direction resolution
14417        mPrivateFlags2 &= ~PFLAG2_LAYOUT_DIRECTION_RESOLVED_MASK;
14418
14419        if (hasRtlSupport()) {
14420            // Set resolved depending on layout direction
14421            switch ((mPrivateFlags2 & PFLAG2_LAYOUT_DIRECTION_MASK) >>
14422                    PFLAG2_LAYOUT_DIRECTION_MASK_SHIFT) {
14423                case LAYOUT_DIRECTION_INHERIT:
14424                    // We cannot resolve yet. LTR is by default and let the resolution happen again
14425                    // later to get the correct resolved value
14426                    if (!canResolveLayoutDirection()) return false;
14427
14428                    // Parent has not yet resolved, LTR is still the default
14429                    try {
14430                        if (!mParent.isLayoutDirectionResolved()) return false;
14431
14432                        if (mParent.getLayoutDirection() == LAYOUT_DIRECTION_RTL) {
14433                            mPrivateFlags2 |= PFLAG2_LAYOUT_DIRECTION_RESOLVED_RTL;
14434                        }
14435                    } catch (AbstractMethodError e) {
14436                        Log.e(VIEW_LOG_TAG, mParent.getClass().getSimpleName() +
14437                                " does not fully implement ViewParent", e);
14438                    }
14439                    break;
14440                case LAYOUT_DIRECTION_RTL:
14441                    mPrivateFlags2 |= PFLAG2_LAYOUT_DIRECTION_RESOLVED_RTL;
14442                    break;
14443                case LAYOUT_DIRECTION_LOCALE:
14444                    if((LAYOUT_DIRECTION_RTL ==
14445                            TextUtils.getLayoutDirectionFromLocale(Locale.getDefault()))) {
14446                        mPrivateFlags2 |= PFLAG2_LAYOUT_DIRECTION_RESOLVED_RTL;
14447                    }
14448                    break;
14449                default:
14450                    // Nothing to do, LTR by default
14451            }
14452        }
14453
14454        // Set to resolved
14455        mPrivateFlags2 |= PFLAG2_LAYOUT_DIRECTION_RESOLVED;
14456        return true;
14457    }
14458
14459    /**
14460     * Check if layout direction resolution can be done.
14461     *
14462     * @return true if layout direction resolution can be done otherwise return false.
14463     */
14464    public boolean canResolveLayoutDirection() {
14465        switch (getRawLayoutDirection()) {
14466            case LAYOUT_DIRECTION_INHERIT:
14467                if (mParent != null) {
14468                    try {
14469                        return mParent.canResolveLayoutDirection();
14470                    } catch (AbstractMethodError e) {
14471                        Log.e(VIEW_LOG_TAG, mParent.getClass().getSimpleName() +
14472                                " does not fully implement ViewParent", e);
14473                    }
14474                }
14475                return false;
14476
14477            default:
14478                return true;
14479        }
14480    }
14481
14482    /**
14483     * Reset the resolved layout direction. Layout direction will be resolved during a call to
14484     * {@link #onMeasure(int, int)}.
14485     *
14486     * @hide
14487     */
14488    public void resetResolvedLayoutDirection() {
14489        // Reset the current resolved bits
14490        mPrivateFlags2 &= ~PFLAG2_LAYOUT_DIRECTION_RESOLVED_MASK;
14491    }
14492
14493    /**
14494     * @return true if the layout direction is inherited.
14495     *
14496     * @hide
14497     */
14498    public boolean isLayoutDirectionInherited() {
14499        return (getRawLayoutDirection() == LAYOUT_DIRECTION_INHERIT);
14500    }
14501
14502    /**
14503     * @return true if layout direction has been resolved.
14504     */
14505    public boolean isLayoutDirectionResolved() {
14506        return (mPrivateFlags2 & PFLAG2_LAYOUT_DIRECTION_RESOLVED) == PFLAG2_LAYOUT_DIRECTION_RESOLVED;
14507    }
14508
14509    /**
14510     * Return if padding has been resolved
14511     *
14512     * @hide
14513     */
14514    boolean isPaddingResolved() {
14515        return (mPrivateFlags2 & PFLAG2_PADDING_RESOLVED) == PFLAG2_PADDING_RESOLVED;
14516    }
14517
14518    /**
14519     * Resolves padding depending on layout direction, if applicable, and
14520     * recomputes internal padding values to adjust for scroll bars.
14521     *
14522     * @hide
14523     */
14524    public void resolvePadding() {
14525        final int resolvedLayoutDirection = getLayoutDirection();
14526
14527        if (!isRtlCompatibilityMode()) {
14528            // Post Jelly Bean MR1 case: we need to take the resolved layout direction into account.
14529            // If start / end padding are defined, they will be resolved (hence overriding) to
14530            // left / right or right / left depending on the resolved layout direction.
14531            // If start / end padding are not defined, use the left / right ones.
14532            if (mBackground != null && (!mLeftPaddingDefined || !mRightPaddingDefined)) {
14533                Rect padding = sThreadLocal.get();
14534                if (padding == null) {
14535                    padding = new Rect();
14536                    sThreadLocal.set(padding);
14537                }
14538                mBackground.getPadding(padding);
14539                if (!mLeftPaddingDefined) {
14540                    mUserPaddingLeftInitial = padding.left;
14541                }
14542                if (!mRightPaddingDefined) {
14543                    mUserPaddingRightInitial = padding.right;
14544                }
14545            }
14546            switch (resolvedLayoutDirection) {
14547                case LAYOUT_DIRECTION_RTL:
14548                    if (mUserPaddingStart != UNDEFINED_PADDING) {
14549                        mUserPaddingRight = mUserPaddingStart;
14550                    } else {
14551                        mUserPaddingRight = mUserPaddingRightInitial;
14552                    }
14553                    if (mUserPaddingEnd != UNDEFINED_PADDING) {
14554                        mUserPaddingLeft = mUserPaddingEnd;
14555                    } else {
14556                        mUserPaddingLeft = mUserPaddingLeftInitial;
14557                    }
14558                    break;
14559                case LAYOUT_DIRECTION_LTR:
14560                default:
14561                    if (mUserPaddingStart != UNDEFINED_PADDING) {
14562                        mUserPaddingLeft = mUserPaddingStart;
14563                    } else {
14564                        mUserPaddingLeft = mUserPaddingLeftInitial;
14565                    }
14566                    if (mUserPaddingEnd != UNDEFINED_PADDING) {
14567                        mUserPaddingRight = mUserPaddingEnd;
14568                    } else {
14569                        mUserPaddingRight = mUserPaddingRightInitial;
14570                    }
14571            }
14572
14573            mUserPaddingBottom = (mUserPaddingBottom >= 0) ? mUserPaddingBottom : mPaddingBottom;
14574        }
14575
14576        internalSetPadding(mUserPaddingLeft, mPaddingTop, mUserPaddingRight, mUserPaddingBottom);
14577        onRtlPropertiesChanged(resolvedLayoutDirection);
14578
14579        mPrivateFlags2 |= PFLAG2_PADDING_RESOLVED;
14580    }
14581
14582    /**
14583     * Reset the resolved layout direction.
14584     *
14585     * @hide
14586     */
14587    public void resetResolvedPadding() {
14588        resetResolvedPaddingInternal();
14589    }
14590
14591    /**
14592     * Used when we only want to reset *this* view's padding and not trigger overrides
14593     * in ViewGroup that reset children too.
14594     */
14595    void resetResolvedPaddingInternal() {
14596        mPrivateFlags2 &= ~PFLAG2_PADDING_RESOLVED;
14597    }
14598
14599    /**
14600     * This is called when the view is detached from a window.  At this point it
14601     * no longer has a surface for drawing.
14602     *
14603     * @see #onAttachedToWindow()
14604     */
14605    @CallSuper
14606    protected void onDetachedFromWindow() {
14607    }
14608
14609    /**
14610     * This is a framework-internal mirror of onDetachedFromWindow() that's called
14611     * after onDetachedFromWindow().
14612     *
14613     * If you override this you *MUST* call super.onDetachedFromWindowInternal()!
14614     * The super method should be called at the end of the overridden method to ensure
14615     * subclasses are destroyed first
14616     *
14617     * @hide
14618     */
14619    @CallSuper
14620    protected void onDetachedFromWindowInternal() {
14621        mPrivateFlags &= ~PFLAG_CANCEL_NEXT_UP_EVENT;
14622        mPrivateFlags3 &= ~PFLAG3_IS_LAID_OUT;
14623
14624        removeUnsetPressCallback();
14625        removeLongPressCallback();
14626        removePerformClickCallback();
14627        removeSendViewScrolledAccessibilityEventCallback();
14628        stopNestedScroll();
14629
14630        // Anything that started animating right before detach should already
14631        // be in its final state when re-attached.
14632        jumpDrawablesToCurrentState();
14633
14634        destroyDrawingCache();
14635
14636        cleanupDraw();
14637        mCurrentAnimation = null;
14638    }
14639
14640    private void cleanupDraw() {
14641        resetDisplayList();
14642        if (mAttachInfo != null) {
14643            mAttachInfo.mViewRootImpl.cancelInvalidate(this);
14644        }
14645    }
14646
14647    void invalidateInheritedLayoutMode(int layoutModeOfRoot) {
14648    }
14649
14650    /**
14651     * @return The number of times this view has been attached to a window
14652     */
14653    protected int getWindowAttachCount() {
14654        return mWindowAttachCount;
14655    }
14656
14657    /**
14658     * Retrieve a unique token identifying the window this view is attached to.
14659     * @return Return the window's token for use in
14660     * {@link WindowManager.LayoutParams#token WindowManager.LayoutParams.token}.
14661     */
14662    public IBinder getWindowToken() {
14663        return mAttachInfo != null ? mAttachInfo.mWindowToken : null;
14664    }
14665
14666    /**
14667     * Retrieve the {@link WindowId} for the window this view is
14668     * currently attached to.
14669     */
14670    public WindowId getWindowId() {
14671        if (mAttachInfo == null) {
14672            return null;
14673        }
14674        if (mAttachInfo.mWindowId == null) {
14675            try {
14676                mAttachInfo.mIWindowId = mAttachInfo.mSession.getWindowId(
14677                        mAttachInfo.mWindowToken);
14678                mAttachInfo.mWindowId = new WindowId(
14679                        mAttachInfo.mIWindowId);
14680            } catch (RemoteException e) {
14681            }
14682        }
14683        return mAttachInfo.mWindowId;
14684    }
14685
14686    /**
14687     * Retrieve a unique token identifying the top-level "real" window of
14688     * the window that this view is attached to.  That is, this is like
14689     * {@link #getWindowToken}, except if the window this view in is a panel
14690     * window (attached to another containing window), then the token of
14691     * the containing window is returned instead.
14692     *
14693     * @return Returns the associated window token, either
14694     * {@link #getWindowToken()} or the containing window's token.
14695     */
14696    public IBinder getApplicationWindowToken() {
14697        AttachInfo ai = mAttachInfo;
14698        if (ai != null) {
14699            IBinder appWindowToken = ai.mPanelParentWindowToken;
14700            if (appWindowToken == null) {
14701                appWindowToken = ai.mWindowToken;
14702            }
14703            return appWindowToken;
14704        }
14705        return null;
14706    }
14707
14708    /**
14709     * Gets the logical display to which the view's window has been attached.
14710     *
14711     * @return The logical display, or null if the view is not currently attached to a window.
14712     */
14713    public Display getDisplay() {
14714        return mAttachInfo != null ? mAttachInfo.mDisplay : null;
14715    }
14716
14717    /**
14718     * Retrieve private session object this view hierarchy is using to
14719     * communicate with the window manager.
14720     * @return the session object to communicate with the window manager
14721     */
14722    /*package*/ IWindowSession getWindowSession() {
14723        return mAttachInfo != null ? mAttachInfo.mSession : null;
14724    }
14725
14726    /**
14727     * Return the visibility value of the least visible component passed.
14728     */
14729    int combineVisibility(int vis1, int vis2) {
14730        // This works because VISIBLE < INVISIBLE < GONE.
14731        return Math.max(vis1, vis2);
14732    }
14733
14734    /**
14735     * @param info the {@link android.view.View.AttachInfo} to associated with
14736     *        this view
14737     */
14738    void dispatchAttachedToWindow(AttachInfo info, int visibility) {
14739        mAttachInfo = info;
14740        if (mOverlay != null) {
14741            mOverlay.getOverlayView().dispatchAttachedToWindow(info, visibility);
14742        }
14743        mWindowAttachCount++;
14744        // We will need to evaluate the drawable state at least once.
14745        mPrivateFlags |= PFLAG_DRAWABLE_STATE_DIRTY;
14746        if (mFloatingTreeObserver != null) {
14747            info.mTreeObserver.merge(mFloatingTreeObserver);
14748            mFloatingTreeObserver = null;
14749        }
14750        if ((mPrivateFlags&PFLAG_SCROLL_CONTAINER) != 0) {
14751            mAttachInfo.mScrollContainers.add(this);
14752            mPrivateFlags |= PFLAG_SCROLL_CONTAINER_ADDED;
14753        }
14754        // Transfer all pending runnables.
14755        if (mRunQueue != null) {
14756            mRunQueue.executeActions(info.mHandler);
14757            mRunQueue = null;
14758        }
14759        performCollectViewAttributes(mAttachInfo, visibility);
14760        onAttachedToWindow();
14761
14762        ListenerInfo li = mListenerInfo;
14763        final CopyOnWriteArrayList<OnAttachStateChangeListener> listeners =
14764                li != null ? li.mOnAttachStateChangeListeners : null;
14765        if (listeners != null && listeners.size() > 0) {
14766            // NOTE: because of the use of CopyOnWriteArrayList, we *must* use an iterator to
14767            // perform the dispatching. The iterator is a safe guard against listeners that
14768            // could mutate the list by calling the various add/remove methods. This prevents
14769            // the array from being modified while we iterate it.
14770            for (OnAttachStateChangeListener listener : listeners) {
14771                listener.onViewAttachedToWindow(this);
14772            }
14773        }
14774
14775        int vis = info.mWindowVisibility;
14776        if (vis != GONE) {
14777            onWindowVisibilityChanged(vis);
14778        }
14779
14780        // Send onVisibilityChanged directly instead of dispatchVisibilityChanged.
14781        // As all views in the subtree will already receive dispatchAttachedToWindow
14782        // traversing the subtree again here is not desired.
14783        onVisibilityChanged(this, visibility);
14784
14785        if ((mPrivateFlags&PFLAG_DRAWABLE_STATE_DIRTY) != 0) {
14786            // If nobody has evaluated the drawable state yet, then do it now.
14787            refreshDrawableState();
14788        }
14789        needGlobalAttributesUpdate(false);
14790    }
14791
14792    void dispatchDetachedFromWindow() {
14793        AttachInfo info = mAttachInfo;
14794        if (info != null) {
14795            int vis = info.mWindowVisibility;
14796            if (vis != GONE) {
14797                onWindowVisibilityChanged(GONE);
14798            }
14799        }
14800
14801        onDetachedFromWindow();
14802        onDetachedFromWindowInternal();
14803
14804        InputMethodManager imm = InputMethodManager.peekInstance();
14805        if (imm != null) {
14806            imm.onViewDetachedFromWindow(this);
14807        }
14808
14809        ListenerInfo li = mListenerInfo;
14810        final CopyOnWriteArrayList<OnAttachStateChangeListener> listeners =
14811                li != null ? li.mOnAttachStateChangeListeners : null;
14812        if (listeners != null && listeners.size() > 0) {
14813            // NOTE: because of the use of CopyOnWriteArrayList, we *must* use an iterator to
14814            // perform the dispatching. The iterator is a safe guard against listeners that
14815            // could mutate the list by calling the various add/remove methods. This prevents
14816            // the array from being modified while we iterate it.
14817            for (OnAttachStateChangeListener listener : listeners) {
14818                listener.onViewDetachedFromWindow(this);
14819            }
14820        }
14821
14822        if ((mPrivateFlags & PFLAG_SCROLL_CONTAINER_ADDED) != 0) {
14823            mAttachInfo.mScrollContainers.remove(this);
14824            mPrivateFlags &= ~PFLAG_SCROLL_CONTAINER_ADDED;
14825        }
14826
14827        mAttachInfo = null;
14828        if (mOverlay != null) {
14829            mOverlay.getOverlayView().dispatchDetachedFromWindow();
14830        }
14831    }
14832
14833    /**
14834     * Cancel any deferred high-level input events that were previously posted to the event queue.
14835     *
14836     * <p>Many views post high-level events such as click handlers to the event queue
14837     * to run deferred in order to preserve a desired user experience - clearing visible
14838     * pressed states before executing, etc. This method will abort any events of this nature
14839     * that are currently in flight.</p>
14840     *
14841     * <p>Custom views that generate their own high-level deferred input events should override
14842     * {@link #onCancelPendingInputEvents()} and remove those pending events from the queue.</p>
14843     *
14844     * <p>This will also cancel pending input events for any child views.</p>
14845     *
14846     * <p>Note that this may not be sufficient as a debouncing strategy for clicks in all cases.
14847     * This will not impact newer events posted after this call that may occur as a result of
14848     * lower-level input events still waiting in the queue. If you are trying to prevent
14849     * double-submitted  events for the duration of some sort of asynchronous transaction
14850     * you should also take other steps to protect against unexpected double inputs e.g. calling
14851     * {@link #setEnabled(boolean) setEnabled(false)} and re-enabling the view when
14852     * the transaction completes, tracking already submitted transaction IDs, etc.</p>
14853     */
14854    public final void cancelPendingInputEvents() {
14855        dispatchCancelPendingInputEvents();
14856    }
14857
14858    /**
14859     * Called by {@link #cancelPendingInputEvents()} to cancel input events in flight.
14860     * Overridden by ViewGroup to dispatch. Package scoped to prevent app-side meddling.
14861     */
14862    void dispatchCancelPendingInputEvents() {
14863        mPrivateFlags3 &= ~PFLAG3_CALLED_SUPER;
14864        onCancelPendingInputEvents();
14865        if ((mPrivateFlags3 & PFLAG3_CALLED_SUPER) != PFLAG3_CALLED_SUPER) {
14866            throw new SuperNotCalledException("View " + getClass().getSimpleName() +
14867                    " did not call through to super.onCancelPendingInputEvents()");
14868        }
14869    }
14870
14871    /**
14872     * Called as the result of a call to {@link #cancelPendingInputEvents()} on this view or
14873     * a parent view.
14874     *
14875     * <p>This method is responsible for removing any pending high-level input events that were
14876     * posted to the event queue to run later. Custom view classes that post their own deferred
14877     * high-level events via {@link #post(Runnable)}, {@link #postDelayed(Runnable, long)} or
14878     * {@link android.os.Handler} should override this method, call
14879     * <code>super.onCancelPendingInputEvents()</code> and remove those callbacks as appropriate.
14880     * </p>
14881     */
14882    public void onCancelPendingInputEvents() {
14883        removePerformClickCallback();
14884        cancelLongPress();
14885        mPrivateFlags3 |= PFLAG3_CALLED_SUPER;
14886    }
14887
14888    /**
14889     * Store this view hierarchy's frozen state into the given container.
14890     *
14891     * @param container The SparseArray in which to save the view's state.
14892     *
14893     * @see #restoreHierarchyState(android.util.SparseArray)
14894     * @see #dispatchSaveInstanceState(android.util.SparseArray)
14895     * @see #onSaveInstanceState()
14896     */
14897    public void saveHierarchyState(SparseArray<Parcelable> container) {
14898        dispatchSaveInstanceState(container);
14899    }
14900
14901    /**
14902     * Called by {@link #saveHierarchyState(android.util.SparseArray)} to store the state for
14903     * this view and its children. May be overridden to modify how freezing happens to a
14904     * view's children; for example, some views may want to not store state for their children.
14905     *
14906     * @param container The SparseArray in which to save the view's state.
14907     *
14908     * @see #dispatchRestoreInstanceState(android.util.SparseArray)
14909     * @see #saveHierarchyState(android.util.SparseArray)
14910     * @see #onSaveInstanceState()
14911     */
14912    protected void dispatchSaveInstanceState(SparseArray<Parcelable> container) {
14913        if (mID != NO_ID && (mViewFlags & SAVE_DISABLED_MASK) == 0) {
14914            mPrivateFlags &= ~PFLAG_SAVE_STATE_CALLED;
14915            Parcelable state = onSaveInstanceState();
14916            if ((mPrivateFlags & PFLAG_SAVE_STATE_CALLED) == 0) {
14917                throw new IllegalStateException(
14918                        "Derived class did not call super.onSaveInstanceState()");
14919            }
14920            if (state != null) {
14921                // Log.i("View", "Freezing #" + Integer.toHexString(mID)
14922                // + ": " + state);
14923                container.put(mID, state);
14924            }
14925        }
14926    }
14927
14928    /**
14929     * Hook allowing a view to generate a representation of its internal state
14930     * that can later be used to create a new instance with that same state.
14931     * This state should only contain information that is not persistent or can
14932     * not be reconstructed later. For example, you will never store your
14933     * current position on screen because that will be computed again when a
14934     * new instance of the view is placed in its view hierarchy.
14935     * <p>
14936     * Some examples of things you may store here: the current cursor position
14937     * in a text view (but usually not the text itself since that is stored in a
14938     * content provider or other persistent storage), the currently selected
14939     * item in a list view.
14940     *
14941     * @return Returns a Parcelable object containing the view's current dynamic
14942     *         state, or null if there is nothing interesting to save. The
14943     *         default implementation returns null.
14944     * @see #onRestoreInstanceState(android.os.Parcelable)
14945     * @see #saveHierarchyState(android.util.SparseArray)
14946     * @see #dispatchSaveInstanceState(android.util.SparseArray)
14947     * @see #setSaveEnabled(boolean)
14948     */
14949    @CallSuper
14950    protected Parcelable onSaveInstanceState() {
14951        mPrivateFlags |= PFLAG_SAVE_STATE_CALLED;
14952        if (mStartActivityRequestWho != null) {
14953            BaseSavedState state = new BaseSavedState(AbsSavedState.EMPTY_STATE);
14954            state.mStartActivityRequestWhoSaved = mStartActivityRequestWho;
14955            return state;
14956        }
14957        return BaseSavedState.EMPTY_STATE;
14958    }
14959
14960    /**
14961     * Restore this view hierarchy's frozen state from the given container.
14962     *
14963     * @param container The SparseArray which holds previously frozen states.
14964     *
14965     * @see #saveHierarchyState(android.util.SparseArray)
14966     * @see #dispatchRestoreInstanceState(android.util.SparseArray)
14967     * @see #onRestoreInstanceState(android.os.Parcelable)
14968     */
14969    public void restoreHierarchyState(SparseArray<Parcelable> container) {
14970        dispatchRestoreInstanceState(container);
14971    }
14972
14973    /**
14974     * Called by {@link #restoreHierarchyState(android.util.SparseArray)} to retrieve the
14975     * state for this view and its children. May be overridden to modify how restoring
14976     * happens to a view's children; for example, some views may want to not store state
14977     * for their children.
14978     *
14979     * @param container The SparseArray which holds previously saved state.
14980     *
14981     * @see #dispatchSaveInstanceState(android.util.SparseArray)
14982     * @see #restoreHierarchyState(android.util.SparseArray)
14983     * @see #onRestoreInstanceState(android.os.Parcelable)
14984     */
14985    protected void dispatchRestoreInstanceState(SparseArray<Parcelable> container) {
14986        if (mID != NO_ID) {
14987            Parcelable state = container.get(mID);
14988            if (state != null) {
14989                // Log.i("View", "Restoreing #" + Integer.toHexString(mID)
14990                // + ": " + state);
14991                mPrivateFlags &= ~PFLAG_SAVE_STATE_CALLED;
14992                onRestoreInstanceState(state);
14993                if ((mPrivateFlags & PFLAG_SAVE_STATE_CALLED) == 0) {
14994                    throw new IllegalStateException(
14995                            "Derived class did not call super.onRestoreInstanceState()");
14996                }
14997            }
14998        }
14999    }
15000
15001    /**
15002     * Hook allowing a view to re-apply a representation of its internal state that had previously
15003     * been generated by {@link #onSaveInstanceState}. This function will never be called with a
15004     * null state.
15005     *
15006     * @param state The frozen state that had previously been returned by
15007     *        {@link #onSaveInstanceState}.
15008     *
15009     * @see #onSaveInstanceState()
15010     * @see #restoreHierarchyState(android.util.SparseArray)
15011     * @see #dispatchRestoreInstanceState(android.util.SparseArray)
15012     */
15013    @CallSuper
15014    protected void onRestoreInstanceState(Parcelable state) {
15015        mPrivateFlags |= PFLAG_SAVE_STATE_CALLED;
15016        if (state != null && !(state instanceof AbsSavedState)) {
15017            throw new IllegalArgumentException("Wrong state class, expecting View State but "
15018                    + "received " + state.getClass().toString() + " instead. This usually happens "
15019                    + "when two views of different type have the same id in the same hierarchy. "
15020                    + "This view's id is " + ViewDebug.resolveId(mContext, getId()) + ". Make sure "
15021                    + "other views do not use the same id.");
15022        }
15023        if (state != null && state instanceof BaseSavedState) {
15024            mStartActivityRequestWho = ((BaseSavedState) state).mStartActivityRequestWhoSaved;
15025        }
15026    }
15027
15028    /**
15029     * <p>Return the time at which the drawing of the view hierarchy started.</p>
15030     *
15031     * @return the drawing start time in milliseconds
15032     */
15033    public long getDrawingTime() {
15034        return mAttachInfo != null ? mAttachInfo.mDrawingTime : 0;
15035    }
15036
15037    /**
15038     * <p>Enables or disables the duplication of the parent's state into this view. When
15039     * duplication is enabled, this view gets its drawable state from its parent rather
15040     * than from its own internal properties.</p>
15041     *
15042     * <p>Note: in the current implementation, setting this property to true after the
15043     * view was added to a ViewGroup might have no effect at all. This property should
15044     * always be used from XML or set to true before adding this view to a ViewGroup.</p>
15045     *
15046     * <p>Note: if this view's parent addStateFromChildren property is enabled and this
15047     * property is enabled, an exception will be thrown.</p>
15048     *
15049     * <p>Note: if the child view uses and updates additional states which are unknown to the
15050     * parent, these states should not be affected by this method.</p>
15051     *
15052     * @param enabled True to enable duplication of the parent's drawable state, false
15053     *                to disable it.
15054     *
15055     * @see #getDrawableState()
15056     * @see #isDuplicateParentStateEnabled()
15057     */
15058    public void setDuplicateParentStateEnabled(boolean enabled) {
15059        setFlags(enabled ? DUPLICATE_PARENT_STATE : 0, DUPLICATE_PARENT_STATE);
15060    }
15061
15062    /**
15063     * <p>Indicates whether this duplicates its drawable state from its parent.</p>
15064     *
15065     * @return True if this view's drawable state is duplicated from the parent,
15066     *         false otherwise
15067     *
15068     * @see #getDrawableState()
15069     * @see #setDuplicateParentStateEnabled(boolean)
15070     */
15071    public boolean isDuplicateParentStateEnabled() {
15072        return (mViewFlags & DUPLICATE_PARENT_STATE) == DUPLICATE_PARENT_STATE;
15073    }
15074
15075    /**
15076     * <p>Specifies the type of layer backing this view. The layer can be
15077     * {@link #LAYER_TYPE_NONE}, {@link #LAYER_TYPE_SOFTWARE} or
15078     * {@link #LAYER_TYPE_HARDWARE}.</p>
15079     *
15080     * <p>A layer is associated with an optional {@link android.graphics.Paint}
15081     * instance that controls how the layer is composed on screen. The following
15082     * properties of the paint are taken into account when composing the layer:</p>
15083     * <ul>
15084     * <li>{@link android.graphics.Paint#getAlpha() Translucency (alpha)}</li>
15085     * <li>{@link android.graphics.Paint#getXfermode() Blending mode}</li>
15086     * <li>{@link android.graphics.Paint#getColorFilter() Color filter}</li>
15087     * </ul>
15088     *
15089     * <p>If this view has an alpha value set to < 1.0 by calling
15090     * {@link #setAlpha(float)}, the alpha value of the layer's paint is superseded
15091     * by this view's alpha value.</p>
15092     *
15093     * <p>Refer to the documentation of {@link #LAYER_TYPE_NONE},
15094     * {@link #LAYER_TYPE_SOFTWARE} and {@link #LAYER_TYPE_HARDWARE}
15095     * for more information on when and how to use layers.</p>
15096     *
15097     * @param layerType The type of layer to use with this view, must be one of
15098     *        {@link #LAYER_TYPE_NONE}, {@link #LAYER_TYPE_SOFTWARE} or
15099     *        {@link #LAYER_TYPE_HARDWARE}
15100     * @param paint The paint used to compose the layer. This argument is optional
15101     *        and can be null. It is ignored when the layer type is
15102     *        {@link #LAYER_TYPE_NONE}
15103     *
15104     * @see #getLayerType()
15105     * @see #LAYER_TYPE_NONE
15106     * @see #LAYER_TYPE_SOFTWARE
15107     * @see #LAYER_TYPE_HARDWARE
15108     * @see #setAlpha(float)
15109     *
15110     * @attr ref android.R.styleable#View_layerType
15111     */
15112    public void setLayerType(int layerType, Paint paint) {
15113        if (layerType < LAYER_TYPE_NONE || layerType > LAYER_TYPE_HARDWARE) {
15114            throw new IllegalArgumentException("Layer type can only be one of: LAYER_TYPE_NONE, "
15115                    + "LAYER_TYPE_SOFTWARE or LAYER_TYPE_HARDWARE");
15116        }
15117
15118        boolean typeChanged = mRenderNode.setLayerType(layerType);
15119
15120        if (!typeChanged) {
15121            setLayerPaint(paint);
15122            return;
15123        }
15124
15125        // Destroy any previous software drawing cache if needed
15126        if (mLayerType == LAYER_TYPE_SOFTWARE) {
15127            destroyDrawingCache();
15128        }
15129
15130        mLayerType = layerType;
15131        final boolean layerDisabled = (mLayerType == LAYER_TYPE_NONE);
15132        mLayerPaint = layerDisabled ? null : (paint == null ? new Paint() : paint);
15133        mRenderNode.setLayerPaint(mLayerPaint);
15134
15135        // draw() behaves differently if we are on a layer, so we need to
15136        // invalidate() here
15137        invalidateParentCaches();
15138        invalidate(true);
15139    }
15140
15141    /**
15142     * Updates the {@link Paint} object used with the current layer (used only if the current
15143     * layer type is not set to {@link #LAYER_TYPE_NONE}). Changed properties of the Paint
15144     * provided to {@link #setLayerType(int, android.graphics.Paint)} will be used the next time
15145     * the View is redrawn, but {@link #setLayerPaint(android.graphics.Paint)} must be called to
15146     * ensure that the view gets redrawn immediately.
15147     *
15148     * <p>A layer is associated with an optional {@link android.graphics.Paint}
15149     * instance that controls how the layer is composed on screen. The following
15150     * properties of the paint are taken into account when composing the layer:</p>
15151     * <ul>
15152     * <li>{@link android.graphics.Paint#getAlpha() Translucency (alpha)}</li>
15153     * <li>{@link android.graphics.Paint#getXfermode() Blending mode}</li>
15154     * <li>{@link android.graphics.Paint#getColorFilter() Color filter}</li>
15155     * </ul>
15156     *
15157     * <p>If this view has an alpha value set to < 1.0 by calling {@link #setAlpha(float)}, the
15158     * alpha value of the layer's paint is superseded by this view's alpha value.</p>
15159     *
15160     * @param paint The paint used to compose the layer. This argument is optional
15161     *        and can be null. It is ignored when the layer type is
15162     *        {@link #LAYER_TYPE_NONE}
15163     *
15164     * @see #setLayerType(int, android.graphics.Paint)
15165     */
15166    public void setLayerPaint(Paint paint) {
15167        int layerType = getLayerType();
15168        if (layerType != LAYER_TYPE_NONE) {
15169            mLayerPaint = paint == null ? new Paint() : paint;
15170            if (layerType == LAYER_TYPE_HARDWARE) {
15171                if (mRenderNode.setLayerPaint(mLayerPaint)) {
15172                    invalidateViewProperty(false, false);
15173                }
15174            } else {
15175                invalidate();
15176            }
15177        }
15178    }
15179
15180    /**
15181     * Indicates what type of layer is currently associated with this view. By default
15182     * a view does not have a layer, and the layer type is {@link #LAYER_TYPE_NONE}.
15183     * Refer to the documentation of {@link #setLayerType(int, android.graphics.Paint)}
15184     * for more information on the different types of layers.
15185     *
15186     * @return {@link #LAYER_TYPE_NONE}, {@link #LAYER_TYPE_SOFTWARE} or
15187     *         {@link #LAYER_TYPE_HARDWARE}
15188     *
15189     * @see #setLayerType(int, android.graphics.Paint)
15190     * @see #buildLayer()
15191     * @see #LAYER_TYPE_NONE
15192     * @see #LAYER_TYPE_SOFTWARE
15193     * @see #LAYER_TYPE_HARDWARE
15194     */
15195    public int getLayerType() {
15196        return mLayerType;
15197    }
15198
15199    /**
15200     * Forces this view's layer to be created and this view to be rendered
15201     * into its layer. If this view's layer type is set to {@link #LAYER_TYPE_NONE},
15202     * invoking this method will have no effect.
15203     *
15204     * This method can for instance be used to render a view into its layer before
15205     * starting an animation. If this view is complex, rendering into the layer
15206     * before starting the animation will avoid skipping frames.
15207     *
15208     * @throws IllegalStateException If this view is not attached to a window
15209     *
15210     * @see #setLayerType(int, android.graphics.Paint)
15211     */
15212    public void buildLayer() {
15213        if (mLayerType == LAYER_TYPE_NONE) return;
15214
15215        final AttachInfo attachInfo = mAttachInfo;
15216        if (attachInfo == null) {
15217            throw new IllegalStateException("This view must be attached to a window first");
15218        }
15219
15220        if (getWidth() == 0 || getHeight() == 0) {
15221            return;
15222        }
15223
15224        switch (mLayerType) {
15225            case LAYER_TYPE_HARDWARE:
15226                updateDisplayListIfDirty();
15227                if (attachInfo.mHardwareRenderer != null && mRenderNode.isValid()) {
15228                    attachInfo.mHardwareRenderer.buildLayer(mRenderNode);
15229                }
15230                break;
15231            case LAYER_TYPE_SOFTWARE:
15232                buildDrawingCache(true);
15233                break;
15234        }
15235    }
15236
15237    /**
15238     * Destroys all hardware rendering resources. This method is invoked
15239     * when the system needs to reclaim resources. Upon execution of this
15240     * method, you should free any OpenGL resources created by the view.
15241     *
15242     * Note: you <strong>must</strong> call
15243     * <code>super.destroyHardwareResources()</code> when overriding
15244     * this method.
15245     *
15246     * @hide
15247     */
15248    @CallSuper
15249    protected void destroyHardwareResources() {
15250        // Although the Layer will be destroyed by RenderNode, we want to release
15251        // the staging display list, which is also a signal to RenderNode that it's
15252        // safe to free its copy of the display list as it knows that we will
15253        // push an updated DisplayList if we try to draw again
15254        resetDisplayList();
15255    }
15256
15257    /**
15258     * <p>Enables or disables the drawing cache. When the drawing cache is enabled, the next call
15259     * to {@link #getDrawingCache()} or {@link #buildDrawingCache()} will draw the view in a
15260     * bitmap. Calling {@link #draw(android.graphics.Canvas)} will not draw from the cache when
15261     * the cache is enabled. To benefit from the cache, you must request the drawing cache by
15262     * calling {@link #getDrawingCache()} and draw it on screen if the returned bitmap is not
15263     * null.</p>
15264     *
15265     * <p>Enabling the drawing cache is similar to
15266     * {@link #setLayerType(int, android.graphics.Paint) setting a layer} when hardware
15267     * acceleration is turned off. When hardware acceleration is turned on, enabling the
15268     * drawing cache has no effect on rendering because the system uses a different mechanism
15269     * for acceleration which ignores the flag. If you want to use a Bitmap for the view, even
15270     * when hardware acceleration is enabled, see {@link #setLayerType(int, android.graphics.Paint)}
15271     * for information on how to enable software and hardware layers.</p>
15272     *
15273     * <p>This API can be used to manually generate
15274     * a bitmap copy of this view, by setting the flag to <code>true</code> and calling
15275     * {@link #getDrawingCache()}.</p>
15276     *
15277     * @param enabled true to enable the drawing cache, false otherwise
15278     *
15279     * @see #isDrawingCacheEnabled()
15280     * @see #getDrawingCache()
15281     * @see #buildDrawingCache()
15282     * @see #setLayerType(int, android.graphics.Paint)
15283     */
15284    public void setDrawingCacheEnabled(boolean enabled) {
15285        mCachingFailed = false;
15286        setFlags(enabled ? DRAWING_CACHE_ENABLED : 0, DRAWING_CACHE_ENABLED);
15287    }
15288
15289    /**
15290     * <p>Indicates whether the drawing cache is enabled for this view.</p>
15291     *
15292     * @return true if the drawing cache is enabled
15293     *
15294     * @see #setDrawingCacheEnabled(boolean)
15295     * @see #getDrawingCache()
15296     */
15297    @ViewDebug.ExportedProperty(category = "drawing")
15298    public boolean isDrawingCacheEnabled() {
15299        return (mViewFlags & DRAWING_CACHE_ENABLED) == DRAWING_CACHE_ENABLED;
15300    }
15301
15302    /**
15303     * Debugging utility which recursively outputs the dirty state of a view and its
15304     * descendants.
15305     *
15306     * @hide
15307     */
15308    @SuppressWarnings({"UnusedDeclaration"})
15309    public void outputDirtyFlags(String indent, boolean clear, int clearMask) {
15310        Log.d("View", indent + this + "             DIRTY(" + (mPrivateFlags & View.PFLAG_DIRTY_MASK) +
15311                ") DRAWN(" + (mPrivateFlags & PFLAG_DRAWN) + ")" + " CACHE_VALID(" +
15312                (mPrivateFlags & View.PFLAG_DRAWING_CACHE_VALID) +
15313                ") INVALIDATED(" + (mPrivateFlags & PFLAG_INVALIDATED) + ")");
15314        if (clear) {
15315            mPrivateFlags &= clearMask;
15316        }
15317        if (this instanceof ViewGroup) {
15318            ViewGroup parent = (ViewGroup) this;
15319            final int count = parent.getChildCount();
15320            for (int i = 0; i < count; i++) {
15321                final View child = parent.getChildAt(i);
15322                child.outputDirtyFlags(indent + "  ", clear, clearMask);
15323            }
15324        }
15325    }
15326
15327    /**
15328     * This method is used by ViewGroup to cause its children to restore or recreate their
15329     * display lists. It is called by getDisplayList() when the parent ViewGroup does not need
15330     * to recreate its own display list, which would happen if it went through the normal
15331     * draw/dispatchDraw mechanisms.
15332     *
15333     * @hide
15334     */
15335    protected void dispatchGetDisplayList() {}
15336
15337    /**
15338     * A view that is not attached or hardware accelerated cannot create a display list.
15339     * This method checks these conditions and returns the appropriate result.
15340     *
15341     * @return true if view has the ability to create a display list, false otherwise.
15342     *
15343     * @hide
15344     */
15345    public boolean canHaveDisplayList() {
15346        return !(mAttachInfo == null || mAttachInfo.mHardwareRenderer == null);
15347    }
15348
15349    /**
15350     * Gets the RenderNode for the view, and updates its DisplayList (if needed and supported)
15351     * @hide
15352     */
15353    @NonNull
15354    public RenderNode updateDisplayListIfDirty() {
15355        final RenderNode renderNode = mRenderNode;
15356        if (!canHaveDisplayList()) {
15357            // can't populate RenderNode, don't try
15358            return renderNode;
15359        }
15360
15361        if ((mPrivateFlags & PFLAG_DRAWING_CACHE_VALID) == 0
15362                || !renderNode.isValid()
15363                || (mRecreateDisplayList)) {
15364            // Don't need to recreate the display list, just need to tell our
15365            // children to restore/recreate theirs
15366            if (renderNode.isValid()
15367                    && !mRecreateDisplayList) {
15368                mPrivateFlags |= PFLAG_DRAWN | PFLAG_DRAWING_CACHE_VALID;
15369                mPrivateFlags &= ~PFLAG_DIRTY_MASK;
15370                dispatchGetDisplayList();
15371
15372                return renderNode; // no work needed
15373            }
15374
15375            // If we got here, we're recreating it. Mark it as such to ensure that
15376            // we copy in child display lists into ours in drawChild()
15377            mRecreateDisplayList = true;
15378
15379            int width = mRight - mLeft;
15380            int height = mBottom - mTop;
15381            int layerType = getLayerType();
15382
15383            final DisplayListCanvas canvas = renderNode.start(width, height);
15384            canvas.setHighContrastText(mAttachInfo.mHighContrastText);
15385
15386            try {
15387                if (layerType == LAYER_TYPE_SOFTWARE) {
15388                    buildDrawingCache(true);
15389                    Bitmap cache = getDrawingCache(true);
15390                    if (cache != null) {
15391                        canvas.drawBitmap(cache, 0, 0, mLayerPaint);
15392                    }
15393                } else {
15394                    computeScroll();
15395
15396                    canvas.translate(-mScrollX, -mScrollY);
15397                    mPrivateFlags |= PFLAG_DRAWN | PFLAG_DRAWING_CACHE_VALID;
15398                    mPrivateFlags &= ~PFLAG_DIRTY_MASK;
15399
15400                    // Fast path for layouts with no backgrounds
15401                    if ((mPrivateFlags & PFLAG_SKIP_DRAW) == PFLAG_SKIP_DRAW) {
15402                        dispatchDraw(canvas);
15403                        if (mOverlay != null && !mOverlay.isEmpty()) {
15404                            mOverlay.getOverlayView().draw(canvas);
15405                        }
15406                    } else {
15407                        draw(canvas);
15408                    }
15409                }
15410            } finally {
15411                renderNode.end(canvas);
15412                setDisplayListProperties(renderNode);
15413            }
15414        } else {
15415            mPrivateFlags |= PFLAG_DRAWN | PFLAG_DRAWING_CACHE_VALID;
15416            mPrivateFlags &= ~PFLAG_DIRTY_MASK;
15417        }
15418        return renderNode;
15419    }
15420
15421    private void resetDisplayList() {
15422        if (mRenderNode.isValid()) {
15423            mRenderNode.discardDisplayList();
15424        }
15425
15426        if (mBackgroundRenderNode != null && mBackgroundRenderNode.isValid()) {
15427            mBackgroundRenderNode.discardDisplayList();
15428        }
15429    }
15430
15431    /**
15432     * <p>Calling this method is equivalent to calling <code>getDrawingCache(false)</code>.</p>
15433     *
15434     * @return A non-scaled bitmap representing this view or null if cache is disabled.
15435     *
15436     * @see #getDrawingCache(boolean)
15437     */
15438    public Bitmap getDrawingCache() {
15439        return getDrawingCache(false);
15440    }
15441
15442    /**
15443     * <p>Returns the bitmap in which this view drawing is cached. The returned bitmap
15444     * is null when caching is disabled. If caching is enabled and the cache is not ready,
15445     * this method will create it. Calling {@link #draw(android.graphics.Canvas)} will not
15446     * draw from the cache when the cache is enabled. To benefit from the cache, you must
15447     * request the drawing cache by calling this method and draw it on screen if the
15448     * returned bitmap is not null.</p>
15449     *
15450     * <p>Note about auto scaling in compatibility mode: When auto scaling is not enabled,
15451     * this method will create a bitmap of the same size as this view. Because this bitmap
15452     * will be drawn scaled by the parent ViewGroup, the result on screen might show
15453     * scaling artifacts. To avoid such artifacts, you should call this method by setting
15454     * the auto scaling to true. Doing so, however, will generate a bitmap of a different
15455     * size than the view. This implies that your application must be able to handle this
15456     * size.</p>
15457     *
15458     * @param autoScale Indicates whether the generated bitmap should be scaled based on
15459     *        the current density of the screen when the application is in compatibility
15460     *        mode.
15461     *
15462     * @return A bitmap representing this view or null if cache is disabled.
15463     *
15464     * @see #setDrawingCacheEnabled(boolean)
15465     * @see #isDrawingCacheEnabled()
15466     * @see #buildDrawingCache(boolean)
15467     * @see #destroyDrawingCache()
15468     */
15469    public Bitmap getDrawingCache(boolean autoScale) {
15470        if ((mViewFlags & WILL_NOT_CACHE_DRAWING) == WILL_NOT_CACHE_DRAWING) {
15471            return null;
15472        }
15473        if ((mViewFlags & DRAWING_CACHE_ENABLED) == DRAWING_CACHE_ENABLED) {
15474            buildDrawingCache(autoScale);
15475        }
15476        return autoScale ? mDrawingCache : mUnscaledDrawingCache;
15477    }
15478
15479    /**
15480     * <p>Frees the resources used by the drawing cache. If you call
15481     * {@link #buildDrawingCache()} manually without calling
15482     * {@link #setDrawingCacheEnabled(boolean) setDrawingCacheEnabled(true)}, you
15483     * should cleanup the cache with this method afterwards.</p>
15484     *
15485     * @see #setDrawingCacheEnabled(boolean)
15486     * @see #buildDrawingCache()
15487     * @see #getDrawingCache()
15488     */
15489    public void destroyDrawingCache() {
15490        if (mDrawingCache != null) {
15491            mDrawingCache.recycle();
15492            mDrawingCache = null;
15493        }
15494        if (mUnscaledDrawingCache != null) {
15495            mUnscaledDrawingCache.recycle();
15496            mUnscaledDrawingCache = null;
15497        }
15498    }
15499
15500    /**
15501     * Setting a solid background color for the drawing cache's bitmaps will improve
15502     * performance and memory usage. Note, though that this should only be used if this
15503     * view will always be drawn on top of a solid color.
15504     *
15505     * @param color The background color to use for the drawing cache's bitmap
15506     *
15507     * @see #setDrawingCacheEnabled(boolean)
15508     * @see #buildDrawingCache()
15509     * @see #getDrawingCache()
15510     */
15511    public void setDrawingCacheBackgroundColor(@ColorInt int color) {
15512        if (color != mDrawingCacheBackgroundColor) {
15513            mDrawingCacheBackgroundColor = color;
15514            mPrivateFlags &= ~PFLAG_DRAWING_CACHE_VALID;
15515        }
15516    }
15517
15518    /**
15519     * @see #setDrawingCacheBackgroundColor(int)
15520     *
15521     * @return The background color to used for the drawing cache's bitmap
15522     */
15523    @ColorInt
15524    public int getDrawingCacheBackgroundColor() {
15525        return mDrawingCacheBackgroundColor;
15526    }
15527
15528    /**
15529     * <p>Calling this method is equivalent to calling <code>buildDrawingCache(false)</code>.</p>
15530     *
15531     * @see #buildDrawingCache(boolean)
15532     */
15533    public void buildDrawingCache() {
15534        buildDrawingCache(false);
15535    }
15536
15537    /**
15538     * <p>Forces the drawing cache to be built if the drawing cache is invalid.</p>
15539     *
15540     * <p>If you call {@link #buildDrawingCache()} manually without calling
15541     * {@link #setDrawingCacheEnabled(boolean) setDrawingCacheEnabled(true)}, you
15542     * should cleanup the cache by calling {@link #destroyDrawingCache()} afterwards.</p>
15543     *
15544     * <p>Note about auto scaling in compatibility mode: When auto scaling is not enabled,
15545     * this method will create a bitmap of the same size as this view. Because this bitmap
15546     * will be drawn scaled by the parent ViewGroup, the result on screen might show
15547     * scaling artifacts. To avoid such artifacts, you should call this method by setting
15548     * the auto scaling to true. Doing so, however, will generate a bitmap of a different
15549     * size than the view. This implies that your application must be able to handle this
15550     * size.</p>
15551     *
15552     * <p>You should avoid calling this method when hardware acceleration is enabled. If
15553     * you do not need the drawing cache bitmap, calling this method will increase memory
15554     * usage and cause the view to be rendered in software once, thus negatively impacting
15555     * performance.</p>
15556     *
15557     * @see #getDrawingCache()
15558     * @see #destroyDrawingCache()
15559     */
15560    public void buildDrawingCache(boolean autoScale) {
15561        if ((mPrivateFlags & PFLAG_DRAWING_CACHE_VALID) == 0 || (autoScale ?
15562                mDrawingCache == null : mUnscaledDrawingCache == null)) {
15563            if (Trace.isTagEnabled(Trace.TRACE_TAG_VIEW)) {
15564                Trace.traceBegin(Trace.TRACE_TAG_VIEW,
15565                        "buildDrawingCache/SW Layer for " + getClass().getSimpleName());
15566            }
15567            try {
15568                buildDrawingCacheImpl(autoScale);
15569            } finally {
15570                Trace.traceEnd(Trace.TRACE_TAG_VIEW);
15571            }
15572        }
15573    }
15574
15575    /**
15576     * private, internal implementation of buildDrawingCache, used to enable tracing
15577     */
15578    private void buildDrawingCacheImpl(boolean autoScale) {
15579        mCachingFailed = false;
15580
15581        int width = mRight - mLeft;
15582        int height = mBottom - mTop;
15583
15584        final AttachInfo attachInfo = mAttachInfo;
15585        final boolean scalingRequired = attachInfo != null && attachInfo.mScalingRequired;
15586
15587        if (autoScale && scalingRequired) {
15588            width = (int) ((width * attachInfo.mApplicationScale) + 0.5f);
15589            height = (int) ((height * attachInfo.mApplicationScale) + 0.5f);
15590        }
15591
15592        final int drawingCacheBackgroundColor = mDrawingCacheBackgroundColor;
15593        final boolean opaque = drawingCacheBackgroundColor != 0 || isOpaque();
15594        final boolean use32BitCache = attachInfo != null && attachInfo.mUse32BitDrawingCache;
15595
15596        final long projectedBitmapSize = width * height * (opaque && !use32BitCache ? 2 : 4);
15597        final long drawingCacheSize =
15598                ViewConfiguration.get(mContext).getScaledMaximumDrawingCacheSize();
15599        if (width <= 0 || height <= 0 || projectedBitmapSize > drawingCacheSize) {
15600            if (width > 0 && height > 0) {
15601                Log.w(VIEW_LOG_TAG, getClass().getSimpleName() + " not displayed because it is"
15602                        + " too large to fit into a software layer (or drawing cache), needs "
15603                        + projectedBitmapSize + " bytes, only "
15604                        + drawingCacheSize + " available");
15605            }
15606            destroyDrawingCache();
15607            mCachingFailed = true;
15608            return;
15609        }
15610
15611        boolean clear = true;
15612        Bitmap bitmap = autoScale ? mDrawingCache : mUnscaledDrawingCache;
15613
15614        if (bitmap == null || bitmap.getWidth() != width || bitmap.getHeight() != height) {
15615            Bitmap.Config quality;
15616            if (!opaque) {
15617                // Never pick ARGB_4444 because it looks awful
15618                // Keep the DRAWING_CACHE_QUALITY_LOW flag just in case
15619                switch (mViewFlags & DRAWING_CACHE_QUALITY_MASK) {
15620                    case DRAWING_CACHE_QUALITY_AUTO:
15621                    case DRAWING_CACHE_QUALITY_LOW:
15622                    case DRAWING_CACHE_QUALITY_HIGH:
15623                    default:
15624                        quality = Bitmap.Config.ARGB_8888;
15625                        break;
15626                }
15627            } else {
15628                // Optimization for translucent windows
15629                // If the window is translucent, use a 32 bits bitmap to benefit from memcpy()
15630                quality = use32BitCache ? Bitmap.Config.ARGB_8888 : Bitmap.Config.RGB_565;
15631            }
15632
15633            // Try to cleanup memory
15634            if (bitmap != null) bitmap.recycle();
15635
15636            try {
15637                bitmap = Bitmap.createBitmap(mResources.getDisplayMetrics(),
15638                        width, height, quality);
15639                bitmap.setDensity(getResources().getDisplayMetrics().densityDpi);
15640                if (autoScale) {
15641                    mDrawingCache = bitmap;
15642                } else {
15643                    mUnscaledDrawingCache = bitmap;
15644                }
15645                if (opaque && use32BitCache) bitmap.setHasAlpha(false);
15646            } catch (OutOfMemoryError e) {
15647                // If there is not enough memory to create the bitmap cache, just
15648                // ignore the issue as bitmap caches are not required to draw the
15649                // view hierarchy
15650                if (autoScale) {
15651                    mDrawingCache = null;
15652                } else {
15653                    mUnscaledDrawingCache = null;
15654                }
15655                mCachingFailed = true;
15656                return;
15657            }
15658
15659            clear = drawingCacheBackgroundColor != 0;
15660        }
15661
15662        Canvas canvas;
15663        if (attachInfo != null) {
15664            canvas = attachInfo.mCanvas;
15665            if (canvas == null) {
15666                canvas = new Canvas();
15667            }
15668            canvas.setBitmap(bitmap);
15669            // Temporarily clobber the cached Canvas in case one of our children
15670            // is also using a drawing cache. Without this, the children would
15671            // steal the canvas by attaching their own bitmap to it and bad, bad
15672            // thing would happen (invisible views, corrupted drawings, etc.)
15673            attachInfo.mCanvas = null;
15674        } else {
15675            // This case should hopefully never or seldom happen
15676            canvas = new Canvas(bitmap);
15677        }
15678
15679        if (clear) {
15680            bitmap.eraseColor(drawingCacheBackgroundColor);
15681        }
15682
15683        computeScroll();
15684        final int restoreCount = canvas.save();
15685
15686        if (autoScale && scalingRequired) {
15687            final float scale = attachInfo.mApplicationScale;
15688            canvas.scale(scale, scale);
15689        }
15690
15691        canvas.translate(-mScrollX, -mScrollY);
15692
15693        mPrivateFlags |= PFLAG_DRAWN;
15694        if (mAttachInfo == null || !mAttachInfo.mHardwareAccelerated ||
15695                mLayerType != LAYER_TYPE_NONE) {
15696            mPrivateFlags |= PFLAG_DRAWING_CACHE_VALID;
15697        }
15698
15699        // Fast path for layouts with no backgrounds
15700        if ((mPrivateFlags & PFLAG_SKIP_DRAW) == PFLAG_SKIP_DRAW) {
15701            mPrivateFlags &= ~PFLAG_DIRTY_MASK;
15702            dispatchDraw(canvas);
15703            if (mOverlay != null && !mOverlay.isEmpty()) {
15704                mOverlay.getOverlayView().draw(canvas);
15705            }
15706        } else {
15707            draw(canvas);
15708        }
15709
15710        canvas.restoreToCount(restoreCount);
15711        canvas.setBitmap(null);
15712
15713        if (attachInfo != null) {
15714            // Restore the cached Canvas for our siblings
15715            attachInfo.mCanvas = canvas;
15716        }
15717    }
15718
15719    /**
15720     * Create a snapshot of the view into a bitmap.  We should probably make
15721     * some form of this public, but should think about the API.
15722     */
15723    Bitmap createSnapshot(Bitmap.Config quality, int backgroundColor, boolean skipChildren) {
15724        int width = mRight - mLeft;
15725        int height = mBottom - mTop;
15726
15727        final AttachInfo attachInfo = mAttachInfo;
15728        final float scale = attachInfo != null ? attachInfo.mApplicationScale : 1.0f;
15729        width = (int) ((width * scale) + 0.5f);
15730        height = (int) ((height * scale) + 0.5f);
15731
15732        Bitmap bitmap = Bitmap.createBitmap(mResources.getDisplayMetrics(),
15733                width > 0 ? width : 1, height > 0 ? height : 1, quality);
15734        if (bitmap == null) {
15735            throw new OutOfMemoryError();
15736        }
15737
15738        Resources resources = getResources();
15739        if (resources != null) {
15740            bitmap.setDensity(resources.getDisplayMetrics().densityDpi);
15741        }
15742
15743        Canvas canvas;
15744        if (attachInfo != null) {
15745            canvas = attachInfo.mCanvas;
15746            if (canvas == null) {
15747                canvas = new Canvas();
15748            }
15749            canvas.setBitmap(bitmap);
15750            // Temporarily clobber the cached Canvas in case one of our children
15751            // is also using a drawing cache. Without this, the children would
15752            // steal the canvas by attaching their own bitmap to it and bad, bad
15753            // things would happen (invisible views, corrupted drawings, etc.)
15754            attachInfo.mCanvas = null;
15755        } else {
15756            // This case should hopefully never or seldom happen
15757            canvas = new Canvas(bitmap);
15758        }
15759
15760        if ((backgroundColor & 0xff000000) != 0) {
15761            bitmap.eraseColor(backgroundColor);
15762        }
15763
15764        computeScroll();
15765        final int restoreCount = canvas.save();
15766        canvas.scale(scale, scale);
15767        canvas.translate(-mScrollX, -mScrollY);
15768
15769        // Temporarily remove the dirty mask
15770        int flags = mPrivateFlags;
15771        mPrivateFlags &= ~PFLAG_DIRTY_MASK;
15772
15773        // Fast path for layouts with no backgrounds
15774        if ((mPrivateFlags & PFLAG_SKIP_DRAW) == PFLAG_SKIP_DRAW) {
15775            dispatchDraw(canvas);
15776            if (mOverlay != null && !mOverlay.isEmpty()) {
15777                mOverlay.getOverlayView().draw(canvas);
15778            }
15779        } else {
15780            draw(canvas);
15781        }
15782
15783        mPrivateFlags = flags;
15784
15785        canvas.restoreToCount(restoreCount);
15786        canvas.setBitmap(null);
15787
15788        if (attachInfo != null) {
15789            // Restore the cached Canvas for our siblings
15790            attachInfo.mCanvas = canvas;
15791        }
15792
15793        return bitmap;
15794    }
15795
15796    /**
15797     * Indicates whether this View is currently in edit mode. A View is usually
15798     * in edit mode when displayed within a developer tool. For instance, if
15799     * this View is being drawn by a visual user interface builder, this method
15800     * should return true.
15801     *
15802     * Subclasses should check the return value of this method to provide
15803     * different behaviors if their normal behavior might interfere with the
15804     * host environment. For instance: the class spawns a thread in its
15805     * constructor, the drawing code relies on device-specific features, etc.
15806     *
15807     * This method is usually checked in the drawing code of custom widgets.
15808     *
15809     * @return True if this View is in edit mode, false otherwise.
15810     */
15811    public boolean isInEditMode() {
15812        return false;
15813    }
15814
15815    /**
15816     * If the View draws content inside its padding and enables fading edges,
15817     * it needs to support padding offsets. Padding offsets are added to the
15818     * fading edges to extend the length of the fade so that it covers pixels
15819     * drawn inside the padding.
15820     *
15821     * Subclasses of this class should override this method if they need
15822     * to draw content inside the padding.
15823     *
15824     * @return True if padding offset must be applied, false otherwise.
15825     *
15826     * @see #getLeftPaddingOffset()
15827     * @see #getRightPaddingOffset()
15828     * @see #getTopPaddingOffset()
15829     * @see #getBottomPaddingOffset()
15830     *
15831     * @since CURRENT
15832     */
15833    protected boolean isPaddingOffsetRequired() {
15834        return false;
15835    }
15836
15837    /**
15838     * Amount by which to extend the left fading region. Called only when
15839     * {@link #isPaddingOffsetRequired()} returns true.
15840     *
15841     * @return The left padding offset in pixels.
15842     *
15843     * @see #isPaddingOffsetRequired()
15844     *
15845     * @since CURRENT
15846     */
15847    protected int getLeftPaddingOffset() {
15848        return 0;
15849    }
15850
15851    /**
15852     * Amount by which to extend the right fading region. Called only when
15853     * {@link #isPaddingOffsetRequired()} returns true.
15854     *
15855     * @return The right padding offset in pixels.
15856     *
15857     * @see #isPaddingOffsetRequired()
15858     *
15859     * @since CURRENT
15860     */
15861    protected int getRightPaddingOffset() {
15862        return 0;
15863    }
15864
15865    /**
15866     * Amount by which to extend the top fading region. Called only when
15867     * {@link #isPaddingOffsetRequired()} returns true.
15868     *
15869     * @return The top padding offset in pixels.
15870     *
15871     * @see #isPaddingOffsetRequired()
15872     *
15873     * @since CURRENT
15874     */
15875    protected int getTopPaddingOffset() {
15876        return 0;
15877    }
15878
15879    /**
15880     * Amount by which to extend the bottom fading region. Called only when
15881     * {@link #isPaddingOffsetRequired()} returns true.
15882     *
15883     * @return The bottom padding offset in pixels.
15884     *
15885     * @see #isPaddingOffsetRequired()
15886     *
15887     * @since CURRENT
15888     */
15889    protected int getBottomPaddingOffset() {
15890        return 0;
15891    }
15892
15893    /**
15894     * @hide
15895     * @param offsetRequired
15896     */
15897    protected int getFadeTop(boolean offsetRequired) {
15898        int top = mPaddingTop;
15899        if (offsetRequired) top += getTopPaddingOffset();
15900        return top;
15901    }
15902
15903    /**
15904     * @hide
15905     * @param offsetRequired
15906     */
15907    protected int getFadeHeight(boolean offsetRequired) {
15908        int padding = mPaddingTop;
15909        if (offsetRequired) padding += getTopPaddingOffset();
15910        return mBottom - mTop - mPaddingBottom - padding;
15911    }
15912
15913    /**
15914     * <p>Indicates whether this view is attached to a hardware accelerated
15915     * window or not.</p>
15916     *
15917     * <p>Even if this method returns true, it does not mean that every call
15918     * to {@link #draw(android.graphics.Canvas)} will be made with an hardware
15919     * accelerated {@link android.graphics.Canvas}. For instance, if this view
15920     * is drawn onto an offscreen {@link android.graphics.Bitmap} and its
15921     * window is hardware accelerated,
15922     * {@link android.graphics.Canvas#isHardwareAccelerated()} will likely
15923     * return false, and this method will return true.</p>
15924     *
15925     * @return True if the view is attached to a window and the window is
15926     *         hardware accelerated; false in any other case.
15927     */
15928    @ViewDebug.ExportedProperty(category = "drawing")
15929    public boolean isHardwareAccelerated() {
15930        return mAttachInfo != null && mAttachInfo.mHardwareAccelerated;
15931    }
15932
15933    /**
15934     * Sets a rectangular area on this view to which the view will be clipped
15935     * when it is drawn. Setting the value to null will remove the clip bounds
15936     * and the view will draw normally, using its full bounds.
15937     *
15938     * @param clipBounds The rectangular area, in the local coordinates of
15939     * this view, to which future drawing operations will be clipped.
15940     */
15941    public void setClipBounds(Rect clipBounds) {
15942        if (clipBounds == mClipBounds
15943                || (clipBounds != null && clipBounds.equals(mClipBounds))) {
15944            return;
15945        }
15946        if (clipBounds != null) {
15947            if (mClipBounds == null) {
15948                mClipBounds = new Rect(clipBounds);
15949            } else {
15950                mClipBounds.set(clipBounds);
15951            }
15952        } else {
15953            mClipBounds = null;
15954        }
15955        mRenderNode.setClipBounds(mClipBounds);
15956        invalidateViewProperty(false, false);
15957    }
15958
15959    /**
15960     * Returns a copy of the current {@link #setClipBounds(Rect) clipBounds}.
15961     *
15962     * @return A copy of the current clip bounds if clip bounds are set,
15963     * otherwise null.
15964     */
15965    public Rect getClipBounds() {
15966        return (mClipBounds != null) ? new Rect(mClipBounds) : null;
15967    }
15968
15969
15970    /**
15971     * Populates an output rectangle with the clip bounds of the view,
15972     * returning {@code true} if successful or {@code false} if the view's
15973     * clip bounds are {@code null}.
15974     *
15975     * @param outRect rectangle in which to place the clip bounds of the view
15976     * @return {@code true} if successful or {@code false} if the view's
15977     *         clip bounds are {@code null}
15978     */
15979    public boolean getClipBounds(Rect outRect) {
15980        if (mClipBounds != null) {
15981            outRect.set(mClipBounds);
15982            return true;
15983        }
15984        return false;
15985    }
15986
15987    /**
15988     * Utility function, called by draw(canvas, parent, drawingTime) to handle the less common
15989     * case of an active Animation being run on the view.
15990     */
15991    private boolean applyLegacyAnimation(ViewGroup parent, long drawingTime,
15992            Animation a, boolean scalingRequired) {
15993        Transformation invalidationTransform;
15994        final int flags = parent.mGroupFlags;
15995        final boolean initialized = a.isInitialized();
15996        if (!initialized) {
15997            a.initialize(mRight - mLeft, mBottom - mTop, parent.getWidth(), parent.getHeight());
15998            a.initializeInvalidateRegion(0, 0, mRight - mLeft, mBottom - mTop);
15999            if (mAttachInfo != null) a.setListenerHandler(mAttachInfo.mHandler);
16000            onAnimationStart();
16001        }
16002
16003        final Transformation t = parent.getChildTransformation();
16004        boolean more = a.getTransformation(drawingTime, t, 1f);
16005        if (scalingRequired && mAttachInfo.mApplicationScale != 1f) {
16006            if (parent.mInvalidationTransformation == null) {
16007                parent.mInvalidationTransformation = new Transformation();
16008            }
16009            invalidationTransform = parent.mInvalidationTransformation;
16010            a.getTransformation(drawingTime, invalidationTransform, 1f);
16011        } else {
16012            invalidationTransform = t;
16013        }
16014
16015        if (more) {
16016            if (!a.willChangeBounds()) {
16017                if ((flags & (ViewGroup.FLAG_OPTIMIZE_INVALIDATE | ViewGroup.FLAG_ANIMATION_DONE)) ==
16018                        ViewGroup.FLAG_OPTIMIZE_INVALIDATE) {
16019                    parent.mGroupFlags |= ViewGroup.FLAG_INVALIDATE_REQUIRED;
16020                } else if ((flags & ViewGroup.FLAG_INVALIDATE_REQUIRED) == 0) {
16021                    // The child need to draw an animation, potentially offscreen, so
16022                    // make sure we do not cancel invalidate requests
16023                    parent.mPrivateFlags |= PFLAG_DRAW_ANIMATION;
16024                    parent.invalidate(mLeft, mTop, mRight, mBottom);
16025                }
16026            } else {
16027                if (parent.mInvalidateRegion == null) {
16028                    parent.mInvalidateRegion = new RectF();
16029                }
16030                final RectF region = parent.mInvalidateRegion;
16031                a.getInvalidateRegion(0, 0, mRight - mLeft, mBottom - mTop, region,
16032                        invalidationTransform);
16033
16034                // The child need to draw an animation, potentially offscreen, so
16035                // make sure we do not cancel invalidate requests
16036                parent.mPrivateFlags |= PFLAG_DRAW_ANIMATION;
16037
16038                final int left = mLeft + (int) region.left;
16039                final int top = mTop + (int) region.top;
16040                parent.invalidate(left, top, left + (int) (region.width() + .5f),
16041                        top + (int) (region.height() + .5f));
16042            }
16043        }
16044        return more;
16045    }
16046
16047    /**
16048     * This method is called by getDisplayList() when a display list is recorded for a View.
16049     * It pushes any properties to the RenderNode that aren't managed by the RenderNode.
16050     */
16051    void setDisplayListProperties(RenderNode renderNode) {
16052        if (renderNode != null) {
16053            renderNode.setHasOverlappingRendering(hasOverlappingRendering());
16054            renderNode.setClipToBounds(mParent instanceof ViewGroup
16055                    && ((ViewGroup) mParent).getClipChildren());
16056
16057            float alpha = 1;
16058            if (mParent instanceof ViewGroup && (((ViewGroup) mParent).mGroupFlags &
16059                    ViewGroup.FLAG_SUPPORT_STATIC_TRANSFORMATIONS) != 0) {
16060                ViewGroup parentVG = (ViewGroup) mParent;
16061                final Transformation t = parentVG.getChildTransformation();
16062                if (parentVG.getChildStaticTransformation(this, t)) {
16063                    final int transformType = t.getTransformationType();
16064                    if (transformType != Transformation.TYPE_IDENTITY) {
16065                        if ((transformType & Transformation.TYPE_ALPHA) != 0) {
16066                            alpha = t.getAlpha();
16067                        }
16068                        if ((transformType & Transformation.TYPE_MATRIX) != 0) {
16069                            renderNode.setStaticMatrix(t.getMatrix());
16070                        }
16071                    }
16072                }
16073            }
16074            if (mTransformationInfo != null) {
16075                alpha *= getFinalAlpha();
16076                if (alpha < 1) {
16077                    final int multipliedAlpha = (int) (255 * alpha);
16078                    if (onSetAlpha(multipliedAlpha)) {
16079                        alpha = 1;
16080                    }
16081                }
16082                renderNode.setAlpha(alpha);
16083            } else if (alpha < 1) {
16084                renderNode.setAlpha(alpha);
16085            }
16086        }
16087    }
16088
16089    /**
16090     * This method is called by ViewGroup.drawChild() to have each child view draw itself.
16091     *
16092     * This is where the View specializes rendering behavior based on layer type,
16093     * and hardware acceleration.
16094     */
16095    boolean draw(Canvas canvas, ViewGroup parent, long drawingTime) {
16096        final boolean hardwareAcceleratedCanvas = canvas.isHardwareAccelerated();
16097        /* If an attached view draws to a HW canvas, it may use its RenderNode + DisplayList.
16098         *
16099         * If a view is dettached, its DisplayList shouldn't exist. If the canvas isn't
16100         * HW accelerated, it can't handle drawing RenderNodes.
16101         */
16102        boolean drawingWithRenderNode = mAttachInfo != null
16103                && mAttachInfo.mHardwareAccelerated
16104                && hardwareAcceleratedCanvas;
16105
16106        boolean more = false;
16107        final boolean childHasIdentityMatrix = hasIdentityMatrix();
16108        final int parentFlags = parent.mGroupFlags;
16109
16110        if ((parentFlags & ViewGroup.FLAG_CLEAR_TRANSFORMATION) != 0) {
16111            parent.getChildTransformation().clear();
16112            parent.mGroupFlags &= ~ViewGroup.FLAG_CLEAR_TRANSFORMATION;
16113        }
16114
16115        Transformation transformToApply = null;
16116        boolean concatMatrix = false;
16117        final boolean scalingRequired = mAttachInfo != null && mAttachInfo.mScalingRequired;
16118        final Animation a = getAnimation();
16119        if (a != null) {
16120            more = applyLegacyAnimation(parent, drawingTime, a, scalingRequired);
16121            concatMatrix = a.willChangeTransformationMatrix();
16122            if (concatMatrix) {
16123                mPrivateFlags3 |= PFLAG3_VIEW_IS_ANIMATING_TRANSFORM;
16124            }
16125            transformToApply = parent.getChildTransformation();
16126        } else {
16127            if ((mPrivateFlags3 & PFLAG3_VIEW_IS_ANIMATING_TRANSFORM) != 0) {
16128                // No longer animating: clear out old animation matrix
16129                mRenderNode.setAnimationMatrix(null);
16130                mPrivateFlags3 &= ~PFLAG3_VIEW_IS_ANIMATING_TRANSFORM;
16131            }
16132            if (!drawingWithRenderNode
16133                    && (parentFlags & ViewGroup.FLAG_SUPPORT_STATIC_TRANSFORMATIONS) != 0) {
16134                final Transformation t = parent.getChildTransformation();
16135                final boolean hasTransform = parent.getChildStaticTransformation(this, t);
16136                if (hasTransform) {
16137                    final int transformType = t.getTransformationType();
16138                    transformToApply = transformType != Transformation.TYPE_IDENTITY ? t : null;
16139                    concatMatrix = (transformType & Transformation.TYPE_MATRIX) != 0;
16140                }
16141            }
16142        }
16143
16144        concatMatrix |= !childHasIdentityMatrix;
16145
16146        // Sets the flag as early as possible to allow draw() implementations
16147        // to call invalidate() successfully when doing animations
16148        mPrivateFlags |= PFLAG_DRAWN;
16149
16150        if (!concatMatrix &&
16151                (parentFlags & (ViewGroup.FLAG_SUPPORT_STATIC_TRANSFORMATIONS |
16152                        ViewGroup.FLAG_CLIP_CHILDREN)) == ViewGroup.FLAG_CLIP_CHILDREN &&
16153                canvas.quickReject(mLeft, mTop, mRight, mBottom, Canvas.EdgeType.BW) &&
16154                (mPrivateFlags & PFLAG_DRAW_ANIMATION) == 0) {
16155            mPrivateFlags2 |= PFLAG2_VIEW_QUICK_REJECTED;
16156            return more;
16157        }
16158        mPrivateFlags2 &= ~PFLAG2_VIEW_QUICK_REJECTED;
16159
16160        if (hardwareAcceleratedCanvas) {
16161            // Clear INVALIDATED flag to allow invalidation to occur during rendering, but
16162            // retain the flag's value temporarily in the mRecreateDisplayList flag
16163            mRecreateDisplayList = (mPrivateFlags & PFLAG_INVALIDATED) != 0;
16164            mPrivateFlags &= ~PFLAG_INVALIDATED;
16165        }
16166
16167        RenderNode renderNode = null;
16168        Bitmap cache = null;
16169        int layerType = getLayerType(); // TODO: signify cache state with just 'cache' local
16170        if (layerType == LAYER_TYPE_SOFTWARE
16171                || (!drawingWithRenderNode && layerType != LAYER_TYPE_NONE)) {
16172            // If not drawing with RenderNode, treat HW layers as SW
16173            layerType = LAYER_TYPE_SOFTWARE;
16174            buildDrawingCache(true);
16175            cache = getDrawingCache(true);
16176        }
16177
16178        if (drawingWithRenderNode) {
16179            // Delay getting the display list until animation-driven alpha values are
16180            // set up and possibly passed on to the view
16181            renderNode = updateDisplayListIfDirty();
16182            if (!renderNode.isValid()) {
16183                // Uncommon, but possible. If a view is removed from the hierarchy during the call
16184                // to getDisplayList(), the display list will be marked invalid and we should not
16185                // try to use it again.
16186                renderNode = null;
16187                drawingWithRenderNode = false;
16188            }
16189        }
16190
16191        int sx = 0;
16192        int sy = 0;
16193        if (!drawingWithRenderNode) {
16194            computeScroll();
16195            sx = mScrollX;
16196            sy = mScrollY;
16197        }
16198
16199        final boolean drawingWithDrawingCache = cache != null && !drawingWithRenderNode;
16200        final boolean offsetForScroll = cache == null && !drawingWithRenderNode;
16201
16202        int restoreTo = -1;
16203        if (!drawingWithRenderNode || transformToApply != null) {
16204            restoreTo = canvas.save();
16205        }
16206        if (offsetForScroll) {
16207            canvas.translate(mLeft - sx, mTop - sy);
16208        } else {
16209            if (!drawingWithRenderNode) {
16210                canvas.translate(mLeft, mTop);
16211            }
16212            if (scalingRequired) {
16213                if (drawingWithRenderNode) {
16214                    // TODO: Might not need this if we put everything inside the DL
16215                    restoreTo = canvas.save();
16216                }
16217                // mAttachInfo cannot be null, otherwise scalingRequired == false
16218                final float scale = 1.0f / mAttachInfo.mApplicationScale;
16219                canvas.scale(scale, scale);
16220            }
16221        }
16222
16223        float alpha = drawingWithRenderNode ? 1 : (getAlpha() * getTransitionAlpha());
16224        if (transformToApply != null
16225                || alpha < 1
16226                || !hasIdentityMatrix()
16227                || (mPrivateFlags3 & PFLAG3_VIEW_IS_ANIMATING_ALPHA) != 0) {
16228            if (transformToApply != null || !childHasIdentityMatrix) {
16229                int transX = 0;
16230                int transY = 0;
16231
16232                if (offsetForScroll) {
16233                    transX = -sx;
16234                    transY = -sy;
16235                }
16236
16237                if (transformToApply != null) {
16238                    if (concatMatrix) {
16239                        if (drawingWithRenderNode) {
16240                            renderNode.setAnimationMatrix(transformToApply.getMatrix());
16241                        } else {
16242                            // Undo the scroll translation, apply the transformation matrix,
16243                            // then redo the scroll translate to get the correct result.
16244                            canvas.translate(-transX, -transY);
16245                            canvas.concat(transformToApply.getMatrix());
16246                            canvas.translate(transX, transY);
16247                        }
16248                        parent.mGroupFlags |= ViewGroup.FLAG_CLEAR_TRANSFORMATION;
16249                    }
16250
16251                    float transformAlpha = transformToApply.getAlpha();
16252                    if (transformAlpha < 1) {
16253                        alpha *= transformAlpha;
16254                        parent.mGroupFlags |= ViewGroup.FLAG_CLEAR_TRANSFORMATION;
16255                    }
16256                }
16257
16258                if (!childHasIdentityMatrix && !drawingWithRenderNode) {
16259                    canvas.translate(-transX, -transY);
16260                    canvas.concat(getMatrix());
16261                    canvas.translate(transX, transY);
16262                }
16263            }
16264
16265            // Deal with alpha if it is or used to be <1
16266            if (alpha < 1 || (mPrivateFlags3 & PFLAG3_VIEW_IS_ANIMATING_ALPHA) != 0) {
16267                if (alpha < 1) {
16268                    mPrivateFlags3 |= PFLAG3_VIEW_IS_ANIMATING_ALPHA;
16269                } else {
16270                    mPrivateFlags3 &= ~PFLAG3_VIEW_IS_ANIMATING_ALPHA;
16271                }
16272                parent.mGroupFlags |= ViewGroup.FLAG_CLEAR_TRANSFORMATION;
16273                if (!drawingWithDrawingCache) {
16274                    final int multipliedAlpha = (int) (255 * alpha);
16275                    if (!onSetAlpha(multipliedAlpha)) {
16276                        if (drawingWithRenderNode) {
16277                            renderNode.setAlpha(alpha * getAlpha() * getTransitionAlpha());
16278                        } else if (layerType == LAYER_TYPE_NONE) {
16279                            canvas.saveLayerAlpha(sx, sy, sx + getWidth(), sy + getHeight(),
16280                                    multipliedAlpha);
16281                        }
16282                    } else {
16283                        // Alpha is handled by the child directly, clobber the layer's alpha
16284                        mPrivateFlags |= PFLAG_ALPHA_SET;
16285                    }
16286                }
16287            }
16288        } else if ((mPrivateFlags & PFLAG_ALPHA_SET) == PFLAG_ALPHA_SET) {
16289            onSetAlpha(255);
16290            mPrivateFlags &= ~PFLAG_ALPHA_SET;
16291        }
16292
16293        if (!drawingWithRenderNode) {
16294            // apply clips directly, since RenderNode won't do it for this draw
16295            if ((parentFlags & ViewGroup.FLAG_CLIP_CHILDREN) != 0 && cache == null) {
16296                if (offsetForScroll) {
16297                    canvas.clipRect(sx, sy, sx + getWidth(), sy + getHeight());
16298                } else {
16299                    if (!scalingRequired || cache == null) {
16300                        canvas.clipRect(0, 0, getWidth(), getHeight());
16301                    } else {
16302                        canvas.clipRect(0, 0, cache.getWidth(), cache.getHeight());
16303                    }
16304                }
16305            }
16306
16307            if (mClipBounds != null) {
16308                // clip bounds ignore scroll
16309                canvas.clipRect(mClipBounds);
16310            }
16311        }
16312
16313        if (!drawingWithDrawingCache) {
16314            if (drawingWithRenderNode) {
16315                mPrivateFlags &= ~PFLAG_DIRTY_MASK;
16316                ((DisplayListCanvas) canvas).drawRenderNode(renderNode);
16317            } else {
16318                // Fast path for layouts with no backgrounds
16319                if ((mPrivateFlags & PFLAG_SKIP_DRAW) == PFLAG_SKIP_DRAW) {
16320                    mPrivateFlags &= ~PFLAG_DIRTY_MASK;
16321                    dispatchDraw(canvas);
16322                } else {
16323                    draw(canvas);
16324                }
16325            }
16326        } else if (cache != null) {
16327            mPrivateFlags &= ~PFLAG_DIRTY_MASK;
16328            if (layerType == LAYER_TYPE_NONE) {
16329                // no layer paint, use temporary paint to draw bitmap
16330                Paint cachePaint = parent.mCachePaint;
16331                if (cachePaint == null) {
16332                    cachePaint = new Paint();
16333                    cachePaint.setDither(false);
16334                    parent.mCachePaint = cachePaint;
16335                }
16336                cachePaint.setAlpha((int) (alpha * 255));
16337                canvas.drawBitmap(cache, 0.0f, 0.0f, cachePaint);
16338            } else {
16339                // use layer paint to draw the bitmap, merging the two alphas, but also restore
16340                int layerPaintAlpha = mLayerPaint.getAlpha();
16341                mLayerPaint.setAlpha((int) (alpha * layerPaintAlpha));
16342                canvas.drawBitmap(cache, 0.0f, 0.0f, mLayerPaint);
16343                mLayerPaint.setAlpha(layerPaintAlpha);
16344            }
16345        }
16346
16347        if (restoreTo >= 0) {
16348            canvas.restoreToCount(restoreTo);
16349        }
16350
16351        if (a != null && !more) {
16352            if (!hardwareAcceleratedCanvas && !a.getFillAfter()) {
16353                onSetAlpha(255);
16354            }
16355            parent.finishAnimatingView(this, a);
16356        }
16357
16358        if (more && hardwareAcceleratedCanvas) {
16359            if (a.hasAlpha() && (mPrivateFlags & PFLAG_ALPHA_SET) == PFLAG_ALPHA_SET) {
16360                // alpha animations should cause the child to recreate its display list
16361                invalidate(true);
16362            }
16363        }
16364
16365        mRecreateDisplayList = false;
16366
16367        return more;
16368    }
16369
16370    /**
16371     * Manually render this view (and all of its children) to the given Canvas.
16372     * The view must have already done a full layout before this function is
16373     * called.  When implementing a view, implement
16374     * {@link #onDraw(android.graphics.Canvas)} instead of overriding this method.
16375     * If you do need to override this method, call the superclass version.
16376     *
16377     * @param canvas The Canvas to which the View is rendered.
16378     */
16379    @CallSuper
16380    public void draw(Canvas canvas) {
16381        final int privateFlags = mPrivateFlags;
16382        final boolean dirtyOpaque = (privateFlags & PFLAG_DIRTY_MASK) == PFLAG_DIRTY_OPAQUE &&
16383                (mAttachInfo == null || !mAttachInfo.mIgnoreDirtyState);
16384        mPrivateFlags = (privateFlags & ~PFLAG_DIRTY_MASK) | PFLAG_DRAWN;
16385
16386        /*
16387         * Draw traversal performs several drawing steps which must be executed
16388         * in the appropriate order:
16389         *
16390         *      1. Draw the background
16391         *      2. If necessary, save the canvas' layers to prepare for fading
16392         *      3. Draw view's content
16393         *      4. Draw children
16394         *      5. If necessary, draw the fading edges and restore layers
16395         *      6. Draw decorations (scrollbars for instance)
16396         */
16397
16398        // Step 1, draw the background, if needed
16399        int saveCount;
16400
16401        if (!dirtyOpaque) {
16402            drawBackground(canvas);
16403        }
16404
16405        // skip step 2 & 5 if possible (common case)
16406        final int viewFlags = mViewFlags;
16407        boolean horizontalEdges = (viewFlags & FADING_EDGE_HORIZONTAL) != 0;
16408        boolean verticalEdges = (viewFlags & FADING_EDGE_VERTICAL) != 0;
16409        if (!verticalEdges && !horizontalEdges) {
16410            // Step 3, draw the content
16411            if (!dirtyOpaque) onDraw(canvas);
16412
16413            // Step 4, draw the children
16414            dispatchDraw(canvas);
16415
16416            // Overlay is part of the content and draws beneath Foreground
16417            if (mOverlay != null && !mOverlay.isEmpty()) {
16418                mOverlay.getOverlayView().dispatchDraw(canvas);
16419            }
16420
16421            // Step 6, draw decorations (foreground, scrollbars)
16422            onDrawForeground(canvas);
16423
16424            // we're done...
16425            return;
16426        }
16427
16428        /*
16429         * Here we do the full fledged routine...
16430         * (this is an uncommon case where speed matters less,
16431         * this is why we repeat some of the tests that have been
16432         * done above)
16433         */
16434
16435        boolean drawTop = false;
16436        boolean drawBottom = false;
16437        boolean drawLeft = false;
16438        boolean drawRight = false;
16439
16440        float topFadeStrength = 0.0f;
16441        float bottomFadeStrength = 0.0f;
16442        float leftFadeStrength = 0.0f;
16443        float rightFadeStrength = 0.0f;
16444
16445        // Step 2, save the canvas' layers
16446        int paddingLeft = mPaddingLeft;
16447
16448        final boolean offsetRequired = isPaddingOffsetRequired();
16449        if (offsetRequired) {
16450            paddingLeft += getLeftPaddingOffset();
16451        }
16452
16453        int left = mScrollX + paddingLeft;
16454        int right = left + mRight - mLeft - mPaddingRight - paddingLeft;
16455        int top = mScrollY + getFadeTop(offsetRequired);
16456        int bottom = top + getFadeHeight(offsetRequired);
16457
16458        if (offsetRequired) {
16459            right += getRightPaddingOffset();
16460            bottom += getBottomPaddingOffset();
16461        }
16462
16463        final ScrollabilityCache scrollabilityCache = mScrollCache;
16464        final float fadeHeight = scrollabilityCache.fadingEdgeLength;
16465        int length = (int) fadeHeight;
16466
16467        // clip the fade length if top and bottom fades overlap
16468        // overlapping fades produce odd-looking artifacts
16469        if (verticalEdges && (top + length > bottom - length)) {
16470            length = (bottom - top) / 2;
16471        }
16472
16473        // also clip horizontal fades if necessary
16474        if (horizontalEdges && (left + length > right - length)) {
16475            length = (right - left) / 2;
16476        }
16477
16478        if (verticalEdges) {
16479            topFadeStrength = Math.max(0.0f, Math.min(1.0f, getTopFadingEdgeStrength()));
16480            drawTop = topFadeStrength * fadeHeight > 1.0f;
16481            bottomFadeStrength = Math.max(0.0f, Math.min(1.0f, getBottomFadingEdgeStrength()));
16482            drawBottom = bottomFadeStrength * fadeHeight > 1.0f;
16483        }
16484
16485        if (horizontalEdges) {
16486            leftFadeStrength = Math.max(0.0f, Math.min(1.0f, getLeftFadingEdgeStrength()));
16487            drawLeft = leftFadeStrength * fadeHeight > 1.0f;
16488            rightFadeStrength = Math.max(0.0f, Math.min(1.0f, getRightFadingEdgeStrength()));
16489            drawRight = rightFadeStrength * fadeHeight > 1.0f;
16490        }
16491
16492        saveCount = canvas.getSaveCount();
16493
16494        int solidColor = getSolidColor();
16495        if (solidColor == 0) {
16496            final int flags = Canvas.HAS_ALPHA_LAYER_SAVE_FLAG;
16497
16498            if (drawTop) {
16499                canvas.saveLayer(left, top, right, top + length, null, flags);
16500            }
16501
16502            if (drawBottom) {
16503                canvas.saveLayer(left, bottom - length, right, bottom, null, flags);
16504            }
16505
16506            if (drawLeft) {
16507                canvas.saveLayer(left, top, left + length, bottom, null, flags);
16508            }
16509
16510            if (drawRight) {
16511                canvas.saveLayer(right - length, top, right, bottom, null, flags);
16512            }
16513        } else {
16514            scrollabilityCache.setFadeColor(solidColor);
16515        }
16516
16517        // Step 3, draw the content
16518        if (!dirtyOpaque) onDraw(canvas);
16519
16520        // Step 4, draw the children
16521        dispatchDraw(canvas);
16522
16523        // Step 5, draw the fade effect and restore layers
16524        final Paint p = scrollabilityCache.paint;
16525        final Matrix matrix = scrollabilityCache.matrix;
16526        final Shader fade = scrollabilityCache.shader;
16527
16528        if (drawTop) {
16529            matrix.setScale(1, fadeHeight * topFadeStrength);
16530            matrix.postTranslate(left, top);
16531            fade.setLocalMatrix(matrix);
16532            p.setShader(fade);
16533            canvas.drawRect(left, top, right, top + length, p);
16534        }
16535
16536        if (drawBottom) {
16537            matrix.setScale(1, fadeHeight * bottomFadeStrength);
16538            matrix.postRotate(180);
16539            matrix.postTranslate(left, bottom);
16540            fade.setLocalMatrix(matrix);
16541            p.setShader(fade);
16542            canvas.drawRect(left, bottom - length, right, bottom, p);
16543        }
16544
16545        if (drawLeft) {
16546            matrix.setScale(1, fadeHeight * leftFadeStrength);
16547            matrix.postRotate(-90);
16548            matrix.postTranslate(left, top);
16549            fade.setLocalMatrix(matrix);
16550            p.setShader(fade);
16551            canvas.drawRect(left, top, left + length, bottom, p);
16552        }
16553
16554        if (drawRight) {
16555            matrix.setScale(1, fadeHeight * rightFadeStrength);
16556            matrix.postRotate(90);
16557            matrix.postTranslate(right, top);
16558            fade.setLocalMatrix(matrix);
16559            p.setShader(fade);
16560            canvas.drawRect(right - length, top, right, bottom, p);
16561        }
16562
16563        canvas.restoreToCount(saveCount);
16564
16565        // Overlay is part of the content and draws beneath Foreground
16566        if (mOverlay != null && !mOverlay.isEmpty()) {
16567            mOverlay.getOverlayView().dispatchDraw(canvas);
16568        }
16569
16570        // Step 6, draw decorations (foreground, scrollbars)
16571        onDrawForeground(canvas);
16572    }
16573
16574    /**
16575     * Draws the background onto the specified canvas.
16576     *
16577     * @param canvas Canvas on which to draw the background
16578     */
16579    private void drawBackground(Canvas canvas) {
16580        final Drawable background = mBackground;
16581        if (background == null) {
16582            return;
16583        }
16584
16585        setBackgroundBounds();
16586
16587        // Attempt to use a display list if requested.
16588        if (canvas.isHardwareAccelerated() && mAttachInfo != null
16589                && mAttachInfo.mHardwareRenderer != null) {
16590            mBackgroundRenderNode = getDrawableRenderNode(background, mBackgroundRenderNode);
16591
16592            final RenderNode renderNode = mBackgroundRenderNode;
16593            if (renderNode != null && renderNode.isValid()) {
16594                setBackgroundRenderNodeProperties(renderNode);
16595                ((DisplayListCanvas) canvas).drawRenderNode(renderNode);
16596                return;
16597            }
16598        }
16599
16600        final int scrollX = mScrollX;
16601        final int scrollY = mScrollY;
16602        if ((scrollX | scrollY) == 0) {
16603            background.draw(canvas);
16604        } else {
16605            canvas.translate(scrollX, scrollY);
16606            background.draw(canvas);
16607            canvas.translate(-scrollX, -scrollY);
16608        }
16609    }
16610
16611    /**
16612     * Sets the correct background bounds and rebuilds the outline, if needed.
16613     * <p/>
16614     * This is called by LayoutLib.
16615     */
16616    void setBackgroundBounds() {
16617        if (mBackgroundSizeChanged && mBackground != null) {
16618            mBackground.setBounds(0, 0, mRight - mLeft, mBottom - mTop);
16619            mBackgroundSizeChanged = false;
16620            rebuildOutline();
16621        }
16622    }
16623
16624    private void setBackgroundRenderNodeProperties(RenderNode renderNode) {
16625        renderNode.setTranslationX(mScrollX);
16626        renderNode.setTranslationY(mScrollY);
16627    }
16628
16629    /**
16630     * Creates a new display list or updates the existing display list for the
16631     * specified Drawable.
16632     *
16633     * @param drawable Drawable for which to create a display list
16634     * @param renderNode Existing RenderNode, or {@code null}
16635     * @return A valid display list for the specified drawable
16636     */
16637    private RenderNode getDrawableRenderNode(Drawable drawable, RenderNode renderNode) {
16638        if (renderNode == null) {
16639            renderNode = RenderNode.create(drawable.getClass().getName(), this);
16640        }
16641
16642        final Rect bounds = drawable.getBounds();
16643        final int width = bounds.width();
16644        final int height = bounds.height();
16645        final DisplayListCanvas canvas = renderNode.start(width, height);
16646
16647        // Reverse left/top translation done by drawable canvas, which will
16648        // instead be applied by rendernode's LTRB bounds below. This way, the
16649        // drawable's bounds match with its rendernode bounds and its content
16650        // will lie within those bounds in the rendernode tree.
16651        canvas.translate(-bounds.left, -bounds.top);
16652
16653        try {
16654            drawable.draw(canvas);
16655        } finally {
16656            renderNode.end(canvas);
16657        }
16658
16659        // Set up drawable properties that are view-independent.
16660        renderNode.setLeftTopRightBottom(bounds.left, bounds.top, bounds.right, bounds.bottom);
16661        renderNode.setProjectBackwards(drawable.isProjected());
16662        renderNode.setProjectionReceiver(true);
16663        renderNode.setClipToBounds(false);
16664        return renderNode;
16665    }
16666
16667    /**
16668     * Returns the overlay for this view, creating it if it does not yet exist.
16669     * Adding drawables to the overlay will cause them to be displayed whenever
16670     * the view itself is redrawn. Objects in the overlay should be actively
16671     * managed: remove them when they should not be displayed anymore. The
16672     * overlay will always have the same size as its host view.
16673     *
16674     * <p>Note: Overlays do not currently work correctly with {@link
16675     * SurfaceView} or {@link TextureView}; contents in overlays for these
16676     * types of views may not display correctly.</p>
16677     *
16678     * @return The ViewOverlay object for this view.
16679     * @see ViewOverlay
16680     */
16681    public ViewOverlay getOverlay() {
16682        if (mOverlay == null) {
16683            mOverlay = new ViewOverlay(mContext, this);
16684        }
16685        return mOverlay;
16686    }
16687
16688    /**
16689     * Override this if your view is known to always be drawn on top of a solid color background,
16690     * and needs to draw fading edges. Returning a non-zero color enables the view system to
16691     * optimize the drawing of the fading edges. If you do return a non-zero color, the alpha
16692     * should be set to 0xFF.
16693     *
16694     * @see #setVerticalFadingEdgeEnabled(boolean)
16695     * @see #setHorizontalFadingEdgeEnabled(boolean)
16696     *
16697     * @return The known solid color background for this view, or 0 if the color may vary
16698     */
16699    @ViewDebug.ExportedProperty(category = "drawing")
16700    @ColorInt
16701    public int getSolidColor() {
16702        return 0;
16703    }
16704
16705    /**
16706     * Build a human readable string representation of the specified view flags.
16707     *
16708     * @param flags the view flags to convert to a string
16709     * @return a String representing the supplied flags
16710     */
16711    private static String printFlags(int flags) {
16712        String output = "";
16713        int numFlags = 0;
16714        if ((flags & FOCUSABLE_MASK) == FOCUSABLE) {
16715            output += "TAKES_FOCUS";
16716            numFlags++;
16717        }
16718
16719        switch (flags & VISIBILITY_MASK) {
16720        case INVISIBLE:
16721            if (numFlags > 0) {
16722                output += " ";
16723            }
16724            output += "INVISIBLE";
16725            // USELESS HERE numFlags++;
16726            break;
16727        case GONE:
16728            if (numFlags > 0) {
16729                output += " ";
16730            }
16731            output += "GONE";
16732            // USELESS HERE numFlags++;
16733            break;
16734        default:
16735            break;
16736        }
16737        return output;
16738    }
16739
16740    /**
16741     * Build a human readable string representation of the specified private
16742     * view flags.
16743     *
16744     * @param privateFlags the private view flags to convert to a string
16745     * @return a String representing the supplied flags
16746     */
16747    private static String printPrivateFlags(int privateFlags) {
16748        String output = "";
16749        int numFlags = 0;
16750
16751        if ((privateFlags & PFLAG_WANTS_FOCUS) == PFLAG_WANTS_FOCUS) {
16752            output += "WANTS_FOCUS";
16753            numFlags++;
16754        }
16755
16756        if ((privateFlags & PFLAG_FOCUSED) == PFLAG_FOCUSED) {
16757            if (numFlags > 0) {
16758                output += " ";
16759            }
16760            output += "FOCUSED";
16761            numFlags++;
16762        }
16763
16764        if ((privateFlags & PFLAG_SELECTED) == PFLAG_SELECTED) {
16765            if (numFlags > 0) {
16766                output += " ";
16767            }
16768            output += "SELECTED";
16769            numFlags++;
16770        }
16771
16772        if ((privateFlags & PFLAG_IS_ROOT_NAMESPACE) == PFLAG_IS_ROOT_NAMESPACE) {
16773            if (numFlags > 0) {
16774                output += " ";
16775            }
16776            output += "IS_ROOT_NAMESPACE";
16777            numFlags++;
16778        }
16779
16780        if ((privateFlags & PFLAG_HAS_BOUNDS) == PFLAG_HAS_BOUNDS) {
16781            if (numFlags > 0) {
16782                output += " ";
16783            }
16784            output += "HAS_BOUNDS";
16785            numFlags++;
16786        }
16787
16788        if ((privateFlags & PFLAG_DRAWN) == PFLAG_DRAWN) {
16789            if (numFlags > 0) {
16790                output += " ";
16791            }
16792            output += "DRAWN";
16793            // USELESS HERE numFlags++;
16794        }
16795        return output;
16796    }
16797
16798    /**
16799     * <p>Indicates whether or not this view's layout will be requested during
16800     * the next hierarchy layout pass.</p>
16801     *
16802     * @return true if the layout will be forced during next layout pass
16803     */
16804    public boolean isLayoutRequested() {
16805        return (mPrivateFlags & PFLAG_FORCE_LAYOUT) == PFLAG_FORCE_LAYOUT;
16806    }
16807
16808    /**
16809     * Return true if o is a ViewGroup that is laying out using optical bounds.
16810     * @hide
16811     */
16812    public static boolean isLayoutModeOptical(Object o) {
16813        return o instanceof ViewGroup && ((ViewGroup) o).isLayoutModeOptical();
16814    }
16815
16816    private boolean setOpticalFrame(int left, int top, int right, int bottom) {
16817        Insets parentInsets = mParent instanceof View ?
16818                ((View) mParent).getOpticalInsets() : Insets.NONE;
16819        Insets childInsets = getOpticalInsets();
16820        return setFrame(
16821                left   + parentInsets.left - childInsets.left,
16822                top    + parentInsets.top  - childInsets.top,
16823                right  + parentInsets.left + childInsets.right,
16824                bottom + parentInsets.top  + childInsets.bottom);
16825    }
16826
16827    /**
16828     * Assign a size and position to a view and all of its
16829     * descendants
16830     *
16831     * <p>This is the second phase of the layout mechanism.
16832     * (The first is measuring). In this phase, each parent calls
16833     * layout on all of its children to position them.
16834     * This is typically done using the child measurements
16835     * that were stored in the measure pass().</p>
16836     *
16837     * <p>Derived classes should not override this method.
16838     * Derived classes with children should override
16839     * onLayout. In that method, they should
16840     * call layout on each of their children.</p>
16841     *
16842     * @param l Left position, relative to parent
16843     * @param t Top position, relative to parent
16844     * @param r Right position, relative to parent
16845     * @param b Bottom position, relative to parent
16846     */
16847    @SuppressWarnings({"unchecked"})
16848    public void layout(int l, int t, int r, int b) {
16849        if ((mPrivateFlags3 & PFLAG3_MEASURE_NEEDED_BEFORE_LAYOUT) != 0) {
16850            onMeasure(mOldWidthMeasureSpec, mOldHeightMeasureSpec);
16851            mPrivateFlags3 &= ~PFLAG3_MEASURE_NEEDED_BEFORE_LAYOUT;
16852        }
16853
16854        int oldL = mLeft;
16855        int oldT = mTop;
16856        int oldB = mBottom;
16857        int oldR = mRight;
16858
16859        boolean changed = isLayoutModeOptical(mParent) ?
16860                setOpticalFrame(l, t, r, b) : setFrame(l, t, r, b);
16861
16862        if (changed || (mPrivateFlags & PFLAG_LAYOUT_REQUIRED) == PFLAG_LAYOUT_REQUIRED) {
16863            onLayout(changed, l, t, r, b);
16864            mPrivateFlags &= ~PFLAG_LAYOUT_REQUIRED;
16865
16866            ListenerInfo li = mListenerInfo;
16867            if (li != null && li.mOnLayoutChangeListeners != null) {
16868                ArrayList<OnLayoutChangeListener> listenersCopy =
16869                        (ArrayList<OnLayoutChangeListener>)li.mOnLayoutChangeListeners.clone();
16870                int numListeners = listenersCopy.size();
16871                for (int i = 0; i < numListeners; ++i) {
16872                    listenersCopy.get(i).onLayoutChange(this, l, t, r, b, oldL, oldT, oldR, oldB);
16873                }
16874            }
16875        }
16876
16877        mPrivateFlags &= ~PFLAG_FORCE_LAYOUT;
16878        mPrivateFlags3 |= PFLAG3_IS_LAID_OUT;
16879    }
16880
16881    /**
16882     * Called from layout when this view should
16883     * assign a size and position to each of its children.
16884     *
16885     * Derived classes with children should override
16886     * this method and call layout on each of
16887     * their children.
16888     * @param changed This is a new size or position for this view
16889     * @param left Left position, relative to parent
16890     * @param top Top position, relative to parent
16891     * @param right Right position, relative to parent
16892     * @param bottom Bottom position, relative to parent
16893     */
16894    protected void onLayout(boolean changed, int left, int top, int right, int bottom) {
16895    }
16896
16897    /**
16898     * Assign a size and position to this view.
16899     *
16900     * This is called from layout.
16901     *
16902     * @param left Left position, relative to parent
16903     * @param top Top position, relative to parent
16904     * @param right Right position, relative to parent
16905     * @param bottom Bottom position, relative to parent
16906     * @return true if the new size and position are different than the
16907     *         previous ones
16908     * {@hide}
16909     */
16910    protected boolean setFrame(int left, int top, int right, int bottom) {
16911        boolean changed = false;
16912
16913        if (DBG) {
16914            Log.d("View", this + " View.setFrame(" + left + "," + top + ","
16915                    + right + "," + bottom + ")");
16916        }
16917
16918        if (mLeft != left || mRight != right || mTop != top || mBottom != bottom) {
16919            changed = true;
16920
16921            // Remember our drawn bit
16922            int drawn = mPrivateFlags & PFLAG_DRAWN;
16923
16924            int oldWidth = mRight - mLeft;
16925            int oldHeight = mBottom - mTop;
16926            int newWidth = right - left;
16927            int newHeight = bottom - top;
16928            boolean sizeChanged = (newWidth != oldWidth) || (newHeight != oldHeight);
16929
16930            // Invalidate our old position
16931            invalidate(sizeChanged);
16932
16933            mLeft = left;
16934            mTop = top;
16935            mRight = right;
16936            mBottom = bottom;
16937            mRenderNode.setLeftTopRightBottom(mLeft, mTop, mRight, mBottom);
16938
16939            mPrivateFlags |= PFLAG_HAS_BOUNDS;
16940
16941
16942            if (sizeChanged) {
16943                sizeChange(newWidth, newHeight, oldWidth, oldHeight);
16944            }
16945
16946            if ((mViewFlags & VISIBILITY_MASK) == VISIBLE || mGhostView != null) {
16947                // If we are visible, force the DRAWN bit to on so that
16948                // this invalidate will go through (at least to our parent).
16949                // This is because someone may have invalidated this view
16950                // before this call to setFrame came in, thereby clearing
16951                // the DRAWN bit.
16952                mPrivateFlags |= PFLAG_DRAWN;
16953                invalidate(sizeChanged);
16954                // parent display list may need to be recreated based on a change in the bounds
16955                // of any child
16956                invalidateParentCaches();
16957            }
16958
16959            // Reset drawn bit to original value (invalidate turns it off)
16960            mPrivateFlags |= drawn;
16961
16962            mBackgroundSizeChanged = true;
16963            if (mForegroundInfo != null) {
16964                mForegroundInfo.mBoundsChanged = true;
16965            }
16966
16967            notifySubtreeAccessibilityStateChangedIfNeeded();
16968        }
16969        return changed;
16970    }
16971
16972    /**
16973     * Same as setFrame, but public and hidden. For use in {@link android.transition.ChangeBounds}.
16974     * @hide
16975     */
16976    public void setLeftTopRightBottom(int left, int top, int right, int bottom) {
16977        setFrame(left, top, right, bottom);
16978    }
16979
16980    private void sizeChange(int newWidth, int newHeight, int oldWidth, int oldHeight) {
16981        onSizeChanged(newWidth, newHeight, oldWidth, oldHeight);
16982        if (mOverlay != null) {
16983            mOverlay.getOverlayView().setRight(newWidth);
16984            mOverlay.getOverlayView().setBottom(newHeight);
16985        }
16986        rebuildOutline();
16987    }
16988
16989    /**
16990     * Finalize inflating a view from XML.  This is called as the last phase
16991     * of inflation, after all child views have been added.
16992     *
16993     * <p>Even if the subclass overrides onFinishInflate, they should always be
16994     * sure to call the super method, so that we get called.
16995     */
16996    @CallSuper
16997    protected void onFinishInflate() {
16998    }
16999
17000    /**
17001     * Returns the resources associated with this view.
17002     *
17003     * @return Resources object.
17004     */
17005    public Resources getResources() {
17006        return mResources;
17007    }
17008
17009    /**
17010     * Invalidates the specified Drawable.
17011     *
17012     * @param drawable the drawable to invalidate
17013     */
17014    @Override
17015    public void invalidateDrawable(@NonNull Drawable drawable) {
17016        if (verifyDrawable(drawable)) {
17017            final Rect dirty = drawable.getDirtyBounds();
17018            final int scrollX = mScrollX;
17019            final int scrollY = mScrollY;
17020
17021            invalidate(dirty.left + scrollX, dirty.top + scrollY,
17022                    dirty.right + scrollX, dirty.bottom + scrollY);
17023            rebuildOutline();
17024        }
17025    }
17026
17027    /**
17028     * Schedules an action on a drawable to occur at a specified time.
17029     *
17030     * @param who the recipient of the action
17031     * @param what the action to run on the drawable
17032     * @param when the time at which the action must occur. Uses the
17033     *        {@link SystemClock#uptimeMillis} timebase.
17034     */
17035    @Override
17036    public void scheduleDrawable(Drawable who, Runnable what, long when) {
17037        if (verifyDrawable(who) && what != null) {
17038            final long delay = when - SystemClock.uptimeMillis();
17039            if (mAttachInfo != null) {
17040                mAttachInfo.mViewRootImpl.mChoreographer.postCallbackDelayed(
17041                        Choreographer.CALLBACK_ANIMATION, what, who,
17042                        Choreographer.subtractFrameDelay(delay));
17043            } else {
17044                // Postpone the runnable until we know
17045                // on which thread it needs to run.
17046                getRunQueue().postDelayed(what, delay);
17047            }
17048        }
17049    }
17050
17051    /**
17052     * Cancels a scheduled action on a drawable.
17053     *
17054     * @param who the recipient of the action
17055     * @param what the action to cancel
17056     */
17057    @Override
17058    public void unscheduleDrawable(Drawable who, Runnable what) {
17059        if (verifyDrawable(who) && what != null) {
17060            if (mAttachInfo != null) {
17061                mAttachInfo.mViewRootImpl.mChoreographer.removeCallbacks(
17062                        Choreographer.CALLBACK_ANIMATION, what, who);
17063            }
17064            getRunQueue().removeCallbacks(what);
17065        }
17066    }
17067
17068    /**
17069     * Unschedule any events associated with the given Drawable.  This can be
17070     * used when selecting a new Drawable into a view, so that the previous
17071     * one is completely unscheduled.
17072     *
17073     * @param who The Drawable to unschedule.
17074     *
17075     * @see #drawableStateChanged
17076     */
17077    public void unscheduleDrawable(Drawable who) {
17078        if (mAttachInfo != null && who != null) {
17079            mAttachInfo.mViewRootImpl.mChoreographer.removeCallbacks(
17080                    Choreographer.CALLBACK_ANIMATION, null, who);
17081        }
17082    }
17083
17084    /**
17085     * Resolve the Drawables depending on the layout direction. This is implicitly supposing
17086     * that the View directionality can and will be resolved before its Drawables.
17087     *
17088     * Will call {@link View#onResolveDrawables} when resolution is done.
17089     *
17090     * @hide
17091     */
17092    protected void resolveDrawables() {
17093        // Drawables resolution may need to happen before resolving the layout direction (which is
17094        // done only during the measure() call).
17095        // If the layout direction is not resolved yet, we cannot resolve the Drawables except in
17096        // one case: when the raw layout direction has not been defined as LAYOUT_DIRECTION_INHERIT.
17097        // So, if the raw layout direction is LAYOUT_DIRECTION_LTR or LAYOUT_DIRECTION_RTL or
17098        // LAYOUT_DIRECTION_LOCALE, we can "cheat" and we don't need to wait for the layout
17099        // direction to be resolved as its resolved value will be the same as its raw value.
17100        if (!isLayoutDirectionResolved() &&
17101                getRawLayoutDirection() == View.LAYOUT_DIRECTION_INHERIT) {
17102            return;
17103        }
17104
17105        final int layoutDirection = isLayoutDirectionResolved() ?
17106                getLayoutDirection() : getRawLayoutDirection();
17107
17108        if (mBackground != null) {
17109            mBackground.setLayoutDirection(layoutDirection);
17110        }
17111        if (mForegroundInfo != null && mForegroundInfo.mDrawable != null) {
17112            mForegroundInfo.mDrawable.setLayoutDirection(layoutDirection);
17113        }
17114        mPrivateFlags2 |= PFLAG2_DRAWABLE_RESOLVED;
17115        onResolveDrawables(layoutDirection);
17116    }
17117
17118    boolean areDrawablesResolved() {
17119        return (mPrivateFlags2 & PFLAG2_DRAWABLE_RESOLVED) == PFLAG2_DRAWABLE_RESOLVED;
17120    }
17121
17122    /**
17123     * Called when layout direction has been resolved.
17124     *
17125     * The default implementation does nothing.
17126     *
17127     * @param layoutDirection The resolved layout direction.
17128     *
17129     * @see #LAYOUT_DIRECTION_LTR
17130     * @see #LAYOUT_DIRECTION_RTL
17131     *
17132     * @hide
17133     */
17134    public void onResolveDrawables(@ResolvedLayoutDir int layoutDirection) {
17135    }
17136
17137    /**
17138     * @hide
17139     */
17140    protected void resetResolvedDrawables() {
17141        resetResolvedDrawablesInternal();
17142    }
17143
17144    void resetResolvedDrawablesInternal() {
17145        mPrivateFlags2 &= ~PFLAG2_DRAWABLE_RESOLVED;
17146    }
17147
17148    /**
17149     * If your view subclass is displaying its own Drawable objects, it should
17150     * override this function and return true for any Drawable it is
17151     * displaying.  This allows animations for those drawables to be
17152     * scheduled.
17153     *
17154     * <p>Be sure to call through to the super class when overriding this
17155     * function.
17156     *
17157     * @param who The Drawable to verify.  Return true if it is one you are
17158     *            displaying, else return the result of calling through to the
17159     *            super class.
17160     *
17161     * @return boolean If true than the Drawable is being displayed in the
17162     *         view; else false and it is not allowed to animate.
17163     *
17164     * @see #unscheduleDrawable(android.graphics.drawable.Drawable)
17165     * @see #drawableStateChanged()
17166     */
17167    @CallSuper
17168    protected boolean verifyDrawable(Drawable who) {
17169        return who == mBackground || (mScrollCache != null && mScrollCache.scrollBar == who)
17170                || (mForegroundInfo != null && mForegroundInfo.mDrawable == who);
17171    }
17172
17173    /**
17174     * This function is called whenever the state of the view changes in such
17175     * a way that it impacts the state of drawables being shown.
17176     * <p>
17177     * If the View has a StateListAnimator, it will also be called to run necessary state
17178     * change animations.
17179     * <p>
17180     * Be sure to call through to the superclass when overriding this function.
17181     *
17182     * @see Drawable#setState(int[])
17183     */
17184    @CallSuper
17185    protected void drawableStateChanged() {
17186        final int[] state = getDrawableState();
17187        boolean changed = false;
17188
17189        final Drawable bg = mBackground;
17190        if (bg != null && bg.isStateful()) {
17191            changed |= bg.setState(state);
17192        }
17193
17194        final Drawable fg = mForegroundInfo != null ? mForegroundInfo.mDrawable : null;
17195        if (fg != null && fg.isStateful()) {
17196            changed |= fg.setState(state);
17197        }
17198
17199        if (mScrollCache != null) {
17200            final Drawable scrollBar = mScrollCache.scrollBar;
17201            if (scrollBar != null && scrollBar.isStateful()) {
17202                changed |= scrollBar.setState(state)
17203                        && mScrollCache.state != ScrollabilityCache.OFF;
17204            }
17205        }
17206
17207        if (mStateListAnimator != null) {
17208            mStateListAnimator.setState(state);
17209        }
17210
17211        if (changed) {
17212            invalidate();
17213        }
17214    }
17215
17216    /**
17217     * This function is called whenever the view hotspot changes and needs to
17218     * be propagated to drawables or child views managed by the view.
17219     * <p>
17220     * Dispatching to child views is handled by
17221     * {@link #dispatchDrawableHotspotChanged(float, float)}.
17222     * <p>
17223     * Be sure to call through to the superclass when overriding this function.
17224     *
17225     * @param x hotspot x coordinate
17226     * @param y hotspot y coordinate
17227     */
17228    @CallSuper
17229    public void drawableHotspotChanged(float x, float y) {
17230        if (mBackground != null) {
17231            mBackground.setHotspot(x, y);
17232        }
17233        if (mForegroundInfo != null && mForegroundInfo.mDrawable != null) {
17234            mForegroundInfo.mDrawable.setHotspot(x, y);
17235        }
17236
17237        dispatchDrawableHotspotChanged(x, y);
17238    }
17239
17240    /**
17241     * Dispatches drawableHotspotChanged to all of this View's children.
17242     *
17243     * @param x hotspot x coordinate
17244     * @param y hotspot y coordinate
17245     * @see #drawableHotspotChanged(float, float)
17246     */
17247    public void dispatchDrawableHotspotChanged(float x, float y) {
17248    }
17249
17250    /**
17251     * Call this to force a view to update its drawable state. This will cause
17252     * drawableStateChanged to be called on this view. Views that are interested
17253     * in the new state should call getDrawableState.
17254     *
17255     * @see #drawableStateChanged
17256     * @see #getDrawableState
17257     */
17258    public void refreshDrawableState() {
17259        mPrivateFlags |= PFLAG_DRAWABLE_STATE_DIRTY;
17260        drawableStateChanged();
17261
17262        ViewParent parent = mParent;
17263        if (parent != null) {
17264            parent.childDrawableStateChanged(this);
17265        }
17266    }
17267
17268    /**
17269     * Return an array of resource IDs of the drawable states representing the
17270     * current state of the view.
17271     *
17272     * @return The current drawable state
17273     *
17274     * @see Drawable#setState(int[])
17275     * @see #drawableStateChanged()
17276     * @see #onCreateDrawableState(int)
17277     */
17278    public final int[] getDrawableState() {
17279        if ((mDrawableState != null) && ((mPrivateFlags & PFLAG_DRAWABLE_STATE_DIRTY) == 0)) {
17280            return mDrawableState;
17281        } else {
17282            mDrawableState = onCreateDrawableState(0);
17283            mPrivateFlags &= ~PFLAG_DRAWABLE_STATE_DIRTY;
17284            return mDrawableState;
17285        }
17286    }
17287
17288    /**
17289     * Generate the new {@link android.graphics.drawable.Drawable} state for
17290     * this view. This is called by the view
17291     * system when the cached Drawable state is determined to be invalid.  To
17292     * retrieve the current state, you should use {@link #getDrawableState}.
17293     *
17294     * @param extraSpace if non-zero, this is the number of extra entries you
17295     * would like in the returned array in which you can place your own
17296     * states.
17297     *
17298     * @return Returns an array holding the current {@link Drawable} state of
17299     * the view.
17300     *
17301     * @see #mergeDrawableStates(int[], int[])
17302     */
17303    protected int[] onCreateDrawableState(int extraSpace) {
17304        if ((mViewFlags & DUPLICATE_PARENT_STATE) == DUPLICATE_PARENT_STATE &&
17305                mParent instanceof View) {
17306            return ((View) mParent).onCreateDrawableState(extraSpace);
17307        }
17308
17309        int[] drawableState;
17310
17311        int privateFlags = mPrivateFlags;
17312
17313        int viewStateIndex = 0;
17314        if ((privateFlags & PFLAG_PRESSED) != 0) viewStateIndex |= StateSet.VIEW_STATE_PRESSED;
17315        if ((mViewFlags & ENABLED_MASK) == ENABLED) viewStateIndex |= StateSet.VIEW_STATE_ENABLED;
17316        if (isFocused()) viewStateIndex |= StateSet.VIEW_STATE_FOCUSED;
17317        if ((privateFlags & PFLAG_SELECTED) != 0) viewStateIndex |= StateSet.VIEW_STATE_SELECTED;
17318        if (hasWindowFocus()) viewStateIndex |= StateSet.VIEW_STATE_WINDOW_FOCUSED;
17319        if ((privateFlags & PFLAG_ACTIVATED) != 0) viewStateIndex |= StateSet.VIEW_STATE_ACTIVATED;
17320        if (mAttachInfo != null && mAttachInfo.mHardwareAccelerationRequested &&
17321                HardwareRenderer.isAvailable()) {
17322            // This is set if HW acceleration is requested, even if the current
17323            // process doesn't allow it.  This is just to allow app preview
17324            // windows to better match their app.
17325            viewStateIndex |= StateSet.VIEW_STATE_ACCELERATED;
17326        }
17327        if ((privateFlags & PFLAG_HOVERED) != 0) viewStateIndex |= StateSet.VIEW_STATE_HOVERED;
17328
17329        final int privateFlags2 = mPrivateFlags2;
17330        if ((privateFlags2 & PFLAG2_DRAG_CAN_ACCEPT) != 0) {
17331            viewStateIndex |= StateSet.VIEW_STATE_DRAG_CAN_ACCEPT;
17332        }
17333        if ((privateFlags2 & PFLAG2_DRAG_HOVERED) != 0) {
17334            viewStateIndex |= StateSet.VIEW_STATE_DRAG_HOVERED;
17335        }
17336
17337        drawableState = StateSet.get(viewStateIndex);
17338
17339        //noinspection ConstantIfStatement
17340        if (false) {
17341            Log.i("View", "drawableStateIndex=" + viewStateIndex);
17342            Log.i("View", toString()
17343                    + " pressed=" + ((privateFlags & PFLAG_PRESSED) != 0)
17344                    + " en=" + ((mViewFlags & ENABLED_MASK) == ENABLED)
17345                    + " fo=" + hasFocus()
17346                    + " sl=" + ((privateFlags & PFLAG_SELECTED) != 0)
17347                    + " wf=" + hasWindowFocus()
17348                    + ": " + Arrays.toString(drawableState));
17349        }
17350
17351        if (extraSpace == 0) {
17352            return drawableState;
17353        }
17354
17355        final int[] fullState;
17356        if (drawableState != null) {
17357            fullState = new int[drawableState.length + extraSpace];
17358            System.arraycopy(drawableState, 0, fullState, 0, drawableState.length);
17359        } else {
17360            fullState = new int[extraSpace];
17361        }
17362
17363        return fullState;
17364    }
17365
17366    /**
17367     * Merge your own state values in <var>additionalState</var> into the base
17368     * state values <var>baseState</var> that were returned by
17369     * {@link #onCreateDrawableState(int)}.
17370     *
17371     * @param baseState The base state values returned by
17372     * {@link #onCreateDrawableState(int)}, which will be modified to also hold your
17373     * own additional state values.
17374     *
17375     * @param additionalState The additional state values you would like
17376     * added to <var>baseState</var>; this array is not modified.
17377     *
17378     * @return As a convenience, the <var>baseState</var> array you originally
17379     * passed into the function is returned.
17380     *
17381     * @see #onCreateDrawableState(int)
17382     */
17383    protected static int[] mergeDrawableStates(int[] baseState, int[] additionalState) {
17384        final int N = baseState.length;
17385        int i = N - 1;
17386        while (i >= 0 && baseState[i] == 0) {
17387            i--;
17388        }
17389        System.arraycopy(additionalState, 0, baseState, i + 1, additionalState.length);
17390        return baseState;
17391    }
17392
17393    /**
17394     * Call {@link Drawable#jumpToCurrentState() Drawable.jumpToCurrentState()}
17395     * on all Drawable objects associated with this view.
17396     * <p>
17397     * Also calls {@link StateListAnimator#jumpToCurrentState()} if there is a StateListAnimator
17398     * attached to this view.
17399     */
17400    @CallSuper
17401    public void jumpDrawablesToCurrentState() {
17402        if (mBackground != null) {
17403            mBackground.jumpToCurrentState();
17404        }
17405        if (mStateListAnimator != null) {
17406            mStateListAnimator.jumpToCurrentState();
17407        }
17408        if (mForegroundInfo != null && mForegroundInfo.mDrawable != null) {
17409            mForegroundInfo.mDrawable.jumpToCurrentState();
17410        }
17411    }
17412
17413    /**
17414     * Sets the background color for this view.
17415     * @param color the color of the background
17416     */
17417    @RemotableViewMethod
17418    public void setBackgroundColor(@ColorInt int color) {
17419        if (mBackground instanceof ColorDrawable) {
17420            ((ColorDrawable) mBackground.mutate()).setColor(color);
17421            computeOpaqueFlags();
17422            mBackgroundResource = 0;
17423        } else {
17424            setBackground(new ColorDrawable(color));
17425        }
17426    }
17427
17428    /**
17429     * Set the background to a given resource. The resource should refer to
17430     * a Drawable object or 0 to remove the background.
17431     * @param resid The identifier of the resource.
17432     *
17433     * @attr ref android.R.styleable#View_background
17434     */
17435    @RemotableViewMethod
17436    public void setBackgroundResource(@DrawableRes int resid) {
17437        if (resid != 0 && resid == mBackgroundResource) {
17438            return;
17439        }
17440
17441        Drawable d = null;
17442        if (resid != 0) {
17443            d = mContext.getDrawable(resid);
17444        }
17445        setBackground(d);
17446
17447        mBackgroundResource = resid;
17448    }
17449
17450    /**
17451     * Set the background to a given Drawable, or remove the background. If the
17452     * background has padding, this View's padding is set to the background's
17453     * padding. However, when a background is removed, this View's padding isn't
17454     * touched. If setting the padding is desired, please use
17455     * {@link #setPadding(int, int, int, int)}.
17456     *
17457     * @param background The Drawable to use as the background, or null to remove the
17458     *        background
17459     */
17460    public void setBackground(Drawable background) {
17461        //noinspection deprecation
17462        setBackgroundDrawable(background);
17463    }
17464
17465    /**
17466     * @deprecated use {@link #setBackground(Drawable)} instead
17467     */
17468    @Deprecated
17469    public void setBackgroundDrawable(Drawable background) {
17470        computeOpaqueFlags();
17471
17472        if (background == mBackground) {
17473            return;
17474        }
17475
17476        boolean requestLayout = false;
17477
17478        mBackgroundResource = 0;
17479
17480        /*
17481         * Regardless of whether we're setting a new background or not, we want
17482         * to clear the previous drawable.
17483         */
17484        if (mBackground != null) {
17485            mBackground.setCallback(null);
17486            unscheduleDrawable(mBackground);
17487        }
17488
17489        if (background != null) {
17490            Rect padding = sThreadLocal.get();
17491            if (padding == null) {
17492                padding = new Rect();
17493                sThreadLocal.set(padding);
17494            }
17495            resetResolvedDrawablesInternal();
17496            background.setLayoutDirection(getLayoutDirection());
17497            if (background.getPadding(padding)) {
17498                resetResolvedPaddingInternal();
17499                switch (background.getLayoutDirection()) {
17500                    case LAYOUT_DIRECTION_RTL:
17501                        mUserPaddingLeftInitial = padding.right;
17502                        mUserPaddingRightInitial = padding.left;
17503                        internalSetPadding(padding.right, padding.top, padding.left, padding.bottom);
17504                        break;
17505                    case LAYOUT_DIRECTION_LTR:
17506                    default:
17507                        mUserPaddingLeftInitial = padding.left;
17508                        mUserPaddingRightInitial = padding.right;
17509                        internalSetPadding(padding.left, padding.top, padding.right, padding.bottom);
17510                }
17511                mLeftPaddingDefined = false;
17512                mRightPaddingDefined = false;
17513            }
17514
17515            // Compare the minimum sizes of the old Drawable and the new.  If there isn't an old or
17516            // if it has a different minimum size, we should layout again
17517            if (mBackground == null
17518                    || mBackground.getMinimumHeight() != background.getMinimumHeight()
17519                    || mBackground.getMinimumWidth() != background.getMinimumWidth()) {
17520                requestLayout = true;
17521            }
17522
17523            background.setCallback(this);
17524            if (background.isStateful()) {
17525                background.setState(getDrawableState());
17526            }
17527            background.setVisible(getVisibility() == VISIBLE, false);
17528            mBackground = background;
17529
17530            applyBackgroundTint();
17531
17532            if ((mPrivateFlags & PFLAG_SKIP_DRAW) != 0) {
17533                mPrivateFlags &= ~PFLAG_SKIP_DRAW;
17534                requestLayout = true;
17535            }
17536        } else {
17537            /* Remove the background */
17538            mBackground = null;
17539            if ((mViewFlags & WILL_NOT_DRAW) != 0
17540                    && (mForegroundInfo == null || mForegroundInfo.mDrawable == null)) {
17541                mPrivateFlags |= PFLAG_SKIP_DRAW;
17542            }
17543
17544            /*
17545             * When the background is set, we try to apply its padding to this
17546             * View. When the background is removed, we don't touch this View's
17547             * padding. This is noted in the Javadocs. Hence, we don't need to
17548             * requestLayout(), the invalidate() below is sufficient.
17549             */
17550
17551            // The old background's minimum size could have affected this
17552            // View's layout, so let's requestLayout
17553            requestLayout = true;
17554        }
17555
17556        computeOpaqueFlags();
17557
17558        if (requestLayout) {
17559            requestLayout();
17560        }
17561
17562        mBackgroundSizeChanged = true;
17563        invalidate(true);
17564    }
17565
17566    /**
17567     * Gets the background drawable
17568     *
17569     * @return The drawable used as the background for this view, if any.
17570     *
17571     * @see #setBackground(Drawable)
17572     *
17573     * @attr ref android.R.styleable#View_background
17574     */
17575    public Drawable getBackground() {
17576        return mBackground;
17577    }
17578
17579    /**
17580     * Applies a tint to the background drawable. Does not modify the current tint
17581     * mode, which is {@link PorterDuff.Mode#SRC_IN} by default.
17582     * <p>
17583     * Subsequent calls to {@link #setBackground(Drawable)} will automatically
17584     * mutate the drawable and apply the specified tint and tint mode using
17585     * {@link Drawable#setTintList(ColorStateList)}.
17586     *
17587     * @param tint the tint to apply, may be {@code null} to clear tint
17588     *
17589     * @attr ref android.R.styleable#View_backgroundTint
17590     * @see #getBackgroundTintList()
17591     * @see Drawable#setTintList(ColorStateList)
17592     */
17593    public void setBackgroundTintList(@Nullable ColorStateList tint) {
17594        if (mBackgroundTint == null) {
17595            mBackgroundTint = new TintInfo();
17596        }
17597        mBackgroundTint.mTintList = tint;
17598        mBackgroundTint.mHasTintList = true;
17599
17600        applyBackgroundTint();
17601    }
17602
17603    /**
17604     * Return the tint applied to the background drawable, if specified.
17605     *
17606     * @return the tint applied to the background drawable
17607     * @attr ref android.R.styleable#View_backgroundTint
17608     * @see #setBackgroundTintList(ColorStateList)
17609     */
17610    @Nullable
17611    public ColorStateList getBackgroundTintList() {
17612        return mBackgroundTint != null ? mBackgroundTint.mTintList : null;
17613    }
17614
17615    /**
17616     * Specifies the blending mode used to apply the tint specified by
17617     * {@link #setBackgroundTintList(ColorStateList)}} to the background
17618     * drawable. The default mode is {@link PorterDuff.Mode#SRC_IN}.
17619     *
17620     * @param tintMode the blending mode used to apply the tint, may be
17621     *                 {@code null} to clear tint
17622     * @attr ref android.R.styleable#View_backgroundTintMode
17623     * @see #getBackgroundTintMode()
17624     * @see Drawable#setTintMode(PorterDuff.Mode)
17625     */
17626    public void setBackgroundTintMode(@Nullable PorterDuff.Mode tintMode) {
17627        if (mBackgroundTint == null) {
17628            mBackgroundTint = new TintInfo();
17629        }
17630        mBackgroundTint.mTintMode = tintMode;
17631        mBackgroundTint.mHasTintMode = true;
17632
17633        applyBackgroundTint();
17634    }
17635
17636    /**
17637     * Return the blending mode used to apply the tint to the background
17638     * drawable, if specified.
17639     *
17640     * @return the blending mode used to apply the tint to the background
17641     *         drawable
17642     * @attr ref android.R.styleable#View_backgroundTintMode
17643     * @see #setBackgroundTintMode(PorterDuff.Mode)
17644     */
17645    @Nullable
17646    public PorterDuff.Mode getBackgroundTintMode() {
17647        return mBackgroundTint != null ? mBackgroundTint.mTintMode : null;
17648    }
17649
17650    private void applyBackgroundTint() {
17651        if (mBackground != null && mBackgroundTint != null) {
17652            final TintInfo tintInfo = mBackgroundTint;
17653            if (tintInfo.mHasTintList || tintInfo.mHasTintMode) {
17654                mBackground = mBackground.mutate();
17655
17656                if (tintInfo.mHasTintList) {
17657                    mBackground.setTintList(tintInfo.mTintList);
17658                }
17659
17660                if (tintInfo.mHasTintMode) {
17661                    mBackground.setTintMode(tintInfo.mTintMode);
17662                }
17663
17664                // The drawable (or one of its children) may not have been
17665                // stateful before applying the tint, so let's try again.
17666                if (mBackground.isStateful()) {
17667                    mBackground.setState(getDrawableState());
17668                }
17669            }
17670        }
17671    }
17672
17673    /**
17674     * Returns the drawable used as the foreground of this View. The
17675     * foreground drawable, if non-null, is always drawn on top of the view's content.
17676     *
17677     * @return a Drawable or null if no foreground was set
17678     *
17679     * @see #onDrawForeground(Canvas)
17680     */
17681    public Drawable getForeground() {
17682        return mForegroundInfo != null ? mForegroundInfo.mDrawable : null;
17683    }
17684
17685    /**
17686     * Supply a Drawable that is to be rendered on top of all of the content in the view.
17687     *
17688     * @param foreground the Drawable to be drawn on top of the children
17689     *
17690     * @attr ref android.R.styleable#View_foreground
17691     */
17692    public void setForeground(Drawable foreground) {
17693        if (mForegroundInfo == null) {
17694            if (foreground == null) {
17695                // Nothing to do.
17696                return;
17697            }
17698            mForegroundInfo = new ForegroundInfo();
17699        }
17700
17701        if (foreground == mForegroundInfo.mDrawable) {
17702            // Nothing to do
17703            return;
17704        }
17705
17706        if (mForegroundInfo.mDrawable != null) {
17707            mForegroundInfo.mDrawable.setCallback(null);
17708            unscheduleDrawable(mForegroundInfo.mDrawable);
17709        }
17710
17711        mForegroundInfo.mDrawable = foreground;
17712        mForegroundInfo.mBoundsChanged = true;
17713        if (foreground != null) {
17714            if ((mPrivateFlags & PFLAG_SKIP_DRAW) != 0) {
17715                mPrivateFlags &= ~PFLAG_SKIP_DRAW;
17716            }
17717            foreground.setCallback(this);
17718            foreground.setLayoutDirection(getLayoutDirection());
17719            if (foreground.isStateful()) {
17720                foreground.setState(getDrawableState());
17721            }
17722            applyForegroundTint();
17723        } else if ((mViewFlags & WILL_NOT_DRAW) != 0 && mBackground == null) {
17724            mPrivateFlags |= PFLAG_SKIP_DRAW;
17725        }
17726        requestLayout();
17727        invalidate();
17728    }
17729
17730    /**
17731     * Magic bit used to support features of framework-internal window decor implementation details.
17732     * This used to live exclusively in FrameLayout.
17733     *
17734     * @return true if the foreground should draw inside the padding region or false
17735     *         if it should draw inset by the view's padding
17736     * @hide internal use only; only used by FrameLayout and internal screen layouts.
17737     */
17738    public boolean isForegroundInsidePadding() {
17739        return mForegroundInfo != null ? mForegroundInfo.mInsidePadding : true;
17740    }
17741
17742    /**
17743     * Describes how the foreground is positioned.
17744     *
17745     * @return foreground gravity.
17746     *
17747     * @see #setForegroundGravity(int)
17748     *
17749     * @attr ref android.R.styleable#View_foregroundGravity
17750     */
17751    public int getForegroundGravity() {
17752        return mForegroundInfo != null ? mForegroundInfo.mGravity
17753                : Gravity.START | Gravity.TOP;
17754    }
17755
17756    /**
17757     * Describes how the foreground is positioned. Defaults to START and TOP.
17758     *
17759     * @param gravity see {@link android.view.Gravity}
17760     *
17761     * @see #getForegroundGravity()
17762     *
17763     * @attr ref android.R.styleable#View_foregroundGravity
17764     */
17765    public void setForegroundGravity(int gravity) {
17766        if (mForegroundInfo == null) {
17767            mForegroundInfo = new ForegroundInfo();
17768        }
17769
17770        if (mForegroundInfo.mGravity != gravity) {
17771            if ((gravity & Gravity.RELATIVE_HORIZONTAL_GRAVITY_MASK) == 0) {
17772                gravity |= Gravity.START;
17773            }
17774
17775            if ((gravity & Gravity.VERTICAL_GRAVITY_MASK) == 0) {
17776                gravity |= Gravity.TOP;
17777            }
17778
17779            mForegroundInfo.mGravity = gravity;
17780            requestLayout();
17781        }
17782    }
17783
17784    /**
17785     * Applies a tint to the foreground drawable. Does not modify the current tint
17786     * mode, which is {@link PorterDuff.Mode#SRC_IN} by default.
17787     * <p>
17788     * Subsequent calls to {@link #setForeground(Drawable)} will automatically
17789     * mutate the drawable and apply the specified tint and tint mode using
17790     * {@link Drawable#setTintList(ColorStateList)}.
17791     *
17792     * @param tint the tint to apply, may be {@code null} to clear tint
17793     *
17794     * @attr ref android.R.styleable#View_foregroundTint
17795     * @see #getForegroundTintList()
17796     * @see Drawable#setTintList(ColorStateList)
17797     */
17798    public void setForegroundTintList(@Nullable ColorStateList tint) {
17799        if (mForegroundInfo == null) {
17800            mForegroundInfo = new ForegroundInfo();
17801        }
17802        if (mForegroundInfo.mTintInfo == null) {
17803            mForegroundInfo.mTintInfo = new TintInfo();
17804        }
17805        mForegroundInfo.mTintInfo.mTintList = tint;
17806        mForegroundInfo.mTintInfo.mHasTintList = true;
17807
17808        applyForegroundTint();
17809    }
17810
17811    /**
17812     * Return the tint applied to the foreground drawable, if specified.
17813     *
17814     * @return the tint applied to the foreground drawable
17815     * @attr ref android.R.styleable#View_foregroundTint
17816     * @see #setForegroundTintList(ColorStateList)
17817     */
17818    @Nullable
17819    public ColorStateList getForegroundTintList() {
17820        return mForegroundInfo != null && mForegroundInfo.mTintInfo != null
17821                ? mForegroundInfo.mTintInfo.mTintList : null;
17822    }
17823
17824    /**
17825     * Specifies the blending mode used to apply the tint specified by
17826     * {@link #setForegroundTintList(ColorStateList)}} to the background
17827     * drawable. The default mode is {@link PorterDuff.Mode#SRC_IN}.
17828     *
17829     * @param tintMode the blending mode used to apply the tint, may be
17830     *                 {@code null} to clear tint
17831     * @attr ref android.R.styleable#View_foregroundTintMode
17832     * @see #getForegroundTintMode()
17833     * @see Drawable#setTintMode(PorterDuff.Mode)
17834     */
17835    public void setForegroundTintMode(@Nullable PorterDuff.Mode tintMode) {
17836        if (mForegroundInfo == null) {
17837            mForegroundInfo = new ForegroundInfo();
17838        }
17839        if (mForegroundInfo.mTintInfo == null) {
17840            mForegroundInfo.mTintInfo = new TintInfo();
17841        }
17842        mForegroundInfo.mTintInfo.mTintMode = tintMode;
17843        mForegroundInfo.mTintInfo.mHasTintMode = true;
17844
17845        applyForegroundTint();
17846    }
17847
17848    /**
17849     * Return the blending mode used to apply the tint to the foreground
17850     * drawable, if specified.
17851     *
17852     * @return the blending mode used to apply the tint to the foreground
17853     *         drawable
17854     * @attr ref android.R.styleable#View_foregroundTintMode
17855     * @see #setForegroundTintMode(PorterDuff.Mode)
17856     */
17857    @Nullable
17858    public PorterDuff.Mode getForegroundTintMode() {
17859        return mForegroundInfo != null && mForegroundInfo.mTintInfo != null
17860                ? mForegroundInfo.mTintInfo.mTintMode : null;
17861    }
17862
17863    private void applyForegroundTint() {
17864        if (mForegroundInfo != null && mForegroundInfo.mDrawable != null
17865                && mForegroundInfo.mTintInfo != null) {
17866            final TintInfo tintInfo = mForegroundInfo.mTintInfo;
17867            if (tintInfo.mHasTintList || tintInfo.mHasTintMode) {
17868                mForegroundInfo.mDrawable = mForegroundInfo.mDrawable.mutate();
17869
17870                if (tintInfo.mHasTintList) {
17871                    mForegroundInfo.mDrawable.setTintList(tintInfo.mTintList);
17872                }
17873
17874                if (tintInfo.mHasTintMode) {
17875                    mForegroundInfo.mDrawable.setTintMode(tintInfo.mTintMode);
17876                }
17877
17878                // The drawable (or one of its children) may not have been
17879                // stateful before applying the tint, so let's try again.
17880                if (mForegroundInfo.mDrawable.isStateful()) {
17881                    mForegroundInfo.mDrawable.setState(getDrawableState());
17882                }
17883            }
17884        }
17885    }
17886
17887    /**
17888     * Draw any foreground content for this view.
17889     *
17890     * <p>Foreground content may consist of scroll bars, a {@link #setForeground foreground}
17891     * drawable or other view-specific decorations. The foreground is drawn on top of the
17892     * primary view content.</p>
17893     *
17894     * @param canvas canvas to draw into
17895     */
17896    public void onDrawForeground(Canvas canvas) {
17897        onDrawScrollIndicators(canvas);
17898        onDrawScrollBars(canvas);
17899
17900        final Drawable foreground = mForegroundInfo != null ? mForegroundInfo.mDrawable : null;
17901        if (foreground != null) {
17902            if (mForegroundInfo.mBoundsChanged) {
17903                mForegroundInfo.mBoundsChanged = false;
17904                final Rect selfBounds = mForegroundInfo.mSelfBounds;
17905                final Rect overlayBounds = mForegroundInfo.mOverlayBounds;
17906
17907                if (mForegroundInfo.mInsidePadding) {
17908                    selfBounds.set(0, 0, getWidth(), getHeight());
17909                } else {
17910                    selfBounds.set(getPaddingLeft(), getPaddingTop(),
17911                            getWidth() - getPaddingRight(), getHeight() - getPaddingBottom());
17912                }
17913
17914                final int ld = getLayoutDirection();
17915                Gravity.apply(mForegroundInfo.mGravity, foreground.getIntrinsicWidth(),
17916                        foreground.getIntrinsicHeight(), selfBounds, overlayBounds, ld);
17917                foreground.setBounds(overlayBounds);
17918            }
17919
17920            foreground.draw(canvas);
17921        }
17922    }
17923
17924    /**
17925     * Sets the padding. The view may add on the space required to display
17926     * the scrollbars, depending on the style and visibility of the scrollbars.
17927     * So the values returned from {@link #getPaddingLeft}, {@link #getPaddingTop},
17928     * {@link #getPaddingRight} and {@link #getPaddingBottom} may be different
17929     * from the values set in this call.
17930     *
17931     * @attr ref android.R.styleable#View_padding
17932     * @attr ref android.R.styleable#View_paddingBottom
17933     * @attr ref android.R.styleable#View_paddingLeft
17934     * @attr ref android.R.styleable#View_paddingRight
17935     * @attr ref android.R.styleable#View_paddingTop
17936     * @param left the left padding in pixels
17937     * @param top the top padding in pixels
17938     * @param right the right padding in pixels
17939     * @param bottom the bottom padding in pixels
17940     */
17941    public void setPadding(int left, int top, int right, int bottom) {
17942        resetResolvedPaddingInternal();
17943
17944        mUserPaddingStart = UNDEFINED_PADDING;
17945        mUserPaddingEnd = UNDEFINED_PADDING;
17946
17947        mUserPaddingLeftInitial = left;
17948        mUserPaddingRightInitial = right;
17949
17950        mLeftPaddingDefined = true;
17951        mRightPaddingDefined = true;
17952
17953        internalSetPadding(left, top, right, bottom);
17954    }
17955
17956    /**
17957     * @hide
17958     */
17959    protected void internalSetPadding(int left, int top, int right, int bottom) {
17960        mUserPaddingLeft = left;
17961        mUserPaddingRight = right;
17962        mUserPaddingBottom = bottom;
17963
17964        final int viewFlags = mViewFlags;
17965        boolean changed = false;
17966
17967        // Common case is there are no scroll bars.
17968        if ((viewFlags & (SCROLLBARS_VERTICAL|SCROLLBARS_HORIZONTAL)) != 0) {
17969            if ((viewFlags & SCROLLBARS_VERTICAL) != 0) {
17970                final int offset = (viewFlags & SCROLLBARS_INSET_MASK) == 0
17971                        ? 0 : getVerticalScrollbarWidth();
17972                switch (mVerticalScrollbarPosition) {
17973                    case SCROLLBAR_POSITION_DEFAULT:
17974                        if (isLayoutRtl()) {
17975                            left += offset;
17976                        } else {
17977                            right += offset;
17978                        }
17979                        break;
17980                    case SCROLLBAR_POSITION_RIGHT:
17981                        right += offset;
17982                        break;
17983                    case SCROLLBAR_POSITION_LEFT:
17984                        left += offset;
17985                        break;
17986                }
17987            }
17988            if ((viewFlags & SCROLLBARS_HORIZONTAL) != 0) {
17989                bottom += (viewFlags & SCROLLBARS_INSET_MASK) == 0
17990                        ? 0 : getHorizontalScrollbarHeight();
17991            }
17992        }
17993
17994        if (mPaddingLeft != left) {
17995            changed = true;
17996            mPaddingLeft = left;
17997        }
17998        if (mPaddingTop != top) {
17999            changed = true;
18000            mPaddingTop = top;
18001        }
18002        if (mPaddingRight != right) {
18003            changed = true;
18004            mPaddingRight = right;
18005        }
18006        if (mPaddingBottom != bottom) {
18007            changed = true;
18008            mPaddingBottom = bottom;
18009        }
18010
18011        if (changed) {
18012            requestLayout();
18013            invalidateOutline();
18014        }
18015    }
18016
18017    /**
18018     * Sets the relative padding. The view may add on the space required to display
18019     * the scrollbars, depending on the style and visibility of the scrollbars.
18020     * So the values returned from {@link #getPaddingStart}, {@link #getPaddingTop},
18021     * {@link #getPaddingEnd} and {@link #getPaddingBottom} may be different
18022     * from the values set in this call.
18023     *
18024     * @attr ref android.R.styleable#View_padding
18025     * @attr ref android.R.styleable#View_paddingBottom
18026     * @attr ref android.R.styleable#View_paddingStart
18027     * @attr ref android.R.styleable#View_paddingEnd
18028     * @attr ref android.R.styleable#View_paddingTop
18029     * @param start the start padding in pixels
18030     * @param top the top padding in pixels
18031     * @param end the end padding in pixels
18032     * @param bottom the bottom padding in pixels
18033     */
18034    public void setPaddingRelative(int start, int top, int end, int bottom) {
18035        resetResolvedPaddingInternal();
18036
18037        mUserPaddingStart = start;
18038        mUserPaddingEnd = end;
18039        mLeftPaddingDefined = true;
18040        mRightPaddingDefined = true;
18041
18042        switch(getLayoutDirection()) {
18043            case LAYOUT_DIRECTION_RTL:
18044                mUserPaddingLeftInitial = end;
18045                mUserPaddingRightInitial = start;
18046                internalSetPadding(end, top, start, bottom);
18047                break;
18048            case LAYOUT_DIRECTION_LTR:
18049            default:
18050                mUserPaddingLeftInitial = start;
18051                mUserPaddingRightInitial = end;
18052                internalSetPadding(start, top, end, bottom);
18053        }
18054    }
18055
18056    /**
18057     * Returns the top padding of this view.
18058     *
18059     * @return the top padding in pixels
18060     */
18061    public int getPaddingTop() {
18062        return mPaddingTop;
18063    }
18064
18065    /**
18066     * Returns the bottom padding of this view. If there are inset and enabled
18067     * scrollbars, this value may include the space required to display the
18068     * scrollbars as well.
18069     *
18070     * @return the bottom padding in pixels
18071     */
18072    public int getPaddingBottom() {
18073        return mPaddingBottom;
18074    }
18075
18076    /**
18077     * Returns the left padding of this view. If there are inset and enabled
18078     * scrollbars, this value may include the space required to display the
18079     * scrollbars as well.
18080     *
18081     * @return the left padding in pixels
18082     */
18083    public int getPaddingLeft() {
18084        if (!isPaddingResolved()) {
18085            resolvePadding();
18086        }
18087        return mPaddingLeft;
18088    }
18089
18090    /**
18091     * Returns the start padding of this view depending on its resolved layout direction.
18092     * If there are inset and enabled scrollbars, this value may include the space
18093     * required to display the scrollbars as well.
18094     *
18095     * @return the start padding in pixels
18096     */
18097    public int getPaddingStart() {
18098        if (!isPaddingResolved()) {
18099            resolvePadding();
18100        }
18101        return (getLayoutDirection() == LAYOUT_DIRECTION_RTL) ?
18102                mPaddingRight : mPaddingLeft;
18103    }
18104
18105    /**
18106     * Returns the right padding of this view. If there are inset and enabled
18107     * scrollbars, this value may include the space required to display the
18108     * scrollbars as well.
18109     *
18110     * @return the right padding in pixels
18111     */
18112    public int getPaddingRight() {
18113        if (!isPaddingResolved()) {
18114            resolvePadding();
18115        }
18116        return mPaddingRight;
18117    }
18118
18119    /**
18120     * Returns the end padding of this view depending on its resolved layout direction.
18121     * If there are inset and enabled scrollbars, this value may include the space
18122     * required to display the scrollbars as well.
18123     *
18124     * @return the end padding in pixels
18125     */
18126    public int getPaddingEnd() {
18127        if (!isPaddingResolved()) {
18128            resolvePadding();
18129        }
18130        return (getLayoutDirection() == LAYOUT_DIRECTION_RTL) ?
18131                mPaddingLeft : mPaddingRight;
18132    }
18133
18134    /**
18135     * Return if the padding has been set through relative values
18136     * {@link #setPaddingRelative(int, int, int, int)} or through
18137     * @attr ref android.R.styleable#View_paddingStart or
18138     * @attr ref android.R.styleable#View_paddingEnd
18139     *
18140     * @return true if the padding is relative or false if it is not.
18141     */
18142    public boolean isPaddingRelative() {
18143        return (mUserPaddingStart != UNDEFINED_PADDING || mUserPaddingEnd != UNDEFINED_PADDING);
18144    }
18145
18146    Insets computeOpticalInsets() {
18147        return (mBackground == null) ? Insets.NONE : mBackground.getOpticalInsets();
18148    }
18149
18150    /**
18151     * @hide
18152     */
18153    public void resetPaddingToInitialValues() {
18154        if (isRtlCompatibilityMode()) {
18155            mPaddingLeft = mUserPaddingLeftInitial;
18156            mPaddingRight = mUserPaddingRightInitial;
18157            return;
18158        }
18159        if (isLayoutRtl()) {
18160            mPaddingLeft = (mUserPaddingEnd >= 0) ? mUserPaddingEnd : mUserPaddingLeftInitial;
18161            mPaddingRight = (mUserPaddingStart >= 0) ? mUserPaddingStart : mUserPaddingRightInitial;
18162        } else {
18163            mPaddingLeft = (mUserPaddingStart >= 0) ? mUserPaddingStart : mUserPaddingLeftInitial;
18164            mPaddingRight = (mUserPaddingEnd >= 0) ? mUserPaddingEnd : mUserPaddingRightInitial;
18165        }
18166    }
18167
18168    /**
18169     * @hide
18170     */
18171    public Insets getOpticalInsets() {
18172        if (mLayoutInsets == null) {
18173            mLayoutInsets = computeOpticalInsets();
18174        }
18175        return mLayoutInsets;
18176    }
18177
18178    /**
18179     * Set this view's optical insets.
18180     *
18181     * <p>This method should be treated similarly to setMeasuredDimension and not as a general
18182     * property. Views that compute their own optical insets should call it as part of measurement.
18183     * This method does not request layout. If you are setting optical insets outside of
18184     * measure/layout itself you will want to call requestLayout() yourself.
18185     * </p>
18186     * @hide
18187     */
18188    public void setOpticalInsets(Insets insets) {
18189        mLayoutInsets = insets;
18190    }
18191
18192    /**
18193     * Changes the selection state of this view. A view can be selected or not.
18194     * Note that selection is not the same as focus. Views are typically
18195     * selected in the context of an AdapterView like ListView or GridView;
18196     * the selected view is the view that is highlighted.
18197     *
18198     * @param selected true if the view must be selected, false otherwise
18199     */
18200    public void setSelected(boolean selected) {
18201        //noinspection DoubleNegation
18202        if (((mPrivateFlags & PFLAG_SELECTED) != 0) != selected) {
18203            mPrivateFlags = (mPrivateFlags & ~PFLAG_SELECTED) | (selected ? PFLAG_SELECTED : 0);
18204            if (!selected) resetPressedState();
18205            invalidate(true);
18206            refreshDrawableState();
18207            dispatchSetSelected(selected);
18208            if (selected) {
18209                sendAccessibilityEvent(AccessibilityEvent.TYPE_VIEW_SELECTED);
18210            } else {
18211                notifyViewAccessibilityStateChangedIfNeeded(
18212                        AccessibilityEvent.CONTENT_CHANGE_TYPE_UNDEFINED);
18213            }
18214        }
18215    }
18216
18217    /**
18218     * Dispatch setSelected to all of this View's children.
18219     *
18220     * @see #setSelected(boolean)
18221     *
18222     * @param selected The new selected state
18223     */
18224    protected void dispatchSetSelected(boolean selected) {
18225    }
18226
18227    /**
18228     * Indicates the selection state of this view.
18229     *
18230     * @return true if the view is selected, false otherwise
18231     */
18232    @ViewDebug.ExportedProperty
18233    public boolean isSelected() {
18234        return (mPrivateFlags & PFLAG_SELECTED) != 0;
18235    }
18236
18237    /**
18238     * Changes the activated state of this view. A view can be activated or not.
18239     * Note that activation is not the same as selection.  Selection is
18240     * a transient property, representing the view (hierarchy) the user is
18241     * currently interacting with.  Activation is a longer-term state that the
18242     * user can move views in and out of.  For example, in a list view with
18243     * single or multiple selection enabled, the views in the current selection
18244     * set are activated.  (Um, yeah, we are deeply sorry about the terminology
18245     * here.)  The activated state is propagated down to children of the view it
18246     * is set on.
18247     *
18248     * @param activated true if the view must be activated, false otherwise
18249     */
18250    public void setActivated(boolean activated) {
18251        //noinspection DoubleNegation
18252        if (((mPrivateFlags & PFLAG_ACTIVATED) != 0) != activated) {
18253            mPrivateFlags = (mPrivateFlags & ~PFLAG_ACTIVATED) | (activated ? PFLAG_ACTIVATED : 0);
18254            invalidate(true);
18255            refreshDrawableState();
18256            dispatchSetActivated(activated);
18257        }
18258    }
18259
18260    /**
18261     * Dispatch setActivated to all of this View's children.
18262     *
18263     * @see #setActivated(boolean)
18264     *
18265     * @param activated The new activated state
18266     */
18267    protected void dispatchSetActivated(boolean activated) {
18268    }
18269
18270    /**
18271     * Indicates the activation state of this view.
18272     *
18273     * @return true if the view is activated, false otherwise
18274     */
18275    @ViewDebug.ExportedProperty
18276    public boolean isActivated() {
18277        return (mPrivateFlags & PFLAG_ACTIVATED) != 0;
18278    }
18279
18280    /**
18281     * Returns the ViewTreeObserver for this view's hierarchy. The view tree
18282     * observer can be used to get notifications when global events, like
18283     * layout, happen.
18284     *
18285     * The returned ViewTreeObserver observer is not guaranteed to remain
18286     * valid for the lifetime of this View. If the caller of this method keeps
18287     * a long-lived reference to ViewTreeObserver, it should always check for
18288     * the return value of {@link ViewTreeObserver#isAlive()}.
18289     *
18290     * @return The ViewTreeObserver for this view's hierarchy.
18291     */
18292    public ViewTreeObserver getViewTreeObserver() {
18293        if (mAttachInfo != null) {
18294            return mAttachInfo.mTreeObserver;
18295        }
18296        if (mFloatingTreeObserver == null) {
18297            mFloatingTreeObserver = new ViewTreeObserver();
18298        }
18299        return mFloatingTreeObserver;
18300    }
18301
18302    /**
18303     * <p>Finds the topmost view in the current view hierarchy.</p>
18304     *
18305     * @return the topmost view containing this view
18306     */
18307    public View getRootView() {
18308        if (mAttachInfo != null) {
18309            final View v = mAttachInfo.mRootView;
18310            if (v != null) {
18311                return v;
18312            }
18313        }
18314
18315        View parent = this;
18316
18317        while (parent.mParent != null && parent.mParent instanceof View) {
18318            parent = (View) parent.mParent;
18319        }
18320
18321        return parent;
18322    }
18323
18324    /**
18325     * Transforms a motion event from view-local coordinates to on-screen
18326     * coordinates.
18327     *
18328     * @param ev the view-local motion event
18329     * @return false if the transformation could not be applied
18330     * @hide
18331     */
18332    public boolean toGlobalMotionEvent(MotionEvent ev) {
18333        final AttachInfo info = mAttachInfo;
18334        if (info == null) {
18335            return false;
18336        }
18337
18338        final Matrix m = info.mTmpMatrix;
18339        m.set(Matrix.IDENTITY_MATRIX);
18340        transformMatrixToGlobal(m);
18341        ev.transform(m);
18342        return true;
18343    }
18344
18345    /**
18346     * Transforms a motion event from on-screen coordinates to view-local
18347     * coordinates.
18348     *
18349     * @param ev the on-screen motion event
18350     * @return false if the transformation could not be applied
18351     * @hide
18352     */
18353    public boolean toLocalMotionEvent(MotionEvent ev) {
18354        final AttachInfo info = mAttachInfo;
18355        if (info == null) {
18356            return false;
18357        }
18358
18359        final Matrix m = info.mTmpMatrix;
18360        m.set(Matrix.IDENTITY_MATRIX);
18361        transformMatrixToLocal(m);
18362        ev.transform(m);
18363        return true;
18364    }
18365
18366    /**
18367     * Modifies the input matrix such that it maps view-local coordinates to
18368     * on-screen coordinates.
18369     *
18370     * @param m input matrix to modify
18371     * @hide
18372     */
18373    public void transformMatrixToGlobal(Matrix m) {
18374        final ViewParent parent = mParent;
18375        if (parent instanceof View) {
18376            final View vp = (View) parent;
18377            vp.transformMatrixToGlobal(m);
18378            m.preTranslate(-vp.mScrollX, -vp.mScrollY);
18379        } else if (parent instanceof ViewRootImpl) {
18380            final ViewRootImpl vr = (ViewRootImpl) parent;
18381            vr.transformMatrixToGlobal(m);
18382            m.preTranslate(0, -vr.mCurScrollY);
18383        }
18384
18385        m.preTranslate(mLeft, mTop);
18386
18387        if (!hasIdentityMatrix()) {
18388            m.preConcat(getMatrix());
18389        }
18390    }
18391
18392    /**
18393     * Modifies the input matrix such that it maps on-screen coordinates to
18394     * view-local coordinates.
18395     *
18396     * @param m input matrix to modify
18397     * @hide
18398     */
18399    public void transformMatrixToLocal(Matrix m) {
18400        final ViewParent parent = mParent;
18401        if (parent instanceof View) {
18402            final View vp = (View) parent;
18403            vp.transformMatrixToLocal(m);
18404            m.postTranslate(vp.mScrollX, vp.mScrollY);
18405        } else if (parent instanceof ViewRootImpl) {
18406            final ViewRootImpl vr = (ViewRootImpl) parent;
18407            vr.transformMatrixToLocal(m);
18408            m.postTranslate(0, vr.mCurScrollY);
18409        }
18410
18411        m.postTranslate(-mLeft, -mTop);
18412
18413        if (!hasIdentityMatrix()) {
18414            m.postConcat(getInverseMatrix());
18415        }
18416    }
18417
18418    /**
18419     * @hide
18420     */
18421    @ViewDebug.ExportedProperty(category = "layout", indexMapping = {
18422            @ViewDebug.IntToString(from = 0, to = "x"),
18423            @ViewDebug.IntToString(from = 1, to = "y")
18424    })
18425    public int[] getLocationOnScreen() {
18426        int[] location = new int[2];
18427        getLocationOnScreen(location);
18428        return location;
18429    }
18430
18431    /**
18432     * <p>Computes the coordinates of this view on the screen. The argument
18433     * must be an array of two integers. After the method returns, the array
18434     * contains the x and y location in that order.</p>
18435     *
18436     * @param location an array of two integers in which to hold the coordinates
18437     */
18438    public void getLocationOnScreen(@Size(2) int[] location) {
18439        getLocationInWindow(location);
18440
18441        final AttachInfo info = mAttachInfo;
18442        if (info != null) {
18443            location[0] += info.mWindowLeft;
18444            location[1] += info.mWindowTop;
18445        }
18446    }
18447
18448    /**
18449     * <p>Computes the coordinates of this view in its window. The argument
18450     * must be an array of two integers. After the method returns, the array
18451     * contains the x and y location in that order.</p>
18452     *
18453     * @param location an array of two integers in which to hold the coordinates
18454     */
18455    public void getLocationInWindow(@Size(2) int[] location) {
18456        if (location == null || location.length < 2) {
18457            throw new IllegalArgumentException("location must be an array of two integers");
18458        }
18459
18460        if (mAttachInfo == null) {
18461            // When the view is not attached to a window, this method does not make sense
18462            location[0] = location[1] = 0;
18463            return;
18464        }
18465
18466        float[] position = mAttachInfo.mTmpTransformLocation;
18467        position[0] = position[1] = 0.0f;
18468
18469        if (!hasIdentityMatrix()) {
18470            getMatrix().mapPoints(position);
18471        }
18472
18473        position[0] += mLeft;
18474        position[1] += mTop;
18475
18476        ViewParent viewParent = mParent;
18477        while (viewParent instanceof View) {
18478            final View view = (View) viewParent;
18479
18480            position[0] -= view.mScrollX;
18481            position[1] -= view.mScrollY;
18482
18483            if (!view.hasIdentityMatrix()) {
18484                view.getMatrix().mapPoints(position);
18485            }
18486
18487            position[0] += view.mLeft;
18488            position[1] += view.mTop;
18489
18490            viewParent = view.mParent;
18491         }
18492
18493        if (viewParent instanceof ViewRootImpl) {
18494            // *cough*
18495            final ViewRootImpl vr = (ViewRootImpl) viewParent;
18496            position[1] -= vr.mCurScrollY;
18497        }
18498
18499        location[0] = (int) (position[0] + 0.5f);
18500        location[1] = (int) (position[1] + 0.5f);
18501    }
18502
18503    /**
18504     * {@hide}
18505     * @param id the id of the view to be found
18506     * @return the view of the specified id, null if cannot be found
18507     */
18508    protected View findViewTraversal(@IdRes int id) {
18509        if (id == mID) {
18510            return this;
18511        }
18512        return null;
18513    }
18514
18515    /**
18516     * {@hide}
18517     * @param tag the tag of the view to be found
18518     * @return the view of specified tag, null if cannot be found
18519     */
18520    protected View findViewWithTagTraversal(Object tag) {
18521        if (tag != null && tag.equals(mTag)) {
18522            return this;
18523        }
18524        return null;
18525    }
18526
18527    /**
18528     * {@hide}
18529     * @param predicate The predicate to evaluate.
18530     * @param childToSkip If not null, ignores this child during the recursive traversal.
18531     * @return The first view that matches the predicate or null.
18532     */
18533    protected View findViewByPredicateTraversal(Predicate<View> predicate, View childToSkip) {
18534        if (predicate.apply(this)) {
18535            return this;
18536        }
18537        return null;
18538    }
18539
18540    /**
18541     * Look for a child view with the given id.  If this view has the given
18542     * id, return this view.
18543     *
18544     * @param id The id to search for.
18545     * @return The view that has the given id in the hierarchy or null
18546     */
18547    @Nullable
18548    public final View findViewById(@IdRes int id) {
18549        if (id < 0) {
18550            return null;
18551        }
18552        return findViewTraversal(id);
18553    }
18554
18555    /**
18556     * Finds a view by its unuque and stable accessibility id.
18557     *
18558     * @param accessibilityId The searched accessibility id.
18559     * @return The found view.
18560     */
18561    final View findViewByAccessibilityId(int accessibilityId) {
18562        if (accessibilityId < 0) {
18563            return null;
18564        }
18565        View view = findViewByAccessibilityIdTraversal(accessibilityId);
18566        if (view != null) {
18567            return view.includeForAccessibility() ? view : null;
18568        }
18569        return null;
18570    }
18571
18572    /**
18573     * Performs the traversal to find a view by its unuque and stable accessibility id.
18574     *
18575     * <strong>Note:</strong>This method does not stop at the root namespace
18576     * boundary since the user can touch the screen at an arbitrary location
18577     * potentially crossing the root namespace bounday which will send an
18578     * accessibility event to accessibility services and they should be able
18579     * to obtain the event source. Also accessibility ids are guaranteed to be
18580     * unique in the window.
18581     *
18582     * @param accessibilityId The accessibility id.
18583     * @return The found view.
18584     *
18585     * @hide
18586     */
18587    public View findViewByAccessibilityIdTraversal(int accessibilityId) {
18588        if (getAccessibilityViewId() == accessibilityId) {
18589            return this;
18590        }
18591        return null;
18592    }
18593
18594    /**
18595     * Look for a child view with the given tag.  If this view has the given
18596     * tag, return this view.
18597     *
18598     * @param tag The tag to search for, using "tag.equals(getTag())".
18599     * @return The View that has the given tag in the hierarchy or null
18600     */
18601    public final View findViewWithTag(Object tag) {
18602        if (tag == null) {
18603            return null;
18604        }
18605        return findViewWithTagTraversal(tag);
18606    }
18607
18608    /**
18609     * {@hide}
18610     * Look for a child view that matches the specified predicate.
18611     * If this view matches the predicate, return this view.
18612     *
18613     * @param predicate The predicate to evaluate.
18614     * @return The first view that matches the predicate or null.
18615     */
18616    public final View findViewByPredicate(Predicate<View> predicate) {
18617        return findViewByPredicateTraversal(predicate, null);
18618    }
18619
18620    /**
18621     * {@hide}
18622     * Look for a child view that matches the specified predicate,
18623     * starting with the specified view and its descendents and then
18624     * recusively searching the ancestors and siblings of that view
18625     * until this view is reached.
18626     *
18627     * This method is useful in cases where the predicate does not match
18628     * a single unique view (perhaps multiple views use the same id)
18629     * and we are trying to find the view that is "closest" in scope to the
18630     * starting view.
18631     *
18632     * @param start The view to start from.
18633     * @param predicate The predicate to evaluate.
18634     * @return The first view that matches the predicate or null.
18635     */
18636    public final View findViewByPredicateInsideOut(View start, Predicate<View> predicate) {
18637        View childToSkip = null;
18638        for (;;) {
18639            View view = start.findViewByPredicateTraversal(predicate, childToSkip);
18640            if (view != null || start == this) {
18641                return view;
18642            }
18643
18644            ViewParent parent = start.getParent();
18645            if (parent == null || !(parent instanceof View)) {
18646                return null;
18647            }
18648
18649            childToSkip = start;
18650            start = (View) parent;
18651        }
18652    }
18653
18654    /**
18655     * Sets the identifier for this view. The identifier does not have to be
18656     * unique in this view's hierarchy. The identifier should be a positive
18657     * number.
18658     *
18659     * @see #NO_ID
18660     * @see #getId()
18661     * @see #findViewById(int)
18662     *
18663     * @param id a number used to identify the view
18664     *
18665     * @attr ref android.R.styleable#View_id
18666     */
18667    public void setId(@IdRes int id) {
18668        mID = id;
18669        if (mID == View.NO_ID && mLabelForId != View.NO_ID) {
18670            mID = generateViewId();
18671        }
18672    }
18673
18674    /**
18675     * {@hide}
18676     *
18677     * @param isRoot true if the view belongs to the root namespace, false
18678     *        otherwise
18679     */
18680    public void setIsRootNamespace(boolean isRoot) {
18681        if (isRoot) {
18682            mPrivateFlags |= PFLAG_IS_ROOT_NAMESPACE;
18683        } else {
18684            mPrivateFlags &= ~PFLAG_IS_ROOT_NAMESPACE;
18685        }
18686    }
18687
18688    /**
18689     * {@hide}
18690     *
18691     * @return true if the view belongs to the root namespace, false otherwise
18692     */
18693    public boolean isRootNamespace() {
18694        return (mPrivateFlags&PFLAG_IS_ROOT_NAMESPACE) != 0;
18695    }
18696
18697    /**
18698     * Returns this view's identifier.
18699     *
18700     * @return a positive integer used to identify the view or {@link #NO_ID}
18701     *         if the view has no ID
18702     *
18703     * @see #setId(int)
18704     * @see #findViewById(int)
18705     * @attr ref android.R.styleable#View_id
18706     */
18707    @IdRes
18708    @ViewDebug.CapturedViewProperty
18709    public int getId() {
18710        return mID;
18711    }
18712
18713    /**
18714     * Returns this view's tag.
18715     *
18716     * @return the Object stored in this view as a tag, or {@code null} if not
18717     *         set
18718     *
18719     * @see #setTag(Object)
18720     * @see #getTag(int)
18721     */
18722    @ViewDebug.ExportedProperty
18723    public Object getTag() {
18724        return mTag;
18725    }
18726
18727    /**
18728     * Sets the tag associated with this view. A tag can be used to mark
18729     * a view in its hierarchy and does not have to be unique within the
18730     * hierarchy. Tags can also be used to store data within a view without
18731     * resorting to another data structure.
18732     *
18733     * @param tag an Object to tag the view with
18734     *
18735     * @see #getTag()
18736     * @see #setTag(int, Object)
18737     */
18738    public void setTag(final Object tag) {
18739        mTag = tag;
18740    }
18741
18742    /**
18743     * Returns the tag associated with this view and the specified key.
18744     *
18745     * @param key The key identifying the tag
18746     *
18747     * @return the Object stored in this view as a tag, or {@code null} if not
18748     *         set
18749     *
18750     * @see #setTag(int, Object)
18751     * @see #getTag()
18752     */
18753    public Object getTag(int key) {
18754        if (mKeyedTags != null) return mKeyedTags.get(key);
18755        return null;
18756    }
18757
18758    /**
18759     * Sets a tag associated with this view and a key. A tag can be used
18760     * to mark a view in its hierarchy and does not have to be unique within
18761     * the hierarchy. Tags can also be used to store data within a view
18762     * without resorting to another data structure.
18763     *
18764     * The specified key should be an id declared in the resources of the
18765     * application to ensure it is unique (see the <a
18766     * href="{@docRoot}guide/topics/resources/more-resources.html#Id">ID resource type</a>).
18767     * Keys identified as belonging to
18768     * the Android framework or not associated with any package will cause
18769     * an {@link IllegalArgumentException} to be thrown.
18770     *
18771     * @param key The key identifying the tag
18772     * @param tag An Object to tag the view with
18773     *
18774     * @throws IllegalArgumentException If they specified key is not valid
18775     *
18776     * @see #setTag(Object)
18777     * @see #getTag(int)
18778     */
18779    public void setTag(int key, final Object tag) {
18780        // If the package id is 0x00 or 0x01, it's either an undefined package
18781        // or a framework id
18782        if ((key >>> 24) < 2) {
18783            throw new IllegalArgumentException("The key must be an application-specific "
18784                    + "resource id.");
18785        }
18786
18787        setKeyedTag(key, tag);
18788    }
18789
18790    /**
18791     * Variation of {@link #setTag(int, Object)} that enforces the key to be a
18792     * framework id.
18793     *
18794     * @hide
18795     */
18796    public void setTagInternal(int key, Object tag) {
18797        if ((key >>> 24) != 0x1) {
18798            throw new IllegalArgumentException("The key must be a framework-specific "
18799                    + "resource id.");
18800        }
18801
18802        setKeyedTag(key, tag);
18803    }
18804
18805    private void setKeyedTag(int key, Object tag) {
18806        if (mKeyedTags == null) {
18807            mKeyedTags = new SparseArray<Object>(2);
18808        }
18809
18810        mKeyedTags.put(key, tag);
18811    }
18812
18813    /**
18814     * Prints information about this view in the log output, with the tag
18815     * {@link #VIEW_LOG_TAG}.
18816     *
18817     * @hide
18818     */
18819    public void debug() {
18820        debug(0);
18821    }
18822
18823    /**
18824     * Prints information about this view in the log output, with the tag
18825     * {@link #VIEW_LOG_TAG}. Each line in the output is preceded with an
18826     * indentation defined by the <code>depth</code>.
18827     *
18828     * @param depth the indentation level
18829     *
18830     * @hide
18831     */
18832    protected void debug(int depth) {
18833        String output = debugIndent(depth - 1);
18834
18835        output += "+ " + this;
18836        int id = getId();
18837        if (id != -1) {
18838            output += " (id=" + id + ")";
18839        }
18840        Object tag = getTag();
18841        if (tag != null) {
18842            output += " (tag=" + tag + ")";
18843        }
18844        Log.d(VIEW_LOG_TAG, output);
18845
18846        if ((mPrivateFlags & PFLAG_FOCUSED) != 0) {
18847            output = debugIndent(depth) + " FOCUSED";
18848            Log.d(VIEW_LOG_TAG, output);
18849        }
18850
18851        output = debugIndent(depth);
18852        output += "frame={" + mLeft + ", " + mTop + ", " + mRight
18853                + ", " + mBottom + "} scroll={" + mScrollX + ", " + mScrollY
18854                + "} ";
18855        Log.d(VIEW_LOG_TAG, output);
18856
18857        if (mPaddingLeft != 0 || mPaddingTop != 0 || mPaddingRight != 0
18858                || mPaddingBottom != 0) {
18859            output = debugIndent(depth);
18860            output += "padding={" + mPaddingLeft + ", " + mPaddingTop
18861                    + ", " + mPaddingRight + ", " + mPaddingBottom + "}";
18862            Log.d(VIEW_LOG_TAG, output);
18863        }
18864
18865        output = debugIndent(depth);
18866        output += "mMeasureWidth=" + mMeasuredWidth +
18867                " mMeasureHeight=" + mMeasuredHeight;
18868        Log.d(VIEW_LOG_TAG, output);
18869
18870        output = debugIndent(depth);
18871        if (mLayoutParams == null) {
18872            output += "BAD! no layout params";
18873        } else {
18874            output = mLayoutParams.debug(output);
18875        }
18876        Log.d(VIEW_LOG_TAG, output);
18877
18878        output = debugIndent(depth);
18879        output += "flags={";
18880        output += View.printFlags(mViewFlags);
18881        output += "}";
18882        Log.d(VIEW_LOG_TAG, output);
18883
18884        output = debugIndent(depth);
18885        output += "privateFlags={";
18886        output += View.printPrivateFlags(mPrivateFlags);
18887        output += "}";
18888        Log.d(VIEW_LOG_TAG, output);
18889    }
18890
18891    /**
18892     * Creates a string of whitespaces used for indentation.
18893     *
18894     * @param depth the indentation level
18895     * @return a String containing (depth * 2 + 3) * 2 white spaces
18896     *
18897     * @hide
18898     */
18899    protected static String debugIndent(int depth) {
18900        StringBuilder spaces = new StringBuilder((depth * 2 + 3) * 2);
18901        for (int i = 0; i < (depth * 2) + 3; i++) {
18902            spaces.append(' ').append(' ');
18903        }
18904        return spaces.toString();
18905    }
18906
18907    /**
18908     * <p>Return the offset of the widget's text baseline from the widget's top
18909     * boundary. If this widget does not support baseline alignment, this
18910     * method returns -1. </p>
18911     *
18912     * @return the offset of the baseline within the widget's bounds or -1
18913     *         if baseline alignment is not supported
18914     */
18915    @ViewDebug.ExportedProperty(category = "layout")
18916    public int getBaseline() {
18917        return -1;
18918    }
18919
18920    /**
18921     * Returns whether the view hierarchy is currently undergoing a layout pass. This
18922     * information is useful to avoid situations such as calling {@link #requestLayout()} during
18923     * a layout pass.
18924     *
18925     * @return whether the view hierarchy is currently undergoing a layout pass
18926     */
18927    public boolean isInLayout() {
18928        ViewRootImpl viewRoot = getViewRootImpl();
18929        return (viewRoot != null && viewRoot.isInLayout());
18930    }
18931
18932    /**
18933     * Call this when something has changed which has invalidated the
18934     * layout of this view. This will schedule a layout pass of the view
18935     * tree. This should not be called while the view hierarchy is currently in a layout
18936     * pass ({@link #isInLayout()}. If layout is happening, the request may be honored at the
18937     * end of the current layout pass (and then layout will run again) or after the current
18938     * frame is drawn and the next layout occurs.
18939     *
18940     * <p>Subclasses which override this method should call the superclass method to
18941     * handle possible request-during-layout errors correctly.</p>
18942     */
18943    @CallSuper
18944    public void requestLayout() {
18945        if (mMeasureCache != null) mMeasureCache.clear();
18946
18947        if (mAttachInfo != null && mAttachInfo.mViewRequestingLayout == null) {
18948            // Only trigger request-during-layout logic if this is the view requesting it,
18949            // not the views in its parent hierarchy
18950            ViewRootImpl viewRoot = getViewRootImpl();
18951            if (viewRoot != null && viewRoot.isInLayout()) {
18952                if (!viewRoot.requestLayoutDuringLayout(this)) {
18953                    return;
18954                }
18955            }
18956            mAttachInfo.mViewRequestingLayout = this;
18957        }
18958
18959        mPrivateFlags |= PFLAG_FORCE_LAYOUT;
18960        mPrivateFlags |= PFLAG_INVALIDATED;
18961
18962        if (mParent != null && !mParent.isLayoutRequested()) {
18963            mParent.requestLayout();
18964        }
18965        if (mAttachInfo != null && mAttachInfo.mViewRequestingLayout == this) {
18966            mAttachInfo.mViewRequestingLayout = null;
18967        }
18968    }
18969
18970    /**
18971     * Forces this view to be laid out during the next layout pass.
18972     * This method does not call requestLayout() or forceLayout()
18973     * on the parent.
18974     */
18975    public void forceLayout() {
18976        if (mMeasureCache != null) mMeasureCache.clear();
18977
18978        mPrivateFlags |= PFLAG_FORCE_LAYOUT;
18979        mPrivateFlags |= PFLAG_INVALIDATED;
18980    }
18981
18982    /**
18983     * <p>
18984     * This is called to find out how big a view should be. The parent
18985     * supplies constraint information in the width and height parameters.
18986     * </p>
18987     *
18988     * <p>
18989     * The actual measurement work of a view is performed in
18990     * {@link #onMeasure(int, int)}, called by this method. Therefore, only
18991     * {@link #onMeasure(int, int)} can and must be overridden by subclasses.
18992     * </p>
18993     *
18994     *
18995     * @param widthMeasureSpec Horizontal space requirements as imposed by the
18996     *        parent
18997     * @param heightMeasureSpec Vertical space requirements as imposed by the
18998     *        parent
18999     *
19000     * @see #onMeasure(int, int)
19001     */
19002    public final void measure(int widthMeasureSpec, int heightMeasureSpec) {
19003        boolean optical = isLayoutModeOptical(this);
19004        if (optical != isLayoutModeOptical(mParent)) {
19005            Insets insets = getOpticalInsets();
19006            int oWidth  = insets.left + insets.right;
19007            int oHeight = insets.top  + insets.bottom;
19008            widthMeasureSpec  = MeasureSpec.adjust(widthMeasureSpec,  optical ? -oWidth  : oWidth);
19009            heightMeasureSpec = MeasureSpec.adjust(heightMeasureSpec, optical ? -oHeight : oHeight);
19010        }
19011
19012        // Suppress sign extension for the low bytes
19013        long key = (long) widthMeasureSpec << 32 | (long) heightMeasureSpec & 0xffffffffL;
19014        if (mMeasureCache == null) mMeasureCache = new LongSparseLongArray(2);
19015
19016        final boolean forceLayout = (mPrivateFlags & PFLAG_FORCE_LAYOUT) == PFLAG_FORCE_LAYOUT;
19017
19018        // Optimize layout by avoiding an extra EXACTLY pass when the view is
19019        // already measured as the correct size. In API 23 and below, this
19020        // extra pass is required to make LinearLayout re-distribute weight.
19021        final boolean specChanged = widthMeasureSpec != mOldWidthMeasureSpec
19022                || heightMeasureSpec != mOldHeightMeasureSpec;
19023        final boolean isSpecExactly = MeasureSpec.getMode(widthMeasureSpec) == MeasureSpec.EXACTLY
19024                && MeasureSpec.getMode(heightMeasureSpec) == MeasureSpec.EXACTLY;
19025        final boolean matchesSpecSize = getMeasuredWidth() == MeasureSpec.getSize(widthMeasureSpec)
19026                && getMeasuredHeight() == MeasureSpec.getSize(heightMeasureSpec);
19027        final boolean needsLayout = specChanged
19028                && (sAlwaysRemeasureExactly || !isSpecExactly || !matchesSpecSize);
19029
19030        if (forceLayout || needsLayout) {
19031            // first clears the measured dimension flag
19032            mPrivateFlags &= ~PFLAG_MEASURED_DIMENSION_SET;
19033
19034            resolveRtlPropertiesIfNeeded();
19035
19036            int cacheIndex = forceLayout ? -1 : mMeasureCache.indexOfKey(key);
19037            if (cacheIndex < 0 || sIgnoreMeasureCache) {
19038                // measure ourselves, this should set the measured dimension flag back
19039                onMeasure(widthMeasureSpec, heightMeasureSpec);
19040                mPrivateFlags3 &= ~PFLAG3_MEASURE_NEEDED_BEFORE_LAYOUT;
19041            } else {
19042                long value = mMeasureCache.valueAt(cacheIndex);
19043                // Casting a long to int drops the high 32 bits, no mask needed
19044                setMeasuredDimensionRaw((int) (value >> 32), (int) value);
19045                mPrivateFlags3 |= PFLAG3_MEASURE_NEEDED_BEFORE_LAYOUT;
19046            }
19047
19048            // flag not set, setMeasuredDimension() was not invoked, we raise
19049            // an exception to warn the developer
19050            if ((mPrivateFlags & PFLAG_MEASURED_DIMENSION_SET) != PFLAG_MEASURED_DIMENSION_SET) {
19051                throw new IllegalStateException("View with id " + getId() + ": "
19052                        + getClass().getName() + "#onMeasure() did not set the"
19053                        + " measured dimension by calling"
19054                        + " setMeasuredDimension()");
19055            }
19056
19057            mPrivateFlags |= PFLAG_LAYOUT_REQUIRED;
19058        }
19059
19060        mOldWidthMeasureSpec = widthMeasureSpec;
19061        mOldHeightMeasureSpec = heightMeasureSpec;
19062
19063        mMeasureCache.put(key, ((long) mMeasuredWidth) << 32 |
19064                (long) mMeasuredHeight & 0xffffffffL); // suppress sign extension
19065    }
19066
19067    /**
19068     * <p>
19069     * Measure the view and its content to determine the measured width and the
19070     * measured height. This method is invoked by {@link #measure(int, int)} and
19071     * should be overridden by subclasses to provide accurate and efficient
19072     * measurement of their contents.
19073     * </p>
19074     *
19075     * <p>
19076     * <strong>CONTRACT:</strong> When overriding this method, you
19077     * <em>must</em> call {@link #setMeasuredDimension(int, int)} to store the
19078     * measured width and height of this view. Failure to do so will trigger an
19079     * <code>IllegalStateException</code>, thrown by
19080     * {@link #measure(int, int)}. Calling the superclass'
19081     * {@link #onMeasure(int, int)} is a valid use.
19082     * </p>
19083     *
19084     * <p>
19085     * The base class implementation of measure defaults to the background size,
19086     * unless a larger size is allowed by the MeasureSpec. Subclasses should
19087     * override {@link #onMeasure(int, int)} to provide better measurements of
19088     * their content.
19089     * </p>
19090     *
19091     * <p>
19092     * If this method is overridden, it is the subclass's responsibility to make
19093     * sure the measured height and width are at least the view's minimum height
19094     * and width ({@link #getSuggestedMinimumHeight()} and
19095     * {@link #getSuggestedMinimumWidth()}).
19096     * </p>
19097     *
19098     * @param widthMeasureSpec horizontal space requirements as imposed by the parent.
19099     *                         The requirements are encoded with
19100     *                         {@link android.view.View.MeasureSpec}.
19101     * @param heightMeasureSpec vertical space requirements as imposed by the parent.
19102     *                         The requirements are encoded with
19103     *                         {@link android.view.View.MeasureSpec}.
19104     *
19105     * @see #getMeasuredWidth()
19106     * @see #getMeasuredHeight()
19107     * @see #setMeasuredDimension(int, int)
19108     * @see #getSuggestedMinimumHeight()
19109     * @see #getSuggestedMinimumWidth()
19110     * @see android.view.View.MeasureSpec#getMode(int)
19111     * @see android.view.View.MeasureSpec#getSize(int)
19112     */
19113    protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
19114        setMeasuredDimension(getDefaultSize(getSuggestedMinimumWidth(), widthMeasureSpec),
19115                getDefaultSize(getSuggestedMinimumHeight(), heightMeasureSpec));
19116    }
19117
19118    /**
19119     * <p>This method must be called by {@link #onMeasure(int, int)} to store the
19120     * measured width and measured height. Failing to do so will trigger an
19121     * exception at measurement time.</p>
19122     *
19123     * @param measuredWidth The measured width of this view.  May be a complex
19124     * bit mask as defined by {@link #MEASURED_SIZE_MASK} and
19125     * {@link #MEASURED_STATE_TOO_SMALL}.
19126     * @param measuredHeight The measured height of this view.  May be a complex
19127     * bit mask as defined by {@link #MEASURED_SIZE_MASK} and
19128     * {@link #MEASURED_STATE_TOO_SMALL}.
19129     */
19130    protected final void setMeasuredDimension(int measuredWidth, int measuredHeight) {
19131        boolean optical = isLayoutModeOptical(this);
19132        if (optical != isLayoutModeOptical(mParent)) {
19133            Insets insets = getOpticalInsets();
19134            int opticalWidth  = insets.left + insets.right;
19135            int opticalHeight = insets.top  + insets.bottom;
19136
19137            measuredWidth  += optical ? opticalWidth  : -opticalWidth;
19138            measuredHeight += optical ? opticalHeight : -opticalHeight;
19139        }
19140        setMeasuredDimensionRaw(measuredWidth, measuredHeight);
19141    }
19142
19143    /**
19144     * Sets the measured dimension without extra processing for things like optical bounds.
19145     * Useful for reapplying consistent values that have already been cooked with adjustments
19146     * for optical bounds, etc. such as those from the measurement cache.
19147     *
19148     * @param measuredWidth The measured width of this view.  May be a complex
19149     * bit mask as defined by {@link #MEASURED_SIZE_MASK} and
19150     * {@link #MEASURED_STATE_TOO_SMALL}.
19151     * @param measuredHeight The measured height of this view.  May be a complex
19152     * bit mask as defined by {@link #MEASURED_SIZE_MASK} and
19153     * {@link #MEASURED_STATE_TOO_SMALL}.
19154     */
19155    private void setMeasuredDimensionRaw(int measuredWidth, int measuredHeight) {
19156        mMeasuredWidth = measuredWidth;
19157        mMeasuredHeight = measuredHeight;
19158
19159        mPrivateFlags |= PFLAG_MEASURED_DIMENSION_SET;
19160    }
19161
19162    /**
19163     * Merge two states as returned by {@link #getMeasuredState()}.
19164     * @param curState The current state as returned from a view or the result
19165     * of combining multiple views.
19166     * @param newState The new view state to combine.
19167     * @return Returns a new integer reflecting the combination of the two
19168     * states.
19169     */
19170    public static int combineMeasuredStates(int curState, int newState) {
19171        return curState | newState;
19172    }
19173
19174    /**
19175     * Version of {@link #resolveSizeAndState(int, int, int)}
19176     * returning only the {@link #MEASURED_SIZE_MASK} bits of the result.
19177     */
19178    public static int resolveSize(int size, int measureSpec) {
19179        return resolveSizeAndState(size, measureSpec, 0) & MEASURED_SIZE_MASK;
19180    }
19181
19182    /**
19183     * Utility to reconcile a desired size and state, with constraints imposed
19184     * by a MeasureSpec. Will take the desired size, unless a different size
19185     * is imposed by the constraints. The returned value is a compound integer,
19186     * with the resolved size in the {@link #MEASURED_SIZE_MASK} bits and
19187     * optionally the bit {@link #MEASURED_STATE_TOO_SMALL} set if the
19188     * resulting size is smaller than the size the view wants to be.
19189     *
19190     * @param size How big the view wants to be.
19191     * @param measureSpec Constraints imposed by the parent.
19192     * @param childMeasuredState Size information bit mask for the view's
19193     *                           children.
19194     * @return Size information bit mask as defined by
19195     *         {@link #MEASURED_SIZE_MASK} and
19196     *         {@link #MEASURED_STATE_TOO_SMALL}.
19197     */
19198    public static int resolveSizeAndState(int size, int measureSpec, int childMeasuredState) {
19199        final int specMode = MeasureSpec.getMode(measureSpec);
19200        final int specSize = MeasureSpec.getSize(measureSpec);
19201        final int result;
19202        switch (specMode) {
19203            case MeasureSpec.AT_MOST:
19204                if (specSize < size) {
19205                    result = specSize | MEASURED_STATE_TOO_SMALL;
19206                } else {
19207                    result = size;
19208                }
19209                break;
19210            case MeasureSpec.EXACTLY:
19211                result = specSize;
19212                break;
19213            case MeasureSpec.UNSPECIFIED:
19214            default:
19215                result = size;
19216        }
19217        return result | (childMeasuredState & MEASURED_STATE_MASK);
19218    }
19219
19220    /**
19221     * Utility to return a default size. Uses the supplied size if the
19222     * MeasureSpec imposed no constraints. Will get larger if allowed
19223     * by the MeasureSpec.
19224     *
19225     * @param size Default size for this view
19226     * @param measureSpec Constraints imposed by the parent
19227     * @return The size this view should be.
19228     */
19229    public static int getDefaultSize(int size, int measureSpec) {
19230        int result = size;
19231        int specMode = MeasureSpec.getMode(measureSpec);
19232        int specSize = MeasureSpec.getSize(measureSpec);
19233
19234        switch (specMode) {
19235        case MeasureSpec.UNSPECIFIED:
19236            result = size;
19237            break;
19238        case MeasureSpec.AT_MOST:
19239        case MeasureSpec.EXACTLY:
19240            result = specSize;
19241            break;
19242        }
19243        return result;
19244    }
19245
19246    /**
19247     * Returns the suggested minimum height that the view should use. This
19248     * returns the maximum of the view's minimum height
19249     * and the background's minimum height
19250     * ({@link android.graphics.drawable.Drawable#getMinimumHeight()}).
19251     * <p>
19252     * When being used in {@link #onMeasure(int, int)}, the caller should still
19253     * ensure the returned height is within the requirements of the parent.
19254     *
19255     * @return The suggested minimum height of the view.
19256     */
19257    protected int getSuggestedMinimumHeight() {
19258        return (mBackground == null) ? mMinHeight : max(mMinHeight, mBackground.getMinimumHeight());
19259
19260    }
19261
19262    /**
19263     * Returns the suggested minimum width that the view should use. This
19264     * returns the maximum of the view's minimum width
19265     * and the background's minimum width
19266     *  ({@link android.graphics.drawable.Drawable#getMinimumWidth()}).
19267     * <p>
19268     * When being used in {@link #onMeasure(int, int)}, the caller should still
19269     * ensure the returned width is within the requirements of the parent.
19270     *
19271     * @return The suggested minimum width of the view.
19272     */
19273    protected int getSuggestedMinimumWidth() {
19274        return (mBackground == null) ? mMinWidth : max(mMinWidth, mBackground.getMinimumWidth());
19275    }
19276
19277    /**
19278     * Returns the minimum height of the view.
19279     *
19280     * @return the minimum height the view will try to be.
19281     *
19282     * @see #setMinimumHeight(int)
19283     *
19284     * @attr ref android.R.styleable#View_minHeight
19285     */
19286    public int getMinimumHeight() {
19287        return mMinHeight;
19288    }
19289
19290    /**
19291     * Sets the minimum height of the view. It is not guaranteed the view will
19292     * be able to achieve this minimum height (for example, if its parent layout
19293     * constrains it with less available height).
19294     *
19295     * @param minHeight The minimum height the view will try to be.
19296     *
19297     * @see #getMinimumHeight()
19298     *
19299     * @attr ref android.R.styleable#View_minHeight
19300     */
19301    public void setMinimumHeight(int minHeight) {
19302        mMinHeight = minHeight;
19303        requestLayout();
19304    }
19305
19306    /**
19307     * Returns the minimum width of the view.
19308     *
19309     * @return the minimum width the view will try to be.
19310     *
19311     * @see #setMinimumWidth(int)
19312     *
19313     * @attr ref android.R.styleable#View_minWidth
19314     */
19315    public int getMinimumWidth() {
19316        return mMinWidth;
19317    }
19318
19319    /**
19320     * Sets the minimum width of the view. It is not guaranteed the view will
19321     * be able to achieve this minimum width (for example, if its parent layout
19322     * constrains it with less available width).
19323     *
19324     * @param minWidth The minimum width the view will try to be.
19325     *
19326     * @see #getMinimumWidth()
19327     *
19328     * @attr ref android.R.styleable#View_minWidth
19329     */
19330    public void setMinimumWidth(int minWidth) {
19331        mMinWidth = minWidth;
19332        requestLayout();
19333
19334    }
19335
19336    /**
19337     * Get the animation currently associated with this view.
19338     *
19339     * @return The animation that is currently playing or
19340     *         scheduled to play for this view.
19341     */
19342    public Animation getAnimation() {
19343        return mCurrentAnimation;
19344    }
19345
19346    /**
19347     * Start the specified animation now.
19348     *
19349     * @param animation the animation to start now
19350     */
19351    public void startAnimation(Animation animation) {
19352        animation.setStartTime(Animation.START_ON_FIRST_FRAME);
19353        setAnimation(animation);
19354        invalidateParentCaches();
19355        invalidate(true);
19356    }
19357
19358    /**
19359     * Cancels any animations for this view.
19360     */
19361    public void clearAnimation() {
19362        if (mCurrentAnimation != null) {
19363            mCurrentAnimation.detach();
19364        }
19365        mCurrentAnimation = null;
19366        invalidateParentIfNeeded();
19367    }
19368
19369    /**
19370     * Sets the next animation to play for this view.
19371     * If you want the animation to play immediately, use
19372     * {@link #startAnimation(android.view.animation.Animation)} instead.
19373     * This method provides allows fine-grained
19374     * control over the start time and invalidation, but you
19375     * must make sure that 1) the animation has a start time set, and
19376     * 2) the view's parent (which controls animations on its children)
19377     * will be invalidated when the animation is supposed to
19378     * start.
19379     *
19380     * @param animation The next animation, or null.
19381     */
19382    public void setAnimation(Animation animation) {
19383        mCurrentAnimation = animation;
19384
19385        if (animation != null) {
19386            // If the screen is off assume the animation start time is now instead of
19387            // the next frame we draw. Keeping the START_ON_FIRST_FRAME start time
19388            // would cause the animation to start when the screen turns back on
19389            if (mAttachInfo != null && mAttachInfo.mDisplayState == Display.STATE_OFF
19390                    && animation.getStartTime() == Animation.START_ON_FIRST_FRAME) {
19391                animation.setStartTime(AnimationUtils.currentAnimationTimeMillis());
19392            }
19393            animation.reset();
19394        }
19395    }
19396
19397    /**
19398     * Invoked by a parent ViewGroup to notify the start of the animation
19399     * currently associated with this view. If you override this method,
19400     * always call super.onAnimationStart();
19401     *
19402     * @see #setAnimation(android.view.animation.Animation)
19403     * @see #getAnimation()
19404     */
19405    @CallSuper
19406    protected void onAnimationStart() {
19407        mPrivateFlags |= PFLAG_ANIMATION_STARTED;
19408    }
19409
19410    /**
19411     * Invoked by a parent ViewGroup to notify the end of the animation
19412     * currently associated with this view. If you override this method,
19413     * always call super.onAnimationEnd();
19414     *
19415     * @see #setAnimation(android.view.animation.Animation)
19416     * @see #getAnimation()
19417     */
19418    @CallSuper
19419    protected void onAnimationEnd() {
19420        mPrivateFlags &= ~PFLAG_ANIMATION_STARTED;
19421    }
19422
19423    /**
19424     * Invoked if there is a Transform that involves alpha. Subclass that can
19425     * draw themselves with the specified alpha should return true, and then
19426     * respect that alpha when their onDraw() is called. If this returns false
19427     * then the view may be redirected to draw into an offscreen buffer to
19428     * fulfill the request, which will look fine, but may be slower than if the
19429     * subclass handles it internally. The default implementation returns false.
19430     *
19431     * @param alpha The alpha (0..255) to apply to the view's drawing
19432     * @return true if the view can draw with the specified alpha.
19433     */
19434    protected boolean onSetAlpha(int alpha) {
19435        return false;
19436    }
19437
19438    /**
19439     * This is used by the RootView to perform an optimization when
19440     * the view hierarchy contains one or several SurfaceView.
19441     * SurfaceView is always considered transparent, but its children are not,
19442     * therefore all View objects remove themselves from the global transparent
19443     * region (passed as a parameter to this function).
19444     *
19445     * @param region The transparent region for this ViewAncestor (window).
19446     *
19447     * @return Returns true if the effective visibility of the view at this
19448     * point is opaque, regardless of the transparent region; returns false
19449     * if it is possible for underlying windows to be seen behind the view.
19450     *
19451     * {@hide}
19452     */
19453    public boolean gatherTransparentRegion(Region region) {
19454        final AttachInfo attachInfo = mAttachInfo;
19455        if (region != null && attachInfo != null) {
19456            final int pflags = mPrivateFlags;
19457            if ((pflags & PFLAG_SKIP_DRAW) == 0) {
19458                // The SKIP_DRAW flag IS NOT set, so this view draws. We need to
19459                // remove it from the transparent region.
19460                final int[] location = attachInfo.mTransparentLocation;
19461                getLocationInWindow(location);
19462                region.op(location[0], location[1], location[0] + mRight - mLeft,
19463                        location[1] + mBottom - mTop, Region.Op.DIFFERENCE);
19464            } else {
19465                if (mBackground != null && mBackground.getOpacity() != PixelFormat.TRANSPARENT) {
19466                    // The SKIP_DRAW flag IS set and the background drawable exists, we remove
19467                    // the background drawable's non-transparent parts from this transparent region.
19468                    applyDrawableToTransparentRegion(mBackground, region);
19469                }
19470                if (mForegroundInfo != null && mForegroundInfo.mDrawable != null
19471                        && mForegroundInfo.mDrawable.getOpacity() != PixelFormat.TRANSPARENT) {
19472                    // Similarly, we remove the foreground drawable's non-transparent parts.
19473                    applyDrawableToTransparentRegion(mForegroundInfo.mDrawable, region);
19474                }
19475            }
19476        }
19477        return true;
19478    }
19479
19480    /**
19481     * Play a sound effect for this view.
19482     *
19483     * <p>The framework will play sound effects for some built in actions, such as
19484     * clicking, but you may wish to play these effects in your widget,
19485     * for instance, for internal navigation.
19486     *
19487     * <p>The sound effect will only be played if sound effects are enabled by the user, and
19488     * {@link #isSoundEffectsEnabled()} is true.
19489     *
19490     * @param soundConstant One of the constants defined in {@link SoundEffectConstants}
19491     */
19492    public void playSoundEffect(int soundConstant) {
19493        if (mAttachInfo == null || mAttachInfo.mRootCallbacks == null || !isSoundEffectsEnabled()) {
19494            return;
19495        }
19496        mAttachInfo.mRootCallbacks.playSoundEffect(soundConstant);
19497    }
19498
19499    /**
19500     * BZZZTT!!1!
19501     *
19502     * <p>Provide haptic feedback to the user for this view.
19503     *
19504     * <p>The framework will provide haptic feedback for some built in actions,
19505     * such as long presses, but you may wish to provide feedback for your
19506     * own widget.
19507     *
19508     * <p>The feedback will only be performed if
19509     * {@link #isHapticFeedbackEnabled()} is true.
19510     *
19511     * @param feedbackConstant One of the constants defined in
19512     * {@link HapticFeedbackConstants}
19513     */
19514    public boolean performHapticFeedback(int feedbackConstant) {
19515        return performHapticFeedback(feedbackConstant, 0);
19516    }
19517
19518    /**
19519     * BZZZTT!!1!
19520     *
19521     * <p>Like {@link #performHapticFeedback(int)}, with additional options.
19522     *
19523     * @param feedbackConstant One of the constants defined in
19524     * {@link HapticFeedbackConstants}
19525     * @param flags Additional flags as per {@link HapticFeedbackConstants}.
19526     */
19527    public boolean performHapticFeedback(int feedbackConstant, int flags) {
19528        if (mAttachInfo == null) {
19529            return false;
19530        }
19531        //noinspection SimplifiableIfStatement
19532        if ((flags & HapticFeedbackConstants.FLAG_IGNORE_VIEW_SETTING) == 0
19533                && !isHapticFeedbackEnabled()) {
19534            return false;
19535        }
19536        return mAttachInfo.mRootCallbacks.performHapticFeedback(feedbackConstant,
19537                (flags & HapticFeedbackConstants.FLAG_IGNORE_GLOBAL_SETTING) != 0);
19538    }
19539
19540    /**
19541     * Request that the visibility of the status bar or other screen/window
19542     * decorations be changed.
19543     *
19544     * <p>This method is used to put the over device UI into temporary modes
19545     * where the user's attention is focused more on the application content,
19546     * by dimming or hiding surrounding system affordances.  This is typically
19547     * used in conjunction with {@link Window#FEATURE_ACTION_BAR_OVERLAY
19548     * Window.FEATURE_ACTION_BAR_OVERLAY}, allowing the applications content
19549     * to be placed behind the action bar (and with these flags other system
19550     * affordances) so that smooth transitions between hiding and showing them
19551     * can be done.
19552     *
19553     * <p>Two representative examples of the use of system UI visibility is
19554     * implementing a content browsing application (like a magazine reader)
19555     * and a video playing application.
19556     *
19557     * <p>The first code shows a typical implementation of a View in a content
19558     * browsing application.  In this implementation, the application goes
19559     * into a content-oriented mode by hiding the status bar and action bar,
19560     * and putting the navigation elements into lights out mode.  The user can
19561     * then interact with content while in this mode.  Such an application should
19562     * provide an easy way for the user to toggle out of the mode (such as to
19563     * check information in the status bar or access notifications).  In the
19564     * implementation here, this is done simply by tapping on the content.
19565     *
19566     * {@sample development/samples/ApiDemos/src/com/example/android/apis/view/ContentBrowserActivity.java
19567     *      content}
19568     *
19569     * <p>This second code sample shows a typical implementation of a View
19570     * in a video playing application.  In this situation, while the video is
19571     * playing the application would like to go into a complete full-screen mode,
19572     * to use as much of the display as possible for the video.  When in this state
19573     * the user can not interact with the application; the system intercepts
19574     * touching on the screen to pop the UI out of full screen mode.  See
19575     * {@link #fitSystemWindows(Rect)} for a sample layout that goes with this code.
19576     *
19577     * {@sample development/samples/ApiDemos/src/com/example/android/apis/view/VideoPlayerActivity.java
19578     *      content}
19579     *
19580     * @param visibility  Bitwise-or of flags {@link #SYSTEM_UI_FLAG_LOW_PROFILE},
19581     * {@link #SYSTEM_UI_FLAG_HIDE_NAVIGATION}, {@link #SYSTEM_UI_FLAG_FULLSCREEN},
19582     * {@link #SYSTEM_UI_FLAG_LAYOUT_STABLE}, {@link #SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION},
19583     * {@link #SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN}, {@link #SYSTEM_UI_FLAG_IMMERSIVE},
19584     * and {@link #SYSTEM_UI_FLAG_IMMERSIVE_STICKY}.
19585     */
19586    public void setSystemUiVisibility(int visibility) {
19587        if (visibility != mSystemUiVisibility) {
19588            mSystemUiVisibility = visibility;
19589            if (mParent != null && mAttachInfo != null && !mAttachInfo.mRecomputeGlobalAttributes) {
19590                mParent.recomputeViewAttributes(this);
19591            }
19592        }
19593    }
19594
19595    /**
19596     * Returns the last {@link #setSystemUiVisibility(int)} that this view has requested.
19597     * @return  Bitwise-or of flags {@link #SYSTEM_UI_FLAG_LOW_PROFILE},
19598     * {@link #SYSTEM_UI_FLAG_HIDE_NAVIGATION}, {@link #SYSTEM_UI_FLAG_FULLSCREEN},
19599     * {@link #SYSTEM_UI_FLAG_LAYOUT_STABLE}, {@link #SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION},
19600     * {@link #SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN}, {@link #SYSTEM_UI_FLAG_IMMERSIVE},
19601     * and {@link #SYSTEM_UI_FLAG_IMMERSIVE_STICKY}.
19602     */
19603    public int getSystemUiVisibility() {
19604        return mSystemUiVisibility;
19605    }
19606
19607    /**
19608     * Returns the current system UI visibility that is currently set for
19609     * the entire window.  This is the combination of the
19610     * {@link #setSystemUiVisibility(int)} values supplied by all of the
19611     * views in the window.
19612     */
19613    public int getWindowSystemUiVisibility() {
19614        return mAttachInfo != null ? mAttachInfo.mSystemUiVisibility : 0;
19615    }
19616
19617    /**
19618     * Override to find out when the window's requested system UI visibility
19619     * has changed, that is the value returned by {@link #getWindowSystemUiVisibility()}.
19620     * This is different from the callbacks received through
19621     * {@link #setOnSystemUiVisibilityChangeListener(OnSystemUiVisibilityChangeListener)}
19622     * in that this is only telling you about the local request of the window,
19623     * not the actual values applied by the system.
19624     */
19625    public void onWindowSystemUiVisibilityChanged(int visible) {
19626    }
19627
19628    /**
19629     * Dispatch callbacks to {@link #onWindowSystemUiVisibilityChanged(int)} down
19630     * the view hierarchy.
19631     */
19632    public void dispatchWindowSystemUiVisiblityChanged(int visible) {
19633        onWindowSystemUiVisibilityChanged(visible);
19634    }
19635
19636    /**
19637     * Set a listener to receive callbacks when the visibility of the system bar changes.
19638     * @param l  The {@link OnSystemUiVisibilityChangeListener} to receive callbacks.
19639     */
19640    public void setOnSystemUiVisibilityChangeListener(OnSystemUiVisibilityChangeListener l) {
19641        getListenerInfo().mOnSystemUiVisibilityChangeListener = l;
19642        if (mParent != null && mAttachInfo != null && !mAttachInfo.mRecomputeGlobalAttributes) {
19643            mParent.recomputeViewAttributes(this);
19644        }
19645    }
19646
19647    /**
19648     * Dispatch callbacks to {@link #setOnSystemUiVisibilityChangeListener} down
19649     * the view hierarchy.
19650     */
19651    public void dispatchSystemUiVisibilityChanged(int visibility) {
19652        ListenerInfo li = mListenerInfo;
19653        if (li != null && li.mOnSystemUiVisibilityChangeListener != null) {
19654            li.mOnSystemUiVisibilityChangeListener.onSystemUiVisibilityChange(
19655                    visibility & PUBLIC_STATUS_BAR_VISIBILITY_MASK);
19656        }
19657    }
19658
19659    boolean updateLocalSystemUiVisibility(int localValue, int localChanges) {
19660        int val = (mSystemUiVisibility&~localChanges) | (localValue&localChanges);
19661        if (val != mSystemUiVisibility) {
19662            setSystemUiVisibility(val);
19663            return true;
19664        }
19665        return false;
19666    }
19667
19668    /** @hide */
19669    public void setDisabledSystemUiVisibility(int flags) {
19670        if (mAttachInfo != null) {
19671            if (mAttachInfo.mDisabledSystemUiVisibility != flags) {
19672                mAttachInfo.mDisabledSystemUiVisibility = flags;
19673                if (mParent != null) {
19674                    mParent.recomputeViewAttributes(this);
19675                }
19676            }
19677        }
19678    }
19679
19680    /**
19681     * Creates an image that the system displays during the drag and drop
19682     * operation. This is called a &quot;drag shadow&quot;. The default implementation
19683     * for a DragShadowBuilder based on a View returns an image that has exactly the same
19684     * appearance as the given View. The default also positions the center of the drag shadow
19685     * directly under the touch point. If no View is provided (the constructor with no parameters
19686     * is used), and {@link #onProvideShadowMetrics(Point,Point) onProvideShadowMetrics()} and
19687     * {@link #onDrawShadow(Canvas) onDrawShadow()} are not overridden, then the
19688     * default is an invisible drag shadow.
19689     * <p>
19690     * You are not required to use the View you provide to the constructor as the basis of the
19691     * drag shadow. The {@link #onDrawShadow(Canvas) onDrawShadow()} method allows you to draw
19692     * anything you want as the drag shadow.
19693     * </p>
19694     * <p>
19695     *  You pass a DragShadowBuilder object to the system when you start the drag. The system
19696     *  calls {@link #onProvideShadowMetrics(Point,Point) onProvideShadowMetrics()} to get the
19697     *  size and position of the drag shadow. It uses this data to construct a
19698     *  {@link android.graphics.Canvas} object, then it calls {@link #onDrawShadow(Canvas) onDrawShadow()}
19699     *  so that your application can draw the shadow image in the Canvas.
19700     * </p>
19701     *
19702     * <div class="special reference">
19703     * <h3>Developer Guides</h3>
19704     * <p>For a guide to implementing drag and drop features, read the
19705     * <a href="{@docRoot}guide/topics/ui/drag-drop.html">Drag and Drop</a> developer guide.</p>
19706     * </div>
19707     */
19708    public static class DragShadowBuilder {
19709        private final WeakReference<View> mView;
19710
19711        /**
19712         * Constructs a shadow image builder based on a View. By default, the resulting drag
19713         * shadow will have the same appearance and dimensions as the View, with the touch point
19714         * over the center of the View.
19715         * @param view A View. Any View in scope can be used.
19716         */
19717        public DragShadowBuilder(View view) {
19718            mView = new WeakReference<View>(view);
19719        }
19720
19721        /**
19722         * Construct a shadow builder object with no associated View.  This
19723         * constructor variant is only useful when the {@link #onProvideShadowMetrics(Point, Point)}
19724         * and {@link #onDrawShadow(Canvas)} methods are also overridden in order
19725         * to supply the drag shadow's dimensions and appearance without
19726         * reference to any View object. If they are not overridden, then the result is an
19727         * invisible drag shadow.
19728         */
19729        public DragShadowBuilder() {
19730            mView = new WeakReference<View>(null);
19731        }
19732
19733        /**
19734         * Returns the View object that had been passed to the
19735         * {@link #View.DragShadowBuilder(View)}
19736         * constructor.  If that View parameter was {@code null} or if the
19737         * {@link #View.DragShadowBuilder()}
19738         * constructor was used to instantiate the builder object, this method will return
19739         * null.
19740         *
19741         * @return The View object associate with this builder object.
19742         */
19743        @SuppressWarnings({"JavadocReference"})
19744        final public View getView() {
19745            return mView.get();
19746        }
19747
19748        /**
19749         * Provides the metrics for the shadow image. These include the dimensions of
19750         * the shadow image, and the point within that shadow that should
19751         * be centered under the touch location while dragging.
19752         * <p>
19753         * The default implementation sets the dimensions of the shadow to be the
19754         * same as the dimensions of the View itself and centers the shadow under
19755         * the touch point.
19756         * </p>
19757         *
19758         * @param shadowSize A {@link android.graphics.Point} containing the width and height
19759         * of the shadow image. Your application must set {@link android.graphics.Point#x} to the
19760         * desired width and must set {@link android.graphics.Point#y} to the desired height of the
19761         * image.
19762         *
19763         * @param shadowTouchPoint A {@link android.graphics.Point} for the position within the
19764         * shadow image that should be underneath the touch point during the drag and drop
19765         * operation. Your application must set {@link android.graphics.Point#x} to the
19766         * X coordinate and {@link android.graphics.Point#y} to the Y coordinate of this position.
19767         */
19768        public void onProvideShadowMetrics(Point shadowSize, Point shadowTouchPoint) {
19769            final View view = mView.get();
19770            if (view != null) {
19771                shadowSize.set(view.getWidth(), view.getHeight());
19772                shadowTouchPoint.set(shadowSize.x / 2, shadowSize.y / 2);
19773            } else {
19774                Log.e(View.VIEW_LOG_TAG, "Asked for drag thumb metrics but no view");
19775            }
19776        }
19777
19778        /**
19779         * Draws the shadow image. The system creates the {@link android.graphics.Canvas} object
19780         * based on the dimensions it received from the
19781         * {@link #onProvideShadowMetrics(Point, Point)} callback.
19782         *
19783         * @param canvas A {@link android.graphics.Canvas} object in which to draw the shadow image.
19784         */
19785        public void onDrawShadow(Canvas canvas) {
19786            final View view = mView.get();
19787            if (view != null) {
19788                view.draw(canvas);
19789            } else {
19790                Log.e(View.VIEW_LOG_TAG, "Asked to draw drag shadow but no view");
19791            }
19792        }
19793    }
19794
19795    /**
19796     * Starts a drag and drop operation. When your application calls this method, it passes a
19797     * {@link android.view.View.DragShadowBuilder} object to the system. The
19798     * system calls this object's {@link DragShadowBuilder#onProvideShadowMetrics(Point, Point)}
19799     * to get metrics for the drag shadow, and then calls the object's
19800     * {@link DragShadowBuilder#onDrawShadow(Canvas)} to draw the drag shadow itself.
19801     * <p>
19802     *  Once the system has the drag shadow, it begins the drag and drop operation by sending
19803     *  drag events to all the View objects in your application that are currently visible. It does
19804     *  this either by calling the View object's drag listener (an implementation of
19805     *  {@link android.view.View.OnDragListener#onDrag(View,DragEvent) onDrag()} or by calling the
19806     *  View object's {@link android.view.View#onDragEvent(DragEvent) onDragEvent()} method.
19807     *  Both are passed a {@link android.view.DragEvent} object that has a
19808     *  {@link android.view.DragEvent#getAction()} value of
19809     *  {@link android.view.DragEvent#ACTION_DRAG_STARTED}.
19810     * </p>
19811     * <p>
19812     * Your application can invoke startDrag() on any attached View object. The View object does not
19813     * need to be the one used in {@link android.view.View.DragShadowBuilder}, nor does it need to
19814     * be related to the View the user selected for dragging.
19815     * </p>
19816     * @param data A {@link android.content.ClipData} object pointing to the data to be
19817     * transferred by the drag and drop operation.
19818     * @param shadowBuilder A {@link android.view.View.DragShadowBuilder} object for building the
19819     * drag shadow.
19820     * @param myLocalState An {@link java.lang.Object} containing local data about the drag and
19821     * drop operation. This Object is put into every DragEvent object sent by the system during the
19822     * current drag.
19823     * <p>
19824     * myLocalState is a lightweight mechanism for the sending information from the dragged View
19825     * to the target Views. For example, it can contain flags that differentiate between a
19826     * a copy operation and a move operation.
19827     * </p>
19828     * @param flags Flags that control the drag and drop operation. No flags are currently defined,
19829     * so the parameter should be set to 0.
19830     * @return {@code true} if the method completes successfully, or
19831     * {@code false} if it fails anywhere. Returning {@code false} means the system was unable to
19832     * do a drag, and so no drag operation is in progress.
19833     */
19834    public final boolean startDrag(ClipData data, DragShadowBuilder shadowBuilder,
19835            Object myLocalState, int flags) {
19836        if (ViewDebug.DEBUG_DRAG) {
19837            Log.d(VIEW_LOG_TAG, "startDrag: data=" + data + " flags=" + flags);
19838        }
19839        boolean okay = false;
19840
19841        Point shadowSize = new Point();
19842        Point shadowTouchPoint = new Point();
19843        shadowBuilder.onProvideShadowMetrics(shadowSize, shadowTouchPoint);
19844
19845        if ((shadowSize.x < 0) || (shadowSize.y < 0) ||
19846                (shadowTouchPoint.x < 0) || (shadowTouchPoint.y < 0)) {
19847            throw new IllegalStateException("Drag shadow dimensions must not be negative");
19848        }
19849
19850        if (ViewDebug.DEBUG_DRAG) {
19851            Log.d(VIEW_LOG_TAG, "drag shadow: width=" + shadowSize.x + " height=" + shadowSize.y
19852                    + " shadowX=" + shadowTouchPoint.x + " shadowY=" + shadowTouchPoint.y);
19853        }
19854        Surface surface = new Surface();
19855        try {
19856            IBinder token = mAttachInfo.mSession.prepareDrag(mAttachInfo.mWindow,
19857                    flags, shadowSize.x, shadowSize.y, surface);
19858            if (ViewDebug.DEBUG_DRAG) Log.d(VIEW_LOG_TAG, "prepareDrag returned token=" + token
19859                    + " surface=" + surface);
19860            if (token != null) {
19861                Canvas canvas = surface.lockCanvas(null);
19862                try {
19863                    canvas.drawColor(0, PorterDuff.Mode.CLEAR);
19864                    shadowBuilder.onDrawShadow(canvas);
19865                } finally {
19866                    surface.unlockCanvasAndPost(canvas);
19867                }
19868
19869                final ViewRootImpl root = getViewRootImpl();
19870
19871                // Cache the local state object for delivery with DragEvents
19872                root.setLocalDragState(myLocalState);
19873
19874                // repurpose 'shadowSize' for the last touch point
19875                root.getLastTouchPoint(shadowSize);
19876
19877                okay = mAttachInfo.mSession.performDrag(mAttachInfo.mWindow, token,
19878                        shadowSize.x, shadowSize.y,
19879                        shadowTouchPoint.x, shadowTouchPoint.y, data);
19880                if (ViewDebug.DEBUG_DRAG) Log.d(VIEW_LOG_TAG, "performDrag returned " + okay);
19881
19882                // Off and running!  Release our local surface instance; the drag
19883                // shadow surface is now managed by the system process.
19884                surface.release();
19885            }
19886        } catch (Exception e) {
19887            Log.e(VIEW_LOG_TAG, "Unable to initiate drag", e);
19888            surface.destroy();
19889        }
19890
19891        return okay;
19892    }
19893
19894    /**
19895     * Starts a move from {startX, startY}, the amount of the movement will be the offset
19896     * between {startX, startY} and the new cursor positon.
19897     * @param startX horizontal coordinate where the move started.
19898     * @param startY vertical coordinate where the move started.
19899     * @return whether moving was started successfully.
19900     * @hide
19901     */
19902    public final boolean startMovingTask(float startX, float startY) {
19903        if (ViewDebug.DEBUG_POSITIONING) {
19904            Log.d(VIEW_LOG_TAG, "startMovingTask: {" + startX + "," + startY + "}");
19905        }
19906        try {
19907            return mAttachInfo.mSession.startMovingTask(mAttachInfo.mWindow, startX, startY);
19908        } catch (RemoteException e) {
19909            Log.e(VIEW_LOG_TAG, "Unable to start moving", e);
19910        }
19911        return false;
19912    }
19913
19914    /**
19915     * Handles drag events sent by the system following a call to
19916     * {@link android.view.View#startDrag(ClipData,DragShadowBuilder,Object,int) startDrag()}.
19917     *<p>
19918     * When the system calls this method, it passes a
19919     * {@link android.view.DragEvent} object. A call to
19920     * {@link android.view.DragEvent#getAction()} returns one of the action type constants defined
19921     * in DragEvent. The method uses these to determine what is happening in the drag and drop
19922     * operation.
19923     * @param event The {@link android.view.DragEvent} sent by the system.
19924     * The {@link android.view.DragEvent#getAction()} method returns an action type constant defined
19925     * in DragEvent, indicating the type of drag event represented by this object.
19926     * @return {@code true} if the method was successful, otherwise {@code false}.
19927     * <p>
19928     *  The method should return {@code true} in response to an action type of
19929     *  {@link android.view.DragEvent#ACTION_DRAG_STARTED} to receive drag events for the current
19930     *  operation.
19931     * </p>
19932     * <p>
19933     *  The method should also return {@code true} in response to an action type of
19934     *  {@link android.view.DragEvent#ACTION_DROP} if it consumed the drop, or
19935     *  {@code false} if it didn't.
19936     * </p>
19937     */
19938    public boolean onDragEvent(DragEvent event) {
19939        return false;
19940    }
19941
19942    /**
19943     * Detects if this View is enabled and has a drag event listener.
19944     * If both are true, then it calls the drag event listener with the
19945     * {@link android.view.DragEvent} it received. If the drag event listener returns
19946     * {@code true}, then dispatchDragEvent() returns {@code true}.
19947     * <p>
19948     * For all other cases, the method calls the
19949     * {@link android.view.View#onDragEvent(DragEvent) onDragEvent()} drag event handler
19950     * method and returns its result.
19951     * </p>
19952     * <p>
19953     * This ensures that a drag event is always consumed, even if the View does not have a drag
19954     * event listener. However, if the View has a listener and the listener returns true, then
19955     * onDragEvent() is not called.
19956     * </p>
19957     */
19958    public boolean dispatchDragEvent(DragEvent event) {
19959        ListenerInfo li = mListenerInfo;
19960        //noinspection SimplifiableIfStatement
19961        if (li != null && li.mOnDragListener != null && (mViewFlags & ENABLED_MASK) == ENABLED
19962                && li.mOnDragListener.onDrag(this, event)) {
19963            return true;
19964        }
19965        return onDragEvent(event);
19966    }
19967
19968    boolean canAcceptDrag() {
19969        return (mPrivateFlags2 & PFLAG2_DRAG_CAN_ACCEPT) != 0;
19970    }
19971
19972    /**
19973     * This needs to be a better API (NOT ON VIEW) before it is exposed.  If
19974     * it is ever exposed at all.
19975     * @hide
19976     */
19977    public void onCloseSystemDialogs(String reason) {
19978    }
19979
19980    /**
19981     * Given a Drawable whose bounds have been set to draw into this view,
19982     * update a Region being computed for
19983     * {@link #gatherTransparentRegion(android.graphics.Region)} so
19984     * that any non-transparent parts of the Drawable are removed from the
19985     * given transparent region.
19986     *
19987     * @param dr The Drawable whose transparency is to be applied to the region.
19988     * @param region A Region holding the current transparency information,
19989     * where any parts of the region that are set are considered to be
19990     * transparent.  On return, this region will be modified to have the
19991     * transparency information reduced by the corresponding parts of the
19992     * Drawable that are not transparent.
19993     * {@hide}
19994     */
19995    public void applyDrawableToTransparentRegion(Drawable dr, Region region) {
19996        if (DBG) {
19997            Log.i("View", "Getting transparent region for: " + this);
19998        }
19999        final Region r = dr.getTransparentRegion();
20000        final Rect db = dr.getBounds();
20001        final AttachInfo attachInfo = mAttachInfo;
20002        if (r != null && attachInfo != null) {
20003            final int w = getRight()-getLeft();
20004            final int h = getBottom()-getTop();
20005            if (db.left > 0) {
20006                //Log.i("VIEW", "Drawable left " + db.left + " > view 0");
20007                r.op(0, 0, db.left, h, Region.Op.UNION);
20008            }
20009            if (db.right < w) {
20010                //Log.i("VIEW", "Drawable right " + db.right + " < view " + w);
20011                r.op(db.right, 0, w, h, Region.Op.UNION);
20012            }
20013            if (db.top > 0) {
20014                //Log.i("VIEW", "Drawable top " + db.top + " > view 0");
20015                r.op(0, 0, w, db.top, Region.Op.UNION);
20016            }
20017            if (db.bottom < h) {
20018                //Log.i("VIEW", "Drawable bottom " + db.bottom + " < view " + h);
20019                r.op(0, db.bottom, w, h, Region.Op.UNION);
20020            }
20021            final int[] location = attachInfo.mTransparentLocation;
20022            getLocationInWindow(location);
20023            r.translate(location[0], location[1]);
20024            region.op(r, Region.Op.INTERSECT);
20025        } else {
20026            region.op(db, Region.Op.DIFFERENCE);
20027        }
20028    }
20029
20030    private void checkForLongClick(int delayOffset) {
20031        if ((mViewFlags & LONG_CLICKABLE) == LONG_CLICKABLE) {
20032            mHasPerformedLongPress = false;
20033
20034            if (mPendingCheckForLongPress == null) {
20035                mPendingCheckForLongPress = new CheckForLongPress();
20036            }
20037            mPendingCheckForLongPress.rememberWindowAttachCount();
20038            postDelayed(mPendingCheckForLongPress,
20039                    ViewConfiguration.getLongPressTimeout() - delayOffset);
20040        }
20041    }
20042
20043    /**
20044     * Inflate a view from an XML resource.  This convenience method wraps the {@link
20045     * LayoutInflater} class, which provides a full range of options for view inflation.
20046     *
20047     * @param context The Context object for your activity or application.
20048     * @param resource The resource ID to inflate
20049     * @param root A view group that will be the parent.  Used to properly inflate the
20050     * layout_* parameters.
20051     * @see LayoutInflater
20052     */
20053    public static View inflate(Context context, @LayoutRes int resource, ViewGroup root) {
20054        LayoutInflater factory = LayoutInflater.from(context);
20055        return factory.inflate(resource, root);
20056    }
20057
20058    /**
20059     * Scroll the view with standard behavior for scrolling beyond the normal
20060     * content boundaries. Views that call this method should override
20061     * {@link #onOverScrolled(int, int, boolean, boolean)} to respond to the
20062     * results of an over-scroll operation.
20063     *
20064     * Views can use this method to handle any touch or fling-based scrolling.
20065     *
20066     * @param deltaX Change in X in pixels
20067     * @param deltaY Change in Y in pixels
20068     * @param scrollX Current X scroll value in pixels before applying deltaX
20069     * @param scrollY Current Y scroll value in pixels before applying deltaY
20070     * @param scrollRangeX Maximum content scroll range along the X axis
20071     * @param scrollRangeY Maximum content scroll range along the Y axis
20072     * @param maxOverScrollX Number of pixels to overscroll by in either direction
20073     *          along the X axis.
20074     * @param maxOverScrollY Number of pixels to overscroll by in either direction
20075     *          along the Y axis.
20076     * @param isTouchEvent true if this scroll operation is the result of a touch event.
20077     * @return true if scrolling was clamped to an over-scroll boundary along either
20078     *          axis, false otherwise.
20079     */
20080    @SuppressWarnings({"UnusedParameters"})
20081    protected boolean overScrollBy(int deltaX, int deltaY,
20082            int scrollX, int scrollY,
20083            int scrollRangeX, int scrollRangeY,
20084            int maxOverScrollX, int maxOverScrollY,
20085            boolean isTouchEvent) {
20086        final int overScrollMode = mOverScrollMode;
20087        final boolean canScrollHorizontal =
20088                computeHorizontalScrollRange() > computeHorizontalScrollExtent();
20089        final boolean canScrollVertical =
20090                computeVerticalScrollRange() > computeVerticalScrollExtent();
20091        final boolean overScrollHorizontal = overScrollMode == OVER_SCROLL_ALWAYS ||
20092                (overScrollMode == OVER_SCROLL_IF_CONTENT_SCROLLS && canScrollHorizontal);
20093        final boolean overScrollVertical = overScrollMode == OVER_SCROLL_ALWAYS ||
20094                (overScrollMode == OVER_SCROLL_IF_CONTENT_SCROLLS && canScrollVertical);
20095
20096        int newScrollX = scrollX + deltaX;
20097        if (!overScrollHorizontal) {
20098            maxOverScrollX = 0;
20099        }
20100
20101        int newScrollY = scrollY + deltaY;
20102        if (!overScrollVertical) {
20103            maxOverScrollY = 0;
20104        }
20105
20106        // Clamp values if at the limits and record
20107        final int left = -maxOverScrollX;
20108        final int right = maxOverScrollX + scrollRangeX;
20109        final int top = -maxOverScrollY;
20110        final int bottom = maxOverScrollY + scrollRangeY;
20111
20112        boolean clampedX = false;
20113        if (newScrollX > right) {
20114            newScrollX = right;
20115            clampedX = true;
20116        } else if (newScrollX < left) {
20117            newScrollX = left;
20118            clampedX = true;
20119        }
20120
20121        boolean clampedY = false;
20122        if (newScrollY > bottom) {
20123            newScrollY = bottom;
20124            clampedY = true;
20125        } else if (newScrollY < top) {
20126            newScrollY = top;
20127            clampedY = true;
20128        }
20129
20130        onOverScrolled(newScrollX, newScrollY, clampedX, clampedY);
20131
20132        return clampedX || clampedY;
20133    }
20134
20135    /**
20136     * Called by {@link #overScrollBy(int, int, int, int, int, int, int, int, boolean)} to
20137     * respond to the results of an over-scroll operation.
20138     *
20139     * @param scrollX New X scroll value in pixels
20140     * @param scrollY New Y scroll value in pixels
20141     * @param clampedX True if scrollX was clamped to an over-scroll boundary
20142     * @param clampedY True if scrollY was clamped to an over-scroll boundary
20143     */
20144    protected void onOverScrolled(int scrollX, int scrollY,
20145            boolean clampedX, boolean clampedY) {
20146        // Intentionally empty.
20147    }
20148
20149    /**
20150     * Returns the over-scroll mode for this view. The result will be
20151     * one of {@link #OVER_SCROLL_ALWAYS} (default), {@link #OVER_SCROLL_IF_CONTENT_SCROLLS}
20152     * (allow over-scrolling only if the view content is larger than the container),
20153     * or {@link #OVER_SCROLL_NEVER}.
20154     *
20155     * @return This view's over-scroll mode.
20156     */
20157    public int getOverScrollMode() {
20158        return mOverScrollMode;
20159    }
20160
20161    /**
20162     * Set the over-scroll mode for this view. Valid over-scroll modes are
20163     * {@link #OVER_SCROLL_ALWAYS} (default), {@link #OVER_SCROLL_IF_CONTENT_SCROLLS}
20164     * (allow over-scrolling only if the view content is larger than the container),
20165     * or {@link #OVER_SCROLL_NEVER}.
20166     *
20167     * Setting the over-scroll mode of a view will have an effect only if the
20168     * view is capable of scrolling.
20169     *
20170     * @param overScrollMode The new over-scroll mode for this view.
20171     */
20172    public void setOverScrollMode(int overScrollMode) {
20173        if (overScrollMode != OVER_SCROLL_ALWAYS &&
20174                overScrollMode != OVER_SCROLL_IF_CONTENT_SCROLLS &&
20175                overScrollMode != OVER_SCROLL_NEVER) {
20176            throw new IllegalArgumentException("Invalid overscroll mode " + overScrollMode);
20177        }
20178        mOverScrollMode = overScrollMode;
20179    }
20180
20181    /**
20182     * Enable or disable nested scrolling for this view.
20183     *
20184     * <p>If this property is set to true the view will be permitted to initiate nested
20185     * scrolling operations with a compatible parent view in the current hierarchy. If this
20186     * view does not implement nested scrolling this will have no effect. Disabling nested scrolling
20187     * while a nested scroll is in progress has the effect of {@link #stopNestedScroll() stopping}
20188     * the nested scroll.</p>
20189     *
20190     * @param enabled true to enable nested scrolling, false to disable
20191     *
20192     * @see #isNestedScrollingEnabled()
20193     */
20194    public void setNestedScrollingEnabled(boolean enabled) {
20195        if (enabled) {
20196            mPrivateFlags3 |= PFLAG3_NESTED_SCROLLING_ENABLED;
20197        } else {
20198            stopNestedScroll();
20199            mPrivateFlags3 &= ~PFLAG3_NESTED_SCROLLING_ENABLED;
20200        }
20201    }
20202
20203    /**
20204     * Returns true if nested scrolling is enabled for this view.
20205     *
20206     * <p>If nested scrolling is enabled and this View class implementation supports it,
20207     * this view will act as a nested scrolling child view when applicable, forwarding data
20208     * about the scroll operation in progress to a compatible and cooperating nested scrolling
20209     * parent.</p>
20210     *
20211     * @return true if nested scrolling is enabled
20212     *
20213     * @see #setNestedScrollingEnabled(boolean)
20214     */
20215    public boolean isNestedScrollingEnabled() {
20216        return (mPrivateFlags3 & PFLAG3_NESTED_SCROLLING_ENABLED) ==
20217                PFLAG3_NESTED_SCROLLING_ENABLED;
20218    }
20219
20220    /**
20221     * Begin a nestable scroll operation along the given axes.
20222     *
20223     * <p>A view starting a nested scroll promises to abide by the following contract:</p>
20224     *
20225     * <p>The view will call startNestedScroll upon initiating a scroll operation. In the case
20226     * of a touch scroll this corresponds to the initial {@link MotionEvent#ACTION_DOWN}.
20227     * In the case of touch scrolling the nested scroll will be terminated automatically in
20228     * the same manner as {@link ViewParent#requestDisallowInterceptTouchEvent(boolean)}.
20229     * In the event of programmatic scrolling the caller must explicitly call
20230     * {@link #stopNestedScroll()} to indicate the end of the nested scroll.</p>
20231     *
20232     * <p>If <code>startNestedScroll</code> returns true, a cooperative parent was found.
20233     * If it returns false the caller may ignore the rest of this contract until the next scroll.
20234     * Calling startNestedScroll while a nested scroll is already in progress will return true.</p>
20235     *
20236     * <p>At each incremental step of the scroll the caller should invoke
20237     * {@link #dispatchNestedPreScroll(int, int, int[], int[]) dispatchNestedPreScroll}
20238     * once it has calculated the requested scrolling delta. If it returns true the nested scrolling
20239     * parent at least partially consumed the scroll and the caller should adjust the amount it
20240     * scrolls by.</p>
20241     *
20242     * <p>After applying the remainder of the scroll delta the caller should invoke
20243     * {@link #dispatchNestedScroll(int, int, int, int, int[]) dispatchNestedScroll}, passing
20244     * both the delta consumed and the delta unconsumed. A nested scrolling parent may treat
20245     * these values differently. See {@link ViewParent#onNestedScroll(View, int, int, int, int)}.
20246     * </p>
20247     *
20248     * @param axes Flags consisting of a combination of {@link #SCROLL_AXIS_HORIZONTAL} and/or
20249     *             {@link #SCROLL_AXIS_VERTICAL}.
20250     * @return true if a cooperative parent was found and nested scrolling has been enabled for
20251     *         the current gesture.
20252     *
20253     * @see #stopNestedScroll()
20254     * @see #dispatchNestedPreScroll(int, int, int[], int[])
20255     * @see #dispatchNestedScroll(int, int, int, int, int[])
20256     */
20257    public boolean startNestedScroll(int axes) {
20258        if (hasNestedScrollingParent()) {
20259            // Already in progress
20260            return true;
20261        }
20262        if (isNestedScrollingEnabled()) {
20263            ViewParent p = getParent();
20264            View child = this;
20265            while (p != null) {
20266                try {
20267                    if (p.onStartNestedScroll(child, this, axes)) {
20268                        mNestedScrollingParent = p;
20269                        p.onNestedScrollAccepted(child, this, axes);
20270                        return true;
20271                    }
20272                } catch (AbstractMethodError e) {
20273                    Log.e(VIEW_LOG_TAG, "ViewParent " + p + " does not implement interface " +
20274                            "method onStartNestedScroll", e);
20275                    // Allow the search upward to continue
20276                }
20277                if (p instanceof View) {
20278                    child = (View) p;
20279                }
20280                p = p.getParent();
20281            }
20282        }
20283        return false;
20284    }
20285
20286    /**
20287     * Stop a nested scroll in progress.
20288     *
20289     * <p>Calling this method when a nested scroll is not currently in progress is harmless.</p>
20290     *
20291     * @see #startNestedScroll(int)
20292     */
20293    public void stopNestedScroll() {
20294        if (mNestedScrollingParent != null) {
20295            mNestedScrollingParent.onStopNestedScroll(this);
20296            mNestedScrollingParent = null;
20297        }
20298    }
20299
20300    /**
20301     * Returns true if this view has a nested scrolling parent.
20302     *
20303     * <p>The presence of a nested scrolling parent indicates that this view has initiated
20304     * a nested scroll and it was accepted by an ancestor view further up the view hierarchy.</p>
20305     *
20306     * @return whether this view has a nested scrolling parent
20307     */
20308    public boolean hasNestedScrollingParent() {
20309        return mNestedScrollingParent != null;
20310    }
20311
20312    /**
20313     * Dispatch one step of a nested scroll in progress.
20314     *
20315     * <p>Implementations of views that support nested scrolling should call this to report
20316     * info about a scroll in progress to the current nested scrolling parent. If a nested scroll
20317     * is not currently in progress or nested scrolling is not
20318     * {@link #isNestedScrollingEnabled() enabled} for this view this method does nothing.</p>
20319     *
20320     * <p>Compatible View implementations should also call
20321     * {@link #dispatchNestedPreScroll(int, int, int[], int[]) dispatchNestedPreScroll} before
20322     * consuming a component of the scroll event themselves.</p>
20323     *
20324     * @param dxConsumed Horizontal distance in pixels consumed by this view during this scroll step
20325     * @param dyConsumed Vertical distance in pixels consumed by this view during this scroll step
20326     * @param dxUnconsumed Horizontal scroll distance in pixels not consumed by this view
20327     * @param dyUnconsumed Horizontal scroll distance in pixels not consumed by this view
20328     * @param offsetInWindow Optional. If not null, on return this will contain the offset
20329     *                       in local view coordinates of this view from before this operation
20330     *                       to after it completes. View implementations may use this to adjust
20331     *                       expected input coordinate tracking.
20332     * @return true if the event was dispatched, false if it could not be dispatched.
20333     * @see #dispatchNestedPreScroll(int, int, int[], int[])
20334     */
20335    public boolean dispatchNestedScroll(int dxConsumed, int dyConsumed,
20336            int dxUnconsumed, int dyUnconsumed, @Nullable @Size(2) int[] offsetInWindow) {
20337        if (isNestedScrollingEnabled() && mNestedScrollingParent != null) {
20338            if (dxConsumed != 0 || dyConsumed != 0 || dxUnconsumed != 0 || dyUnconsumed != 0) {
20339                int startX = 0;
20340                int startY = 0;
20341                if (offsetInWindow != null) {
20342                    getLocationInWindow(offsetInWindow);
20343                    startX = offsetInWindow[0];
20344                    startY = offsetInWindow[1];
20345                }
20346
20347                mNestedScrollingParent.onNestedScroll(this, dxConsumed, dyConsumed,
20348                        dxUnconsumed, dyUnconsumed);
20349
20350                if (offsetInWindow != null) {
20351                    getLocationInWindow(offsetInWindow);
20352                    offsetInWindow[0] -= startX;
20353                    offsetInWindow[1] -= startY;
20354                }
20355                return true;
20356            } else if (offsetInWindow != null) {
20357                // No motion, no dispatch. Keep offsetInWindow up to date.
20358                offsetInWindow[0] = 0;
20359                offsetInWindow[1] = 0;
20360            }
20361        }
20362        return false;
20363    }
20364
20365    /**
20366     * Dispatch one step of a nested scroll in progress before this view consumes any portion of it.
20367     *
20368     * <p>Nested pre-scroll events are to nested scroll events what touch intercept is to touch.
20369     * <code>dispatchNestedPreScroll</code> offers an opportunity for the parent view in a nested
20370     * scrolling operation to consume some or all of the scroll operation before the child view
20371     * consumes it.</p>
20372     *
20373     * @param dx Horizontal scroll distance in pixels
20374     * @param dy Vertical scroll distance in pixels
20375     * @param consumed Output. If not null, consumed[0] will contain the consumed component of dx
20376     *                 and consumed[1] the consumed dy.
20377     * @param offsetInWindow Optional. If not null, on return this will contain the offset
20378     *                       in local view coordinates of this view from before this operation
20379     *                       to after it completes. View implementations may use this to adjust
20380     *                       expected input coordinate tracking.
20381     * @return true if the parent consumed some or all of the scroll delta
20382     * @see #dispatchNestedScroll(int, int, int, int, int[])
20383     */
20384    public boolean dispatchNestedPreScroll(int dx, int dy,
20385            @Nullable @Size(2) int[] consumed, @Nullable @Size(2) int[] offsetInWindow) {
20386        if (isNestedScrollingEnabled() && mNestedScrollingParent != null) {
20387            if (dx != 0 || dy != 0) {
20388                int startX = 0;
20389                int startY = 0;
20390                if (offsetInWindow != null) {
20391                    getLocationInWindow(offsetInWindow);
20392                    startX = offsetInWindow[0];
20393                    startY = offsetInWindow[1];
20394                }
20395
20396                if (consumed == null) {
20397                    if (mTempNestedScrollConsumed == null) {
20398                        mTempNestedScrollConsumed = new int[2];
20399                    }
20400                    consumed = mTempNestedScrollConsumed;
20401                }
20402                consumed[0] = 0;
20403                consumed[1] = 0;
20404                mNestedScrollingParent.onNestedPreScroll(this, dx, dy, consumed);
20405
20406                if (offsetInWindow != null) {
20407                    getLocationInWindow(offsetInWindow);
20408                    offsetInWindow[0] -= startX;
20409                    offsetInWindow[1] -= startY;
20410                }
20411                return consumed[0] != 0 || consumed[1] != 0;
20412            } else if (offsetInWindow != null) {
20413                offsetInWindow[0] = 0;
20414                offsetInWindow[1] = 0;
20415            }
20416        }
20417        return false;
20418    }
20419
20420    /**
20421     * Dispatch a fling to a nested scrolling parent.
20422     *
20423     * <p>This method should be used to indicate that a nested scrolling child has detected
20424     * suitable conditions for a fling. Generally this means that a touch scroll has ended with a
20425     * {@link VelocityTracker velocity} in the direction of scrolling that meets or exceeds
20426     * the {@link ViewConfiguration#getScaledMinimumFlingVelocity() minimum fling velocity}
20427     * along a scrollable axis.</p>
20428     *
20429     * <p>If a nested scrolling child view would normally fling but it is at the edge of
20430     * its own content, it can use this method to delegate the fling to its nested scrolling
20431     * parent instead. The parent may optionally consume the fling or observe a child fling.</p>
20432     *
20433     * @param velocityX Horizontal fling velocity in pixels per second
20434     * @param velocityY Vertical fling velocity in pixels per second
20435     * @param consumed true if the child consumed the fling, false otherwise
20436     * @return true if the nested scrolling parent consumed or otherwise reacted to the fling
20437     */
20438    public boolean dispatchNestedFling(float velocityX, float velocityY, boolean consumed) {
20439        if (isNestedScrollingEnabled() && mNestedScrollingParent != null) {
20440            return mNestedScrollingParent.onNestedFling(this, velocityX, velocityY, consumed);
20441        }
20442        return false;
20443    }
20444
20445    /**
20446     * Dispatch a fling to a nested scrolling parent before it is processed by this view.
20447     *
20448     * <p>Nested pre-fling events are to nested fling events what touch intercept is to touch
20449     * and what nested pre-scroll is to nested scroll. <code>dispatchNestedPreFling</code>
20450     * offsets an opportunity for the parent view in a nested fling to fully consume the fling
20451     * before the child view consumes it. If this method returns <code>true</code>, a nested
20452     * parent view consumed the fling and this view should not scroll as a result.</p>
20453     *
20454     * <p>For a better user experience, only one view in a nested scrolling chain should consume
20455     * the fling at a time. If a parent view consumed the fling this method will return false.
20456     * Custom view implementations should account for this in two ways:</p>
20457     *
20458     * <ul>
20459     *     <li>If a custom view is paged and needs to settle to a fixed page-point, do not
20460     *     call <code>dispatchNestedPreFling</code>; consume the fling and settle to a valid
20461     *     position regardless.</li>
20462     *     <li>If a nested parent does consume the fling, this view should not scroll at all,
20463     *     even to settle back to a valid idle position.</li>
20464     * </ul>
20465     *
20466     * <p>Views should also not offer fling velocities to nested parent views along an axis
20467     * where scrolling is not currently supported; a {@link android.widget.ScrollView ScrollView}
20468     * should not offer a horizontal fling velocity to its parents since scrolling along that
20469     * axis is not permitted and carrying velocity along that motion does not make sense.</p>
20470     *
20471     * @param velocityX Horizontal fling velocity in pixels per second
20472     * @param velocityY Vertical fling velocity in pixels per second
20473     * @return true if a nested scrolling parent consumed the fling
20474     */
20475    public boolean dispatchNestedPreFling(float velocityX, float velocityY) {
20476        if (isNestedScrollingEnabled() && mNestedScrollingParent != null) {
20477            return mNestedScrollingParent.onNestedPreFling(this, velocityX, velocityY);
20478        }
20479        return false;
20480    }
20481
20482    /**
20483     * Gets a scale factor that determines the distance the view should scroll
20484     * vertically in response to {@link MotionEvent#ACTION_SCROLL}.
20485     * @return The vertical scroll scale factor.
20486     * @hide
20487     */
20488    protected float getVerticalScrollFactor() {
20489        if (mVerticalScrollFactor == 0) {
20490            TypedValue outValue = new TypedValue();
20491            if (!mContext.getTheme().resolveAttribute(
20492                    com.android.internal.R.attr.listPreferredItemHeight, outValue, true)) {
20493                throw new IllegalStateException(
20494                        "Expected theme to define listPreferredItemHeight.");
20495            }
20496            mVerticalScrollFactor = outValue.getDimension(
20497                    mContext.getResources().getDisplayMetrics());
20498        }
20499        return mVerticalScrollFactor;
20500    }
20501
20502    /**
20503     * Gets a scale factor that determines the distance the view should scroll
20504     * horizontally in response to {@link MotionEvent#ACTION_SCROLL}.
20505     * @return The horizontal scroll scale factor.
20506     * @hide
20507     */
20508    protected float getHorizontalScrollFactor() {
20509        // TODO: Should use something else.
20510        return getVerticalScrollFactor();
20511    }
20512
20513    /**
20514     * Return the value specifying the text direction or policy that was set with
20515     * {@link #setTextDirection(int)}.
20516     *
20517     * @return the defined text direction. It can be one of:
20518     *
20519     * {@link #TEXT_DIRECTION_INHERIT},
20520     * {@link #TEXT_DIRECTION_FIRST_STRONG},
20521     * {@link #TEXT_DIRECTION_ANY_RTL},
20522     * {@link #TEXT_DIRECTION_LTR},
20523     * {@link #TEXT_DIRECTION_RTL},
20524     * {@link #TEXT_DIRECTION_LOCALE},
20525     * {@link #TEXT_DIRECTION_FIRST_STRONG_LTR},
20526     * {@link #TEXT_DIRECTION_FIRST_STRONG_RTL}
20527     *
20528     * @attr ref android.R.styleable#View_textDirection
20529     *
20530     * @hide
20531     */
20532    @ViewDebug.ExportedProperty(category = "text", mapping = {
20533            @ViewDebug.IntToString(from = TEXT_DIRECTION_INHERIT, to = "INHERIT"),
20534            @ViewDebug.IntToString(from = TEXT_DIRECTION_FIRST_STRONG, to = "FIRST_STRONG"),
20535            @ViewDebug.IntToString(from = TEXT_DIRECTION_ANY_RTL, to = "ANY_RTL"),
20536            @ViewDebug.IntToString(from = TEXT_DIRECTION_LTR, to = "LTR"),
20537            @ViewDebug.IntToString(from = TEXT_DIRECTION_RTL, to = "RTL"),
20538            @ViewDebug.IntToString(from = TEXT_DIRECTION_LOCALE, to = "LOCALE"),
20539            @ViewDebug.IntToString(from = TEXT_DIRECTION_FIRST_STRONG_LTR, to = "FIRST_STRONG_LTR"),
20540            @ViewDebug.IntToString(from = TEXT_DIRECTION_FIRST_STRONG_RTL, to = "FIRST_STRONG_RTL")
20541    })
20542    public int getRawTextDirection() {
20543        return (mPrivateFlags2 & PFLAG2_TEXT_DIRECTION_MASK) >> PFLAG2_TEXT_DIRECTION_MASK_SHIFT;
20544    }
20545
20546    /**
20547     * Set the text direction.
20548     *
20549     * @param textDirection the direction to set. Should be one of:
20550     *
20551     * {@link #TEXT_DIRECTION_INHERIT},
20552     * {@link #TEXT_DIRECTION_FIRST_STRONG},
20553     * {@link #TEXT_DIRECTION_ANY_RTL},
20554     * {@link #TEXT_DIRECTION_LTR},
20555     * {@link #TEXT_DIRECTION_RTL},
20556     * {@link #TEXT_DIRECTION_LOCALE}
20557     * {@link #TEXT_DIRECTION_FIRST_STRONG_LTR},
20558     * {@link #TEXT_DIRECTION_FIRST_STRONG_RTL},
20559     *
20560     * Resolution will be done if the value is set to TEXT_DIRECTION_INHERIT. The resolution
20561     * proceeds up the parent chain of the view to get the value. If there is no parent, then it will
20562     * return the default {@link #TEXT_DIRECTION_FIRST_STRONG}.
20563     *
20564     * @attr ref android.R.styleable#View_textDirection
20565     */
20566    public void setTextDirection(int textDirection) {
20567        if (getRawTextDirection() != textDirection) {
20568            // Reset the current text direction and the resolved one
20569            mPrivateFlags2 &= ~PFLAG2_TEXT_DIRECTION_MASK;
20570            resetResolvedTextDirection();
20571            // Set the new text direction
20572            mPrivateFlags2 |= ((textDirection << PFLAG2_TEXT_DIRECTION_MASK_SHIFT) & PFLAG2_TEXT_DIRECTION_MASK);
20573            // Do resolution
20574            resolveTextDirection();
20575            // Notify change
20576            onRtlPropertiesChanged(getLayoutDirection());
20577            // Refresh
20578            requestLayout();
20579            invalidate(true);
20580        }
20581    }
20582
20583    /**
20584     * Return the resolved text direction.
20585     *
20586     * @return the resolved text direction. Returns one of:
20587     *
20588     * {@link #TEXT_DIRECTION_FIRST_STRONG},
20589     * {@link #TEXT_DIRECTION_ANY_RTL},
20590     * {@link #TEXT_DIRECTION_LTR},
20591     * {@link #TEXT_DIRECTION_RTL},
20592     * {@link #TEXT_DIRECTION_LOCALE},
20593     * {@link #TEXT_DIRECTION_FIRST_STRONG_LTR},
20594     * {@link #TEXT_DIRECTION_FIRST_STRONG_RTL}
20595     *
20596     * @attr ref android.R.styleable#View_textDirection
20597     */
20598    @ViewDebug.ExportedProperty(category = "text", mapping = {
20599            @ViewDebug.IntToString(from = TEXT_DIRECTION_INHERIT, to = "INHERIT"),
20600            @ViewDebug.IntToString(from = TEXT_DIRECTION_FIRST_STRONG, to = "FIRST_STRONG"),
20601            @ViewDebug.IntToString(from = TEXT_DIRECTION_ANY_RTL, to = "ANY_RTL"),
20602            @ViewDebug.IntToString(from = TEXT_DIRECTION_LTR, to = "LTR"),
20603            @ViewDebug.IntToString(from = TEXT_DIRECTION_RTL, to = "RTL"),
20604            @ViewDebug.IntToString(from = TEXT_DIRECTION_LOCALE, to = "LOCALE"),
20605            @ViewDebug.IntToString(from = TEXT_DIRECTION_FIRST_STRONG_LTR, to = "FIRST_STRONG_LTR"),
20606            @ViewDebug.IntToString(from = TEXT_DIRECTION_FIRST_STRONG_RTL, to = "FIRST_STRONG_RTL")
20607    })
20608    public int getTextDirection() {
20609        return (mPrivateFlags2 & PFLAG2_TEXT_DIRECTION_RESOLVED_MASK) >> PFLAG2_TEXT_DIRECTION_RESOLVED_MASK_SHIFT;
20610    }
20611
20612    /**
20613     * Resolve the text direction.
20614     *
20615     * @return true if resolution has been done, false otherwise.
20616     *
20617     * @hide
20618     */
20619    public boolean resolveTextDirection() {
20620        // Reset any previous text direction resolution
20621        mPrivateFlags2 &= ~(PFLAG2_TEXT_DIRECTION_RESOLVED | PFLAG2_TEXT_DIRECTION_RESOLVED_MASK);
20622
20623        if (hasRtlSupport()) {
20624            // Set resolved text direction flag depending on text direction flag
20625            final int textDirection = getRawTextDirection();
20626            switch(textDirection) {
20627                case TEXT_DIRECTION_INHERIT:
20628                    if (!canResolveTextDirection()) {
20629                        // We cannot do the resolution if there is no parent, so use the default one
20630                        mPrivateFlags2 |= PFLAG2_TEXT_DIRECTION_RESOLVED_DEFAULT;
20631                        // Resolution will need to happen again later
20632                        return false;
20633                    }
20634
20635                    // Parent has not yet resolved, so we still return the default
20636                    try {
20637                        if (!mParent.isTextDirectionResolved()) {
20638                            mPrivateFlags2 |= PFLAG2_TEXT_DIRECTION_RESOLVED_DEFAULT;
20639                            // Resolution will need to happen again later
20640                            return false;
20641                        }
20642                    } catch (AbstractMethodError e) {
20643                        Log.e(VIEW_LOG_TAG, mParent.getClass().getSimpleName() +
20644                                " does not fully implement ViewParent", e);
20645                        mPrivateFlags2 |= PFLAG2_TEXT_DIRECTION_RESOLVED |
20646                                PFLAG2_TEXT_DIRECTION_RESOLVED_DEFAULT;
20647                        return true;
20648                    }
20649
20650                    // Set current resolved direction to the same value as the parent's one
20651                    int parentResolvedDirection;
20652                    try {
20653                        parentResolvedDirection = mParent.getTextDirection();
20654                    } catch (AbstractMethodError e) {
20655                        Log.e(VIEW_LOG_TAG, mParent.getClass().getSimpleName() +
20656                                " does not fully implement ViewParent", e);
20657                        parentResolvedDirection = TEXT_DIRECTION_LTR;
20658                    }
20659                    switch (parentResolvedDirection) {
20660                        case TEXT_DIRECTION_FIRST_STRONG:
20661                        case TEXT_DIRECTION_ANY_RTL:
20662                        case TEXT_DIRECTION_LTR:
20663                        case TEXT_DIRECTION_RTL:
20664                        case TEXT_DIRECTION_LOCALE:
20665                        case TEXT_DIRECTION_FIRST_STRONG_LTR:
20666                        case TEXT_DIRECTION_FIRST_STRONG_RTL:
20667                            mPrivateFlags2 |=
20668                                    (parentResolvedDirection << PFLAG2_TEXT_DIRECTION_RESOLVED_MASK_SHIFT);
20669                            break;
20670                        default:
20671                            // Default resolved direction is "first strong" heuristic
20672                            mPrivateFlags2 |= PFLAG2_TEXT_DIRECTION_RESOLVED_DEFAULT;
20673                    }
20674                    break;
20675                case TEXT_DIRECTION_FIRST_STRONG:
20676                case TEXT_DIRECTION_ANY_RTL:
20677                case TEXT_DIRECTION_LTR:
20678                case TEXT_DIRECTION_RTL:
20679                case TEXT_DIRECTION_LOCALE:
20680                case TEXT_DIRECTION_FIRST_STRONG_LTR:
20681                case TEXT_DIRECTION_FIRST_STRONG_RTL:
20682                    // Resolved direction is the same as text direction
20683                    mPrivateFlags2 |= (textDirection << PFLAG2_TEXT_DIRECTION_RESOLVED_MASK_SHIFT);
20684                    break;
20685                default:
20686                    // Default resolved direction is "first strong" heuristic
20687                    mPrivateFlags2 |= PFLAG2_TEXT_DIRECTION_RESOLVED_DEFAULT;
20688            }
20689        } else {
20690            // Default resolved direction is "first strong" heuristic
20691            mPrivateFlags2 |= PFLAG2_TEXT_DIRECTION_RESOLVED_DEFAULT;
20692        }
20693
20694        // Set to resolved
20695        mPrivateFlags2 |= PFLAG2_TEXT_DIRECTION_RESOLVED;
20696        return true;
20697    }
20698
20699    /**
20700     * Check if text direction resolution can be done.
20701     *
20702     * @return true if text direction resolution can be done otherwise return false.
20703     */
20704    public boolean canResolveTextDirection() {
20705        switch (getRawTextDirection()) {
20706            case TEXT_DIRECTION_INHERIT:
20707                if (mParent != null) {
20708                    try {
20709                        return mParent.canResolveTextDirection();
20710                    } catch (AbstractMethodError e) {
20711                        Log.e(VIEW_LOG_TAG, mParent.getClass().getSimpleName() +
20712                                " does not fully implement ViewParent", e);
20713                    }
20714                }
20715                return false;
20716
20717            default:
20718                return true;
20719        }
20720    }
20721
20722    /**
20723     * Reset resolved text direction. Text direction will be resolved during a call to
20724     * {@link #onMeasure(int, int)}.
20725     *
20726     * @hide
20727     */
20728    public void resetResolvedTextDirection() {
20729        // Reset any previous text direction resolution
20730        mPrivateFlags2 &= ~(PFLAG2_TEXT_DIRECTION_RESOLVED | PFLAG2_TEXT_DIRECTION_RESOLVED_MASK);
20731        // Set to default value
20732        mPrivateFlags2 |= PFLAG2_TEXT_DIRECTION_RESOLVED_DEFAULT;
20733    }
20734
20735    /**
20736     * @return true if text direction is inherited.
20737     *
20738     * @hide
20739     */
20740    public boolean isTextDirectionInherited() {
20741        return (getRawTextDirection() == TEXT_DIRECTION_INHERIT);
20742    }
20743
20744    /**
20745     * @return true if text direction is resolved.
20746     */
20747    public boolean isTextDirectionResolved() {
20748        return (mPrivateFlags2 & PFLAG2_TEXT_DIRECTION_RESOLVED) == PFLAG2_TEXT_DIRECTION_RESOLVED;
20749    }
20750
20751    /**
20752     * Return the value specifying the text alignment or policy that was set with
20753     * {@link #setTextAlignment(int)}.
20754     *
20755     * @return the defined text alignment. It can be one of:
20756     *
20757     * {@link #TEXT_ALIGNMENT_INHERIT},
20758     * {@link #TEXT_ALIGNMENT_GRAVITY},
20759     * {@link #TEXT_ALIGNMENT_CENTER},
20760     * {@link #TEXT_ALIGNMENT_TEXT_START},
20761     * {@link #TEXT_ALIGNMENT_TEXT_END},
20762     * {@link #TEXT_ALIGNMENT_VIEW_START},
20763     * {@link #TEXT_ALIGNMENT_VIEW_END}
20764     *
20765     * @attr ref android.R.styleable#View_textAlignment
20766     *
20767     * @hide
20768     */
20769    @ViewDebug.ExportedProperty(category = "text", mapping = {
20770            @ViewDebug.IntToString(from = TEXT_ALIGNMENT_INHERIT, to = "INHERIT"),
20771            @ViewDebug.IntToString(from = TEXT_ALIGNMENT_GRAVITY, to = "GRAVITY"),
20772            @ViewDebug.IntToString(from = TEXT_ALIGNMENT_TEXT_START, to = "TEXT_START"),
20773            @ViewDebug.IntToString(from = TEXT_ALIGNMENT_TEXT_END, to = "TEXT_END"),
20774            @ViewDebug.IntToString(from = TEXT_ALIGNMENT_CENTER, to = "CENTER"),
20775            @ViewDebug.IntToString(from = TEXT_ALIGNMENT_VIEW_START, to = "VIEW_START"),
20776            @ViewDebug.IntToString(from = TEXT_ALIGNMENT_VIEW_END, to = "VIEW_END")
20777    })
20778    @TextAlignment
20779    public int getRawTextAlignment() {
20780        return (mPrivateFlags2 & PFLAG2_TEXT_ALIGNMENT_MASK) >> PFLAG2_TEXT_ALIGNMENT_MASK_SHIFT;
20781    }
20782
20783    /**
20784     * Set the text alignment.
20785     *
20786     * @param textAlignment The text alignment to set. Should be one of
20787     *
20788     * {@link #TEXT_ALIGNMENT_INHERIT},
20789     * {@link #TEXT_ALIGNMENT_GRAVITY},
20790     * {@link #TEXT_ALIGNMENT_CENTER},
20791     * {@link #TEXT_ALIGNMENT_TEXT_START},
20792     * {@link #TEXT_ALIGNMENT_TEXT_END},
20793     * {@link #TEXT_ALIGNMENT_VIEW_START},
20794     * {@link #TEXT_ALIGNMENT_VIEW_END}
20795     *
20796     * Resolution will be done if the value is set to TEXT_ALIGNMENT_INHERIT. The resolution
20797     * proceeds up the parent chain of the view to get the value. If there is no parent, then it
20798     * will return the default {@link #TEXT_ALIGNMENT_GRAVITY}.
20799     *
20800     * @attr ref android.R.styleable#View_textAlignment
20801     */
20802    public void setTextAlignment(@TextAlignment int textAlignment) {
20803        if (textAlignment != getRawTextAlignment()) {
20804            // Reset the current and resolved text alignment
20805            mPrivateFlags2 &= ~PFLAG2_TEXT_ALIGNMENT_MASK;
20806            resetResolvedTextAlignment();
20807            // Set the new text alignment
20808            mPrivateFlags2 |=
20809                    ((textAlignment << PFLAG2_TEXT_ALIGNMENT_MASK_SHIFT) & PFLAG2_TEXT_ALIGNMENT_MASK);
20810            // Do resolution
20811            resolveTextAlignment();
20812            // Notify change
20813            onRtlPropertiesChanged(getLayoutDirection());
20814            // Refresh
20815            requestLayout();
20816            invalidate(true);
20817        }
20818    }
20819
20820    /**
20821     * Return the resolved text alignment.
20822     *
20823     * @return the resolved text alignment. Returns one of:
20824     *
20825     * {@link #TEXT_ALIGNMENT_GRAVITY},
20826     * {@link #TEXT_ALIGNMENT_CENTER},
20827     * {@link #TEXT_ALIGNMENT_TEXT_START},
20828     * {@link #TEXT_ALIGNMENT_TEXT_END},
20829     * {@link #TEXT_ALIGNMENT_VIEW_START},
20830     * {@link #TEXT_ALIGNMENT_VIEW_END}
20831     *
20832     * @attr ref android.R.styleable#View_textAlignment
20833     */
20834    @ViewDebug.ExportedProperty(category = "text", mapping = {
20835            @ViewDebug.IntToString(from = TEXT_ALIGNMENT_INHERIT, to = "INHERIT"),
20836            @ViewDebug.IntToString(from = TEXT_ALIGNMENT_GRAVITY, to = "GRAVITY"),
20837            @ViewDebug.IntToString(from = TEXT_ALIGNMENT_TEXT_START, to = "TEXT_START"),
20838            @ViewDebug.IntToString(from = TEXT_ALIGNMENT_TEXT_END, to = "TEXT_END"),
20839            @ViewDebug.IntToString(from = TEXT_ALIGNMENT_CENTER, to = "CENTER"),
20840            @ViewDebug.IntToString(from = TEXT_ALIGNMENT_VIEW_START, to = "VIEW_START"),
20841            @ViewDebug.IntToString(from = TEXT_ALIGNMENT_VIEW_END, to = "VIEW_END")
20842    })
20843    @TextAlignment
20844    public int getTextAlignment() {
20845        return (mPrivateFlags2 & PFLAG2_TEXT_ALIGNMENT_RESOLVED_MASK) >>
20846                PFLAG2_TEXT_ALIGNMENT_RESOLVED_MASK_SHIFT;
20847    }
20848
20849    /**
20850     * Resolve the text alignment.
20851     *
20852     * @return true if resolution has been done, false otherwise.
20853     *
20854     * @hide
20855     */
20856    public boolean resolveTextAlignment() {
20857        // Reset any previous text alignment resolution
20858        mPrivateFlags2 &= ~(PFLAG2_TEXT_ALIGNMENT_RESOLVED | PFLAG2_TEXT_ALIGNMENT_RESOLVED_MASK);
20859
20860        if (hasRtlSupport()) {
20861            // Set resolved text alignment flag depending on text alignment flag
20862            final int textAlignment = getRawTextAlignment();
20863            switch (textAlignment) {
20864                case TEXT_ALIGNMENT_INHERIT:
20865                    // Check if we can resolve the text alignment
20866                    if (!canResolveTextAlignment()) {
20867                        // We cannot do the resolution if there is no parent so use the default
20868                        mPrivateFlags2 |= PFLAG2_TEXT_ALIGNMENT_RESOLVED_DEFAULT;
20869                        // Resolution will need to happen again later
20870                        return false;
20871                    }
20872
20873                    // Parent has not yet resolved, so we still return the default
20874                    try {
20875                        if (!mParent.isTextAlignmentResolved()) {
20876                            mPrivateFlags2 |= PFLAG2_TEXT_ALIGNMENT_RESOLVED_DEFAULT;
20877                            // Resolution will need to happen again later
20878                            return false;
20879                        }
20880                    } catch (AbstractMethodError e) {
20881                        Log.e(VIEW_LOG_TAG, mParent.getClass().getSimpleName() +
20882                                " does not fully implement ViewParent", e);
20883                        mPrivateFlags2 |= PFLAG2_TEXT_ALIGNMENT_RESOLVED |
20884                                PFLAG2_TEXT_ALIGNMENT_RESOLVED_DEFAULT;
20885                        return true;
20886                    }
20887
20888                    int parentResolvedTextAlignment;
20889                    try {
20890                        parentResolvedTextAlignment = mParent.getTextAlignment();
20891                    } catch (AbstractMethodError e) {
20892                        Log.e(VIEW_LOG_TAG, mParent.getClass().getSimpleName() +
20893                                " does not fully implement ViewParent", e);
20894                        parentResolvedTextAlignment = TEXT_ALIGNMENT_GRAVITY;
20895                    }
20896                    switch (parentResolvedTextAlignment) {
20897                        case TEXT_ALIGNMENT_GRAVITY:
20898                        case TEXT_ALIGNMENT_TEXT_START:
20899                        case TEXT_ALIGNMENT_TEXT_END:
20900                        case TEXT_ALIGNMENT_CENTER:
20901                        case TEXT_ALIGNMENT_VIEW_START:
20902                        case TEXT_ALIGNMENT_VIEW_END:
20903                            // Resolved text alignment is the same as the parent resolved
20904                            // text alignment
20905                            mPrivateFlags2 |=
20906                                    (parentResolvedTextAlignment << PFLAG2_TEXT_ALIGNMENT_RESOLVED_MASK_SHIFT);
20907                            break;
20908                        default:
20909                            // Use default resolved text alignment
20910                            mPrivateFlags2 |= PFLAG2_TEXT_ALIGNMENT_RESOLVED_DEFAULT;
20911                    }
20912                    break;
20913                case TEXT_ALIGNMENT_GRAVITY:
20914                case TEXT_ALIGNMENT_TEXT_START:
20915                case TEXT_ALIGNMENT_TEXT_END:
20916                case TEXT_ALIGNMENT_CENTER:
20917                case TEXT_ALIGNMENT_VIEW_START:
20918                case TEXT_ALIGNMENT_VIEW_END:
20919                    // Resolved text alignment is the same as text alignment
20920                    mPrivateFlags2 |= (textAlignment << PFLAG2_TEXT_ALIGNMENT_RESOLVED_MASK_SHIFT);
20921                    break;
20922                default:
20923                    // Use default resolved text alignment
20924                    mPrivateFlags2 |= PFLAG2_TEXT_ALIGNMENT_RESOLVED_DEFAULT;
20925            }
20926        } else {
20927            // Use default resolved text alignment
20928            mPrivateFlags2 |= PFLAG2_TEXT_ALIGNMENT_RESOLVED_DEFAULT;
20929        }
20930
20931        // Set the resolved
20932        mPrivateFlags2 |= PFLAG2_TEXT_ALIGNMENT_RESOLVED;
20933        return true;
20934    }
20935
20936    /**
20937     * Check if text alignment resolution can be done.
20938     *
20939     * @return true if text alignment resolution can be done otherwise return false.
20940     */
20941    public boolean canResolveTextAlignment() {
20942        switch (getRawTextAlignment()) {
20943            case TEXT_DIRECTION_INHERIT:
20944                if (mParent != null) {
20945                    try {
20946                        return mParent.canResolveTextAlignment();
20947                    } catch (AbstractMethodError e) {
20948                        Log.e(VIEW_LOG_TAG, mParent.getClass().getSimpleName() +
20949                                " does not fully implement ViewParent", e);
20950                    }
20951                }
20952                return false;
20953
20954            default:
20955                return true;
20956        }
20957    }
20958
20959    /**
20960     * Reset resolved text alignment. Text alignment will be resolved during a call to
20961     * {@link #onMeasure(int, int)}.
20962     *
20963     * @hide
20964     */
20965    public void resetResolvedTextAlignment() {
20966        // Reset any previous text alignment resolution
20967        mPrivateFlags2 &= ~(PFLAG2_TEXT_ALIGNMENT_RESOLVED | PFLAG2_TEXT_ALIGNMENT_RESOLVED_MASK);
20968        // Set to default
20969        mPrivateFlags2 |= PFLAG2_TEXT_ALIGNMENT_RESOLVED_DEFAULT;
20970    }
20971
20972    /**
20973     * @return true if text alignment is inherited.
20974     *
20975     * @hide
20976     */
20977    public boolean isTextAlignmentInherited() {
20978        return (getRawTextAlignment() == TEXT_ALIGNMENT_INHERIT);
20979    }
20980
20981    /**
20982     * @return true if text alignment is resolved.
20983     */
20984    public boolean isTextAlignmentResolved() {
20985        return (mPrivateFlags2 & PFLAG2_TEXT_ALIGNMENT_RESOLVED) == PFLAG2_TEXT_ALIGNMENT_RESOLVED;
20986    }
20987
20988    /**
20989     * Generate a value suitable for use in {@link #setId(int)}.
20990     * This value will not collide with ID values generated at build time by aapt for R.id.
20991     *
20992     * @return a generated ID value
20993     */
20994    public static int generateViewId() {
20995        for (;;) {
20996            final int result = sNextGeneratedId.get();
20997            // aapt-generated IDs have the high byte nonzero; clamp to the range under that.
20998            int newValue = result + 1;
20999            if (newValue > 0x00FFFFFF) newValue = 1; // Roll over to 1, not 0.
21000            if (sNextGeneratedId.compareAndSet(result, newValue)) {
21001                return result;
21002            }
21003        }
21004    }
21005
21006    /**
21007     * Gets the Views in the hierarchy affected by entering and exiting Activity Scene transitions.
21008     * @param transitioningViews This View will be added to transitioningViews if it is VISIBLE and
21009     *                           a normal View or a ViewGroup with
21010     *                           {@link android.view.ViewGroup#isTransitionGroup()} true.
21011     * @hide
21012     */
21013    public void captureTransitioningViews(List<View> transitioningViews) {
21014        if (getVisibility() == View.VISIBLE) {
21015            transitioningViews.add(this);
21016        }
21017    }
21018
21019    /**
21020     * Adds all Views that have {@link #getTransitionName()} non-null to namedElements.
21021     * @param namedElements Will contain all Views in the hierarchy having a transitionName.
21022     * @hide
21023     */
21024    public void findNamedViews(Map<String, View> namedElements) {
21025        if (getVisibility() == VISIBLE || mGhostView != null) {
21026            String transitionName = getTransitionName();
21027            if (transitionName != null) {
21028                namedElements.put(transitionName, this);
21029            }
21030        }
21031    }
21032
21033    /** @hide */
21034    public int getPointerShape(MotionEvent event, float x, float y) {
21035        final int value = (mPrivateFlags3 & PFLAG3_POINTER_ICON_MASK);
21036        switch (value) {
21037            case PFLAG3_POINTER_ICON_NOT_SPECIFIED:
21038                return PointerIcon.STYLE_NOT_SPECIFIED;
21039            case PFLAG3_POINTER_ICON_NULL:
21040                return PointerIcon.STYLE_NULL;
21041            case PFLAG3_POINTER_ICON_CUSTOM:
21042                return PointerIcon.STYLE_CUSTOM;
21043            default:
21044                return ((value - PFLAG3_POINTER_ICON_VALUE_START) >> PFLAG3_POINTER_ICON_LSHIFT)
21045                        + PointerIcon.STYLE_ARROW;
21046        }
21047    }
21048
21049    /** @hide */
21050    public void setPointerShape(int pointerShape) {
21051        int newValue;
21052        if (pointerShape == PointerIcon.STYLE_NOT_SPECIFIED) {
21053            newValue = PFLAG3_POINTER_ICON_NOT_SPECIFIED;
21054        } else if (pointerShape == PointerIcon.STYLE_NULL) {
21055            newValue = PFLAG3_POINTER_ICON_NULL;
21056        } else if (pointerShape == PointerIcon.STYLE_CUSTOM) {
21057            newValue = PFLAG3_POINTER_ICON_CUSTOM;
21058        } else if (pointerShape >= PointerIcon.STYLE_ARROW
21059                && pointerShape <= PointerIcon.STYLE_GRABBING) {
21060            newValue = ((pointerShape - PointerIcon.STYLE_ARROW) << PFLAG3_POINTER_ICON_LSHIFT)
21061                    + PFLAG3_POINTER_ICON_VALUE_START;
21062        } else {
21063            Log.w(VIEW_LOG_TAG, "Invalid pointer shape " + pointerShape + " is specified.");
21064            return;
21065        }
21066        if (newValue != (mPrivateFlags3 & PFLAG3_POINTER_ICON_MASK)) {
21067            mPrivateFlags3 = (mPrivateFlags3 & ~PFLAG3_POINTER_ICON_MASK) | newValue;
21068        }
21069    }
21070
21071    //
21072    // Properties
21073    //
21074    /**
21075     * A Property wrapper around the <code>alpha</code> functionality handled by the
21076     * {@link View#setAlpha(float)} and {@link View#getAlpha()} methods.
21077     */
21078    public static final Property<View, Float> ALPHA = new FloatProperty<View>("alpha") {
21079        @Override
21080        public void setValue(View object, float value) {
21081            object.setAlpha(value);
21082        }
21083
21084        @Override
21085        public Float get(View object) {
21086            return object.getAlpha();
21087        }
21088    };
21089
21090    /**
21091     * A Property wrapper around the <code>translationX</code> functionality handled by the
21092     * {@link View#setTranslationX(float)} and {@link View#getTranslationX()} methods.
21093     */
21094    public static final Property<View, Float> TRANSLATION_X = new FloatProperty<View>("translationX") {
21095        @Override
21096        public void setValue(View object, float value) {
21097            object.setTranslationX(value);
21098        }
21099
21100                @Override
21101        public Float get(View object) {
21102            return object.getTranslationX();
21103        }
21104    };
21105
21106    /**
21107     * A Property wrapper around the <code>translationY</code> functionality handled by the
21108     * {@link View#setTranslationY(float)} and {@link View#getTranslationY()} methods.
21109     */
21110    public static final Property<View, Float> TRANSLATION_Y = new FloatProperty<View>("translationY") {
21111        @Override
21112        public void setValue(View object, float value) {
21113            object.setTranslationY(value);
21114        }
21115
21116        @Override
21117        public Float get(View object) {
21118            return object.getTranslationY();
21119        }
21120    };
21121
21122    /**
21123     * A Property wrapper around the <code>translationZ</code> functionality handled by the
21124     * {@link View#setTranslationZ(float)} and {@link View#getTranslationZ()} methods.
21125     */
21126    public static final Property<View, Float> TRANSLATION_Z = new FloatProperty<View>("translationZ") {
21127        @Override
21128        public void setValue(View object, float value) {
21129            object.setTranslationZ(value);
21130        }
21131
21132        @Override
21133        public Float get(View object) {
21134            return object.getTranslationZ();
21135        }
21136    };
21137
21138    /**
21139     * A Property wrapper around the <code>x</code> functionality handled by the
21140     * {@link View#setX(float)} and {@link View#getX()} methods.
21141     */
21142    public static final Property<View, Float> X = new FloatProperty<View>("x") {
21143        @Override
21144        public void setValue(View object, float value) {
21145            object.setX(value);
21146        }
21147
21148        @Override
21149        public Float get(View object) {
21150            return object.getX();
21151        }
21152    };
21153
21154    /**
21155     * A Property wrapper around the <code>y</code> functionality handled by the
21156     * {@link View#setY(float)} and {@link View#getY()} methods.
21157     */
21158    public static final Property<View, Float> Y = new FloatProperty<View>("y") {
21159        @Override
21160        public void setValue(View object, float value) {
21161            object.setY(value);
21162        }
21163
21164        @Override
21165        public Float get(View object) {
21166            return object.getY();
21167        }
21168    };
21169
21170    /**
21171     * A Property wrapper around the <code>z</code> functionality handled by the
21172     * {@link View#setZ(float)} and {@link View#getZ()} methods.
21173     */
21174    public static final Property<View, Float> Z = new FloatProperty<View>("z") {
21175        @Override
21176        public void setValue(View object, float value) {
21177            object.setZ(value);
21178        }
21179
21180        @Override
21181        public Float get(View object) {
21182            return object.getZ();
21183        }
21184    };
21185
21186    /**
21187     * A Property wrapper around the <code>rotation</code> functionality handled by the
21188     * {@link View#setRotation(float)} and {@link View#getRotation()} methods.
21189     */
21190    public static final Property<View, Float> ROTATION = new FloatProperty<View>("rotation") {
21191        @Override
21192        public void setValue(View object, float value) {
21193            object.setRotation(value);
21194        }
21195
21196        @Override
21197        public Float get(View object) {
21198            return object.getRotation();
21199        }
21200    };
21201
21202    /**
21203     * A Property wrapper around the <code>rotationX</code> functionality handled by the
21204     * {@link View#setRotationX(float)} and {@link View#getRotationX()} methods.
21205     */
21206    public static final Property<View, Float> ROTATION_X = new FloatProperty<View>("rotationX") {
21207        @Override
21208        public void setValue(View object, float value) {
21209            object.setRotationX(value);
21210        }
21211
21212        @Override
21213        public Float get(View object) {
21214            return object.getRotationX();
21215        }
21216    };
21217
21218    /**
21219     * A Property wrapper around the <code>rotationY</code> functionality handled by the
21220     * {@link View#setRotationY(float)} and {@link View#getRotationY()} methods.
21221     */
21222    public static final Property<View, Float> ROTATION_Y = new FloatProperty<View>("rotationY") {
21223        @Override
21224        public void setValue(View object, float value) {
21225            object.setRotationY(value);
21226        }
21227
21228        @Override
21229        public Float get(View object) {
21230            return object.getRotationY();
21231        }
21232    };
21233
21234    /**
21235     * A Property wrapper around the <code>scaleX</code> functionality handled by the
21236     * {@link View#setScaleX(float)} and {@link View#getScaleX()} methods.
21237     */
21238    public static final Property<View, Float> SCALE_X = new FloatProperty<View>("scaleX") {
21239        @Override
21240        public void setValue(View object, float value) {
21241            object.setScaleX(value);
21242        }
21243
21244        @Override
21245        public Float get(View object) {
21246            return object.getScaleX();
21247        }
21248    };
21249
21250    /**
21251     * A Property wrapper around the <code>scaleY</code> functionality handled by the
21252     * {@link View#setScaleY(float)} and {@link View#getScaleY()} methods.
21253     */
21254    public static final Property<View, Float> SCALE_Y = new FloatProperty<View>("scaleY") {
21255        @Override
21256        public void setValue(View object, float value) {
21257            object.setScaleY(value);
21258        }
21259
21260        @Override
21261        public Float get(View object) {
21262            return object.getScaleY();
21263        }
21264    };
21265
21266    /**
21267     * A MeasureSpec encapsulates the layout requirements passed from parent to child.
21268     * Each MeasureSpec represents a requirement for either the width or the height.
21269     * A MeasureSpec is comprised of a size and a mode. There are three possible
21270     * modes:
21271     * <dl>
21272     * <dt>UNSPECIFIED</dt>
21273     * <dd>
21274     * The parent has not imposed any constraint on the child. It can be whatever size
21275     * it wants.
21276     * </dd>
21277     *
21278     * <dt>EXACTLY</dt>
21279     * <dd>
21280     * The parent has determined an exact size for the child. The child is going to be
21281     * given those bounds regardless of how big it wants to be.
21282     * </dd>
21283     *
21284     * <dt>AT_MOST</dt>
21285     * <dd>
21286     * The child can be as large as it wants up to the specified size.
21287     * </dd>
21288     * </dl>
21289     *
21290     * MeasureSpecs are implemented as ints to reduce object allocation. This class
21291     * is provided to pack and unpack the &lt;size, mode&gt; tuple into the int.
21292     */
21293    public static class MeasureSpec {
21294        private static final int MODE_SHIFT = 30;
21295        private static final int MODE_MASK  = 0x3 << MODE_SHIFT;
21296
21297        /**
21298         * Measure specification mode: The parent has not imposed any constraint
21299         * on the child. It can be whatever size it wants.
21300         */
21301        public static final int UNSPECIFIED = 0 << MODE_SHIFT;
21302
21303        /**
21304         * Measure specification mode: The parent has determined an exact size
21305         * for the child. The child is going to be given those bounds regardless
21306         * of how big it wants to be.
21307         */
21308        public static final int EXACTLY     = 1 << MODE_SHIFT;
21309
21310        /**
21311         * Measure specification mode: The child can be as large as it wants up
21312         * to the specified size.
21313         */
21314        public static final int AT_MOST     = 2 << MODE_SHIFT;
21315
21316        /**
21317         * Creates a measure specification based on the supplied size and mode.
21318         *
21319         * The mode must always be one of the following:
21320         * <ul>
21321         *  <li>{@link android.view.View.MeasureSpec#UNSPECIFIED}</li>
21322         *  <li>{@link android.view.View.MeasureSpec#EXACTLY}</li>
21323         *  <li>{@link android.view.View.MeasureSpec#AT_MOST}</li>
21324         * </ul>
21325         *
21326         * <p><strong>Note:</strong> On API level 17 and lower, makeMeasureSpec's
21327         * implementation was such that the order of arguments did not matter
21328         * and overflow in either value could impact the resulting MeasureSpec.
21329         * {@link android.widget.RelativeLayout} was affected by this bug.
21330         * Apps targeting API levels greater than 17 will get the fixed, more strict
21331         * behavior.</p>
21332         *
21333         * @param size the size of the measure specification
21334         * @param mode the mode of the measure specification
21335         * @return the measure specification based on size and mode
21336         */
21337        public static int makeMeasureSpec(int size, int mode) {
21338            if (sUseBrokenMakeMeasureSpec) {
21339                return size + mode;
21340            } else {
21341                return (size & ~MODE_MASK) | (mode & MODE_MASK);
21342            }
21343        }
21344
21345        /**
21346         * Like {@link #makeMeasureSpec(int, int)}, but any spec with a mode of UNSPECIFIED
21347         * will automatically get a size of 0. Older apps expect this.
21348         *
21349         * @hide internal use only for compatibility with system widgets and older apps
21350         */
21351        public static int makeSafeMeasureSpec(int size, int mode) {
21352            if (sUseZeroUnspecifiedMeasureSpec && mode == UNSPECIFIED) {
21353                return 0;
21354            }
21355            return makeMeasureSpec(size, mode);
21356        }
21357
21358        /**
21359         * Extracts the mode from the supplied measure specification.
21360         *
21361         * @param measureSpec the measure specification to extract the mode from
21362         * @return {@link android.view.View.MeasureSpec#UNSPECIFIED},
21363         *         {@link android.view.View.MeasureSpec#AT_MOST} or
21364         *         {@link android.view.View.MeasureSpec#EXACTLY}
21365         */
21366        public static int getMode(int measureSpec) {
21367            return (measureSpec & MODE_MASK);
21368        }
21369
21370        /**
21371         * Extracts the size from the supplied measure specification.
21372         *
21373         * @param measureSpec the measure specification to extract the size from
21374         * @return the size in pixels defined in the supplied measure specification
21375         */
21376        public static int getSize(int measureSpec) {
21377            return (measureSpec & ~MODE_MASK);
21378        }
21379
21380        static int adjust(int measureSpec, int delta) {
21381            final int mode = getMode(measureSpec);
21382            int size = getSize(measureSpec);
21383            if (mode == UNSPECIFIED) {
21384                // No need to adjust size for UNSPECIFIED mode.
21385                return makeMeasureSpec(size, UNSPECIFIED);
21386            }
21387            size += delta;
21388            if (size < 0) {
21389                Log.e(VIEW_LOG_TAG, "MeasureSpec.adjust: new size would be negative! (" + size +
21390                        ") spec: " + toString(measureSpec) + " delta: " + delta);
21391                size = 0;
21392            }
21393            return makeMeasureSpec(size, mode);
21394        }
21395
21396        /**
21397         * Returns a String representation of the specified measure
21398         * specification.
21399         *
21400         * @param measureSpec the measure specification to convert to a String
21401         * @return a String with the following format: "MeasureSpec: MODE SIZE"
21402         */
21403        public static String toString(int measureSpec) {
21404            int mode = getMode(measureSpec);
21405            int size = getSize(measureSpec);
21406
21407            StringBuilder sb = new StringBuilder("MeasureSpec: ");
21408
21409            if (mode == UNSPECIFIED)
21410                sb.append("UNSPECIFIED ");
21411            else if (mode == EXACTLY)
21412                sb.append("EXACTLY ");
21413            else if (mode == AT_MOST)
21414                sb.append("AT_MOST ");
21415            else
21416                sb.append(mode).append(" ");
21417
21418            sb.append(size);
21419            return sb.toString();
21420        }
21421    }
21422
21423    private final class CheckForLongPress implements Runnable {
21424        private int mOriginalWindowAttachCount;
21425
21426        @Override
21427        public void run() {
21428            if (isPressed() && (mParent != null)
21429                    && mOriginalWindowAttachCount == mWindowAttachCount) {
21430                if (performLongClick()) {
21431                    mHasPerformedLongPress = true;
21432                }
21433            }
21434        }
21435
21436        public void rememberWindowAttachCount() {
21437            mOriginalWindowAttachCount = mWindowAttachCount;
21438        }
21439    }
21440
21441    private final class CheckForTap implements Runnable {
21442        public float x;
21443        public float y;
21444
21445        @Override
21446        public void run() {
21447            mPrivateFlags &= ~PFLAG_PREPRESSED;
21448            setPressed(true, x, y);
21449            checkForLongClick(ViewConfiguration.getTapTimeout());
21450        }
21451    }
21452
21453    private final class PerformClick implements Runnable {
21454        @Override
21455        public void run() {
21456            performClick();
21457        }
21458    }
21459
21460    /**
21461     * This method returns a ViewPropertyAnimator object, which can be used to animate
21462     * specific properties on this View.
21463     *
21464     * @return ViewPropertyAnimator The ViewPropertyAnimator associated with this View.
21465     */
21466    public ViewPropertyAnimator animate() {
21467        if (mAnimator == null) {
21468            mAnimator = new ViewPropertyAnimator(this);
21469        }
21470        return mAnimator;
21471    }
21472
21473    /**
21474     * Sets the name of the View to be used to identify Views in Transitions.
21475     * Names should be unique in the View hierarchy.
21476     *
21477     * @param transitionName The name of the View to uniquely identify it for Transitions.
21478     */
21479    public final void setTransitionName(String transitionName) {
21480        mTransitionName = transitionName;
21481    }
21482
21483    /**
21484     * Returns the name of the View to be used to identify Views in Transitions.
21485     * Names should be unique in the View hierarchy.
21486     *
21487     * <p>This returns null if the View has not been given a name.</p>
21488     *
21489     * @return The name used of the View to be used to identify Views in Transitions or null
21490     * if no name has been given.
21491     */
21492    @ViewDebug.ExportedProperty
21493    public String getTransitionName() {
21494        return mTransitionName;
21495    }
21496
21497    /**
21498     * Interface definition for a callback to be invoked when a hardware key event is
21499     * dispatched to this view. The callback will be invoked before the key event is
21500     * given to the view. This is only useful for hardware keyboards; a software input
21501     * method has no obligation to trigger this listener.
21502     */
21503    public interface OnKeyListener {
21504        /**
21505         * Called when a hardware key is dispatched to a view. This allows listeners to
21506         * get a chance to respond before the target view.
21507         * <p>Key presses in software keyboards will generally NOT trigger this method,
21508         * although some may elect to do so in some situations. Do not assume a
21509         * software input method has to be key-based; even if it is, it may use key presses
21510         * in a different way than you expect, so there is no way to reliably catch soft
21511         * input key presses.
21512         *
21513         * @param v The view the key has been dispatched to.
21514         * @param keyCode The code for the physical key that was pressed
21515         * @param event The KeyEvent object containing full information about
21516         *        the event.
21517         * @return True if the listener has consumed the event, false otherwise.
21518         */
21519        boolean onKey(View v, int keyCode, KeyEvent event);
21520    }
21521
21522    /**
21523     * Interface definition for a callback to be invoked when a touch event is
21524     * dispatched to this view. The callback will be invoked before the touch
21525     * event is given to the view.
21526     */
21527    public interface OnTouchListener {
21528        /**
21529         * Called when a touch event is dispatched to a view. This allows listeners to
21530         * get a chance to respond before the target view.
21531         *
21532         * @param v The view the touch event has been dispatched to.
21533         * @param event The MotionEvent object containing full information about
21534         *        the event.
21535         * @return True if the listener has consumed the event, false otherwise.
21536         */
21537        boolean onTouch(View v, MotionEvent event);
21538    }
21539
21540    /**
21541     * Interface definition for a callback to be invoked when a hover event is
21542     * dispatched to this view. The callback will be invoked before the hover
21543     * event is given to the view.
21544     */
21545    public interface OnHoverListener {
21546        /**
21547         * Called when a hover event is dispatched to a view. This allows listeners to
21548         * get a chance to respond before the target view.
21549         *
21550         * @param v The view the hover event has been dispatched to.
21551         * @param event The MotionEvent object containing full information about
21552         *        the event.
21553         * @return True if the listener has consumed the event, false otherwise.
21554         */
21555        boolean onHover(View v, MotionEvent event);
21556    }
21557
21558    /**
21559     * Interface definition for a callback to be invoked when a generic motion event is
21560     * dispatched to this view. The callback will be invoked before the generic motion
21561     * event is given to the view.
21562     */
21563    public interface OnGenericMotionListener {
21564        /**
21565         * Called when a generic motion event is dispatched to a view. This allows listeners to
21566         * get a chance to respond before the target view.
21567         *
21568         * @param v The view the generic motion event has been dispatched to.
21569         * @param event The MotionEvent object containing full information about
21570         *        the event.
21571         * @return True if the listener has consumed the event, false otherwise.
21572         */
21573        boolean onGenericMotion(View v, MotionEvent event);
21574    }
21575
21576    /**
21577     * Interface definition for a callback to be invoked when a view has been clicked and held.
21578     */
21579    public interface OnLongClickListener {
21580        /**
21581         * Called when a view has been clicked and held.
21582         *
21583         * @param v The view that was clicked and held.
21584         *
21585         * @return true if the callback consumed the long click, false otherwise.
21586         */
21587        boolean onLongClick(View v);
21588    }
21589
21590    /**
21591     * Interface definition for a callback to be invoked when a drag is being dispatched
21592     * to this view.  The callback will be invoked before the hosting view's own
21593     * onDrag(event) method.  If the listener wants to fall back to the hosting view's
21594     * onDrag(event) behavior, it should return 'false' from this callback.
21595     *
21596     * <div class="special reference">
21597     * <h3>Developer Guides</h3>
21598     * <p>For a guide to implementing drag and drop features, read the
21599     * <a href="{@docRoot}guide/topics/ui/drag-drop.html">Drag and Drop</a> developer guide.</p>
21600     * </div>
21601     */
21602    public interface OnDragListener {
21603        /**
21604         * Called when a drag event is dispatched to a view. This allows listeners
21605         * to get a chance to override base View behavior.
21606         *
21607         * @param v The View that received the drag event.
21608         * @param event The {@link android.view.DragEvent} object for the drag event.
21609         * @return {@code true} if the drag event was handled successfully, or {@code false}
21610         * if the drag event was not handled. Note that {@code false} will trigger the View
21611         * to call its {@link #onDragEvent(DragEvent) onDragEvent()} handler.
21612         */
21613        boolean onDrag(View v, DragEvent event);
21614    }
21615
21616    /**
21617     * Interface definition for a callback to be invoked when the focus state of
21618     * a view changed.
21619     */
21620    public interface OnFocusChangeListener {
21621        /**
21622         * Called when the focus state of a view has changed.
21623         *
21624         * @param v The view whose state has changed.
21625         * @param hasFocus The new focus state of v.
21626         */
21627        void onFocusChange(View v, boolean hasFocus);
21628    }
21629
21630    /**
21631     * Interface definition for a callback to be invoked when a view is clicked.
21632     */
21633    public interface OnClickListener {
21634        /**
21635         * Called when a view has been clicked.
21636         *
21637         * @param v The view that was clicked.
21638         */
21639        void onClick(View v);
21640    }
21641
21642    /**
21643     * Interface definition for a callback to be invoked when a view is context clicked.
21644     */
21645    public interface OnContextClickListener {
21646        /**
21647         * Called when a view is context clicked.
21648         *
21649         * @param v The view that has been context clicked.
21650         * @return true if the callback consumed the context click, false otherwise.
21651         */
21652        boolean onContextClick(View v);
21653    }
21654
21655    /**
21656     * Interface definition for a callback to be invoked when the context menu
21657     * for this view is being built.
21658     */
21659    public interface OnCreateContextMenuListener {
21660        /**
21661         * Called when the context menu for this view is being built. It is not
21662         * safe to hold onto the menu after this method returns.
21663         *
21664         * @param menu The context menu that is being built
21665         * @param v The view for which the context menu is being built
21666         * @param menuInfo Extra information about the item for which the
21667         *            context menu should be shown. This information will vary
21668         *            depending on the class of v.
21669         */
21670        void onCreateContextMenu(ContextMenu menu, View v, ContextMenuInfo menuInfo);
21671    }
21672
21673    /**
21674     * Interface definition for a callback to be invoked when the status bar changes
21675     * visibility.  This reports <strong>global</strong> changes to the system UI
21676     * state, not what the application is requesting.
21677     *
21678     * @see View#setOnSystemUiVisibilityChangeListener(android.view.View.OnSystemUiVisibilityChangeListener)
21679     */
21680    public interface OnSystemUiVisibilityChangeListener {
21681        /**
21682         * Called when the status bar changes visibility because of a call to
21683         * {@link View#setSystemUiVisibility(int)}.
21684         *
21685         * @param visibility  Bitwise-or of flags {@link #SYSTEM_UI_FLAG_LOW_PROFILE},
21686         * {@link #SYSTEM_UI_FLAG_HIDE_NAVIGATION}, and {@link #SYSTEM_UI_FLAG_FULLSCREEN}.
21687         * This tells you the <strong>global</strong> state of these UI visibility
21688         * flags, not what your app is currently applying.
21689         */
21690        public void onSystemUiVisibilityChange(int visibility);
21691    }
21692
21693    /**
21694     * Interface definition for a callback to be invoked when this view is attached
21695     * or detached from its window.
21696     */
21697    public interface OnAttachStateChangeListener {
21698        /**
21699         * Called when the view is attached to a window.
21700         * @param v The view that was attached
21701         */
21702        public void onViewAttachedToWindow(View v);
21703        /**
21704         * Called when the view is detached from a window.
21705         * @param v The view that was detached
21706         */
21707        public void onViewDetachedFromWindow(View v);
21708    }
21709
21710    /**
21711     * Listener for applying window insets on a view in a custom way.
21712     *
21713     * <p>Apps may choose to implement this interface if they want to apply custom policy
21714     * to the way that window insets are treated for a view. If an OnApplyWindowInsetsListener
21715     * is set, its
21716     * {@link OnApplyWindowInsetsListener#onApplyWindowInsets(View, WindowInsets) onApplyWindowInsets}
21717     * method will be called instead of the View's own
21718     * {@link #onApplyWindowInsets(WindowInsets) onApplyWindowInsets} method. The listener
21719     * may optionally call the parameter View's <code>onApplyWindowInsets</code> method to apply
21720     * the View's normal behavior as part of its own.</p>
21721     */
21722    public interface OnApplyWindowInsetsListener {
21723        /**
21724         * When {@link View#setOnApplyWindowInsetsListener(View.OnApplyWindowInsetsListener) set}
21725         * on a View, this listener method will be called instead of the view's own
21726         * {@link View#onApplyWindowInsets(WindowInsets) onApplyWindowInsets} method.
21727         *
21728         * @param v The view applying window insets
21729         * @param insets The insets to apply
21730         * @return The insets supplied, minus any insets that were consumed
21731         */
21732        public WindowInsets onApplyWindowInsets(View v, WindowInsets insets);
21733    }
21734
21735    private final class UnsetPressedState implements Runnable {
21736        @Override
21737        public void run() {
21738            setPressed(false);
21739        }
21740    }
21741
21742    /**
21743     * Base class for derived classes that want to save and restore their own
21744     * state in {@link android.view.View#onSaveInstanceState()}.
21745     */
21746    public static class BaseSavedState extends AbsSavedState {
21747        String mStartActivityRequestWhoSaved;
21748
21749        /**
21750         * Constructor used when reading from a parcel. Reads the state of the superclass.
21751         *
21752         * @param source
21753         */
21754        public BaseSavedState(Parcel source) {
21755            super(source);
21756            mStartActivityRequestWhoSaved = source.readString();
21757        }
21758
21759        /**
21760         * Constructor called by derived classes when creating their SavedState objects
21761         *
21762         * @param superState The state of the superclass of this view
21763         */
21764        public BaseSavedState(Parcelable superState) {
21765            super(superState);
21766        }
21767
21768        @Override
21769        public void writeToParcel(Parcel out, int flags) {
21770            super.writeToParcel(out, flags);
21771            out.writeString(mStartActivityRequestWhoSaved);
21772        }
21773
21774        public static final Parcelable.Creator<BaseSavedState> CREATOR =
21775                new Parcelable.Creator<BaseSavedState>() {
21776            public BaseSavedState createFromParcel(Parcel in) {
21777                return new BaseSavedState(in);
21778            }
21779
21780            public BaseSavedState[] newArray(int size) {
21781                return new BaseSavedState[size];
21782            }
21783        };
21784    }
21785
21786    /**
21787     * A set of information given to a view when it is attached to its parent
21788     * window.
21789     */
21790    final static class AttachInfo {
21791        interface Callbacks {
21792            void playSoundEffect(int effectId);
21793            boolean performHapticFeedback(int effectId, boolean always);
21794        }
21795
21796        /**
21797         * InvalidateInfo is used to post invalidate(int, int, int, int) messages
21798         * to a Handler. This class contains the target (View) to invalidate and
21799         * the coordinates of the dirty rectangle.
21800         *
21801         * For performance purposes, this class also implements a pool of up to
21802         * POOL_LIMIT objects that get reused. This reduces memory allocations
21803         * whenever possible.
21804         */
21805        static class InvalidateInfo {
21806            private static final int POOL_LIMIT = 10;
21807
21808            private static final SynchronizedPool<InvalidateInfo> sPool =
21809                    new SynchronizedPool<InvalidateInfo>(POOL_LIMIT);
21810
21811            View target;
21812
21813            int left;
21814            int top;
21815            int right;
21816            int bottom;
21817
21818            public static InvalidateInfo obtain() {
21819                InvalidateInfo instance = sPool.acquire();
21820                return (instance != null) ? instance : new InvalidateInfo();
21821            }
21822
21823            public void recycle() {
21824                target = null;
21825                sPool.release(this);
21826            }
21827        }
21828
21829        final IWindowSession mSession;
21830
21831        final IWindow mWindow;
21832
21833        final IBinder mWindowToken;
21834
21835        final Display mDisplay;
21836
21837        final Callbacks mRootCallbacks;
21838
21839        IWindowId mIWindowId;
21840        WindowId mWindowId;
21841
21842        /**
21843         * The top view of the hierarchy.
21844         */
21845        View mRootView;
21846
21847        IBinder mPanelParentWindowToken;
21848
21849        boolean mHardwareAccelerated;
21850        boolean mHardwareAccelerationRequested;
21851        HardwareRenderer mHardwareRenderer;
21852        List<RenderNode> mPendingAnimatingRenderNodes;
21853
21854        /**
21855         * The state of the display to which the window is attached, as reported
21856         * by {@link Display#getState()}.  Note that the display state constants
21857         * declared by {@link Display} do not exactly line up with the screen state
21858         * constants declared by {@link View} (there are more display states than
21859         * screen states).
21860         */
21861        int mDisplayState = Display.STATE_UNKNOWN;
21862
21863        /**
21864         * Scale factor used by the compatibility mode
21865         */
21866        float mApplicationScale;
21867
21868        /**
21869         * Indicates whether the application is in compatibility mode
21870         */
21871        boolean mScalingRequired;
21872
21873        /**
21874         * Left position of this view's window
21875         */
21876        int mWindowLeft;
21877
21878        /**
21879         * Top position of this view's window
21880         */
21881        int mWindowTop;
21882
21883        /**
21884         * Indicates whether views need to use 32-bit drawing caches
21885         */
21886        boolean mUse32BitDrawingCache;
21887
21888        /**
21889         * For windows that are full-screen but using insets to layout inside
21890         * of the screen areas, these are the current insets to appear inside
21891         * the overscan area of the display.
21892         */
21893        final Rect mOverscanInsets = new Rect();
21894
21895        /**
21896         * For windows that are full-screen but using insets to layout inside
21897         * of the screen decorations, these are the current insets for the
21898         * content of the window.
21899         */
21900        final Rect mContentInsets = new Rect();
21901
21902        /**
21903         * For windows that are full-screen but using insets to layout inside
21904         * of the screen decorations, these are the current insets for the
21905         * actual visible parts of the window.
21906         */
21907        final Rect mVisibleInsets = new Rect();
21908
21909        /**
21910         * For windows that are full-screen but using insets to layout inside
21911         * of the screen decorations, these are the current insets for the
21912         * stable system windows.
21913         */
21914        final Rect mStableInsets = new Rect();
21915
21916        /**
21917         * For windows that include areas that are not covered by real surface these are the outsets
21918         * for real surface.
21919         */
21920        final Rect mOutsets = new Rect();
21921
21922        /**
21923         * The internal insets given by this window.  This value is
21924         * supplied by the client (through
21925         * {@link ViewTreeObserver.OnComputeInternalInsetsListener}) and will
21926         * be given to the window manager when changed to be used in laying
21927         * out windows behind it.
21928         */
21929        final ViewTreeObserver.InternalInsetsInfo mGivenInternalInsets
21930                = new ViewTreeObserver.InternalInsetsInfo();
21931
21932        /**
21933         * Set to true when mGivenInternalInsets is non-empty.
21934         */
21935        boolean mHasNonEmptyGivenInternalInsets;
21936
21937        /**
21938         * All views in the window's hierarchy that serve as scroll containers,
21939         * used to determine if the window can be resized or must be panned
21940         * to adjust for a soft input area.
21941         */
21942        final ArrayList<View> mScrollContainers = new ArrayList<View>();
21943
21944        final KeyEvent.DispatcherState mKeyDispatchState
21945                = new KeyEvent.DispatcherState();
21946
21947        /**
21948         * Indicates whether the view's window currently has the focus.
21949         */
21950        boolean mHasWindowFocus;
21951
21952        /**
21953         * The current visibility of the window.
21954         */
21955        int mWindowVisibility;
21956
21957        /**
21958         * Indicates the time at which drawing started to occur.
21959         */
21960        long mDrawingTime;
21961
21962        /**
21963         * Indicates whether or not ignoring the DIRTY_MASK flags.
21964         */
21965        boolean mIgnoreDirtyState;
21966
21967        /**
21968         * This flag tracks when the mIgnoreDirtyState flag is set during draw(),
21969         * to avoid clearing that flag prematurely.
21970         */
21971        boolean mSetIgnoreDirtyState = false;
21972
21973        /**
21974         * Indicates whether the view's window is currently in touch mode.
21975         */
21976        boolean mInTouchMode;
21977
21978        /**
21979         * Indicates whether the view has requested unbuffered input dispatching for the current
21980         * event stream.
21981         */
21982        boolean mUnbufferedDispatchRequested;
21983
21984        /**
21985         * Indicates that ViewAncestor should trigger a global layout change
21986         * the next time it performs a traversal
21987         */
21988        boolean mRecomputeGlobalAttributes;
21989
21990        /**
21991         * Always report new attributes at next traversal.
21992         */
21993        boolean mForceReportNewAttributes;
21994
21995        /**
21996         * Set during a traveral if any views want to keep the screen on.
21997         */
21998        boolean mKeepScreenOn;
21999
22000        /**
22001         * Bitwise-or of all of the values that views have passed to setSystemUiVisibility().
22002         */
22003        int mSystemUiVisibility;
22004
22005        /**
22006         * Hack to force certain system UI visibility flags to be cleared.
22007         */
22008        int mDisabledSystemUiVisibility;
22009
22010        /**
22011         * Last global system UI visibility reported by the window manager.
22012         */
22013        int mGlobalSystemUiVisibility;
22014
22015        /**
22016         * True if a view in this hierarchy has an OnSystemUiVisibilityChangeListener
22017         * attached.
22018         */
22019        boolean mHasSystemUiListeners;
22020
22021        /**
22022         * Set if the window has requested to extend into the overscan region
22023         * via WindowManager.LayoutParams.FLAG_LAYOUT_IN_OVERSCAN.
22024         */
22025        boolean mOverscanRequested;
22026
22027        /**
22028         * Set if the visibility of any views has changed.
22029         */
22030        boolean mViewVisibilityChanged;
22031
22032        /**
22033         * Set to true if a view has been scrolled.
22034         */
22035        boolean mViewScrollChanged;
22036
22037        /**
22038         * Set to true if high contrast mode enabled
22039         */
22040        boolean mHighContrastText;
22041
22042        /**
22043         * Global to the view hierarchy used as a temporary for dealing with
22044         * x/y points in the transparent region computations.
22045         */
22046        final int[] mTransparentLocation = new int[2];
22047
22048        /**
22049         * Global to the view hierarchy used as a temporary for dealing with
22050         * x/y points in the ViewGroup.invalidateChild implementation.
22051         */
22052        final int[] mInvalidateChildLocation = new int[2];
22053
22054        /**
22055         * Global to the view hierarchy used as a temporary for dealng with
22056         * computing absolute on-screen location.
22057         */
22058        final int[] mTmpLocation = new int[2];
22059
22060        /**
22061         * Global to the view hierarchy used as a temporary for dealing with
22062         * x/y location when view is transformed.
22063         */
22064        final float[] mTmpTransformLocation = new float[2];
22065
22066        /**
22067         * The view tree observer used to dispatch global events like
22068         * layout, pre-draw, touch mode change, etc.
22069         */
22070        final ViewTreeObserver mTreeObserver = new ViewTreeObserver();
22071
22072        /**
22073         * A Canvas used by the view hierarchy to perform bitmap caching.
22074         */
22075        Canvas mCanvas;
22076
22077        /**
22078         * The view root impl.
22079         */
22080        final ViewRootImpl mViewRootImpl;
22081
22082        /**
22083         * A Handler supplied by a view's {@link android.view.ViewRootImpl}. This
22084         * handler can be used to pump events in the UI events queue.
22085         */
22086        final Handler mHandler;
22087
22088        /**
22089         * Temporary for use in computing invalidate rectangles while
22090         * calling up the hierarchy.
22091         */
22092        final Rect mTmpInvalRect = new Rect();
22093
22094        /**
22095         * Temporary for use in computing hit areas with transformed views
22096         */
22097        final RectF mTmpTransformRect = new RectF();
22098
22099        /**
22100         * Temporary for use in computing hit areas with transformed views
22101         */
22102        final RectF mTmpTransformRect1 = new RectF();
22103
22104        /**
22105         * Temporary list of rectanges.
22106         */
22107        final List<RectF> mTmpRectList = new ArrayList<>();
22108
22109        /**
22110         * Temporary for use in transforming invalidation rect
22111         */
22112        final Matrix mTmpMatrix = new Matrix();
22113
22114        /**
22115         * Temporary for use in transforming invalidation rect
22116         */
22117        final Transformation mTmpTransformation = new Transformation();
22118
22119        /**
22120         * Temporary for use in querying outlines from OutlineProviders
22121         */
22122        final Outline mTmpOutline = new Outline();
22123
22124        /**
22125         * Temporary list for use in collecting focusable descendents of a view.
22126         */
22127        final ArrayList<View> mTempArrayList = new ArrayList<View>(24);
22128
22129        /**
22130         * The id of the window for accessibility purposes.
22131         */
22132        int mAccessibilityWindowId = AccessibilityNodeInfo.UNDEFINED_ITEM_ID;
22133
22134        /**
22135         * Flags related to accessibility processing.
22136         *
22137         * @see AccessibilityNodeInfo#FLAG_INCLUDE_NOT_IMPORTANT_VIEWS
22138         * @see AccessibilityNodeInfo#FLAG_REPORT_VIEW_IDS
22139         */
22140        int mAccessibilityFetchFlags;
22141
22142        /**
22143         * The drawable for highlighting accessibility focus.
22144         */
22145        Drawable mAccessibilityFocusDrawable;
22146
22147        /**
22148         * Show where the margins, bounds and layout bounds are for each view.
22149         */
22150        boolean mDebugLayout = SystemProperties.getBoolean(DEBUG_LAYOUT_PROPERTY, false);
22151
22152        /**
22153         * Point used to compute visible regions.
22154         */
22155        final Point mPoint = new Point();
22156
22157        /**
22158         * Used to track which View originated a requestLayout() call, used when
22159         * requestLayout() is called during layout.
22160         */
22161        View mViewRequestingLayout;
22162
22163        /**
22164         * Creates a new set of attachment information with the specified
22165         * events handler and thread.
22166         *
22167         * @param handler the events handler the view must use
22168         */
22169        AttachInfo(IWindowSession session, IWindow window, Display display,
22170                ViewRootImpl viewRootImpl, Handler handler, Callbacks effectPlayer) {
22171            mSession = session;
22172            mWindow = window;
22173            mWindowToken = window.asBinder();
22174            mDisplay = display;
22175            mViewRootImpl = viewRootImpl;
22176            mHandler = handler;
22177            mRootCallbacks = effectPlayer;
22178        }
22179    }
22180
22181    /**
22182     * <p>ScrollabilityCache holds various fields used by a View when scrolling
22183     * is supported. This avoids keeping too many unused fields in most
22184     * instances of View.</p>
22185     */
22186    private static class ScrollabilityCache implements Runnable {
22187
22188        /**
22189         * Scrollbars are not visible
22190         */
22191        public static final int OFF = 0;
22192
22193        /**
22194         * Scrollbars are visible
22195         */
22196        public static final int ON = 1;
22197
22198        /**
22199         * Scrollbars are fading away
22200         */
22201        public static final int FADING = 2;
22202
22203        public boolean fadeScrollBars;
22204
22205        public int fadingEdgeLength;
22206        public int scrollBarDefaultDelayBeforeFade;
22207        public int scrollBarFadeDuration;
22208
22209        public int scrollBarSize;
22210        public ScrollBarDrawable scrollBar;
22211        public float[] interpolatorValues;
22212        public View host;
22213
22214        public final Paint paint;
22215        public final Matrix matrix;
22216        public Shader shader;
22217
22218        public final Interpolator scrollBarInterpolator = new Interpolator(1, 2);
22219
22220        private static final float[] OPAQUE = { 255 };
22221        private static final float[] TRANSPARENT = { 0.0f };
22222
22223        /**
22224         * When fading should start. This time moves into the future every time
22225         * a new scroll happens. Measured based on SystemClock.uptimeMillis()
22226         */
22227        public long fadeStartTime;
22228
22229
22230        /**
22231         * The current state of the scrollbars: ON, OFF, or FADING
22232         */
22233        public int state = OFF;
22234
22235        private int mLastColor;
22236
22237        public ScrollabilityCache(ViewConfiguration configuration, View host) {
22238            fadingEdgeLength = configuration.getScaledFadingEdgeLength();
22239            scrollBarSize = configuration.getScaledScrollBarSize();
22240            scrollBarDefaultDelayBeforeFade = ViewConfiguration.getScrollDefaultDelay();
22241            scrollBarFadeDuration = ViewConfiguration.getScrollBarFadeDuration();
22242
22243            paint = new Paint();
22244            matrix = new Matrix();
22245            // use use a height of 1, and then wack the matrix each time we
22246            // actually use it.
22247            shader = new LinearGradient(0, 0, 0, 1, 0xFF000000, 0, Shader.TileMode.CLAMP);
22248            paint.setShader(shader);
22249            paint.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.DST_OUT));
22250
22251            this.host = host;
22252        }
22253
22254        public void setFadeColor(int color) {
22255            if (color != mLastColor) {
22256                mLastColor = color;
22257
22258                if (color != 0) {
22259                    shader = new LinearGradient(0, 0, 0, 1, color | 0xFF000000,
22260                            color & 0x00FFFFFF, Shader.TileMode.CLAMP);
22261                    paint.setShader(shader);
22262                    // Restore the default transfer mode (src_over)
22263                    paint.setXfermode(null);
22264                } else {
22265                    shader = new LinearGradient(0, 0, 0, 1, 0xFF000000, 0, Shader.TileMode.CLAMP);
22266                    paint.setShader(shader);
22267                    paint.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.DST_OUT));
22268                }
22269            }
22270        }
22271
22272        public void run() {
22273            long now = AnimationUtils.currentAnimationTimeMillis();
22274            if (now >= fadeStartTime) {
22275
22276                // the animation fades the scrollbars out by changing
22277                // the opacity (alpha) from fully opaque to fully
22278                // transparent
22279                int nextFrame = (int) now;
22280                int framesCount = 0;
22281
22282                Interpolator interpolator = scrollBarInterpolator;
22283
22284                // Start opaque
22285                interpolator.setKeyFrame(framesCount++, nextFrame, OPAQUE);
22286
22287                // End transparent
22288                nextFrame += scrollBarFadeDuration;
22289                interpolator.setKeyFrame(framesCount, nextFrame, TRANSPARENT);
22290
22291                state = FADING;
22292
22293                // Kick off the fade animation
22294                host.invalidate(true);
22295            }
22296        }
22297    }
22298
22299    /**
22300     * Resuable callback for sending
22301     * {@link AccessibilityEvent#TYPE_VIEW_SCROLLED} accessibility event.
22302     */
22303    private class SendViewScrolledAccessibilityEvent implements Runnable {
22304        public volatile boolean mIsPending;
22305
22306        public void run() {
22307            sendAccessibilityEvent(AccessibilityEvent.TYPE_VIEW_SCROLLED);
22308            mIsPending = false;
22309        }
22310    }
22311
22312    /**
22313     * <p>
22314     * This class represents a delegate that can be registered in a {@link View}
22315     * to enhance accessibility support via composition rather via inheritance.
22316     * It is specifically targeted to widget developers that extend basic View
22317     * classes i.e. classes in package android.view, that would like their
22318     * applications to be backwards compatible.
22319     * </p>
22320     * <div class="special reference">
22321     * <h3>Developer Guides</h3>
22322     * <p>For more information about making applications accessible, read the
22323     * <a href="{@docRoot}guide/topics/ui/accessibility/index.html">Accessibility</a>
22324     * developer guide.</p>
22325     * </div>
22326     * <p>
22327     * A scenario in which a developer would like to use an accessibility delegate
22328     * is overriding a method introduced in a later API version then the minimal API
22329     * version supported by the application. For example, the method
22330     * {@link View#onInitializeAccessibilityNodeInfo(AccessibilityNodeInfo)} is not available
22331     * in API version 4 when the accessibility APIs were first introduced. If a
22332     * developer would like his application to run on API version 4 devices (assuming
22333     * all other APIs used by the application are version 4 or lower) and take advantage
22334     * of this method, instead of overriding the method which would break the application's
22335     * backwards compatibility, he can override the corresponding method in this
22336     * delegate and register the delegate in the target View if the API version of
22337     * the system is high enough i.e. the API version is same or higher to the API
22338     * version that introduced
22339     * {@link View#onInitializeAccessibilityNodeInfo(AccessibilityNodeInfo)}.
22340     * </p>
22341     * <p>
22342     * Here is an example implementation:
22343     * </p>
22344     * <code><pre><p>
22345     * if (Build.VERSION.SDK_INT >= 14) {
22346     *     // If the API version is equal of higher than the version in
22347     *     // which onInitializeAccessibilityNodeInfo was introduced we
22348     *     // register a delegate with a customized implementation.
22349     *     View view = findViewById(R.id.view_id);
22350     *     view.setAccessibilityDelegate(new AccessibilityDelegate() {
22351     *         public void onInitializeAccessibilityNodeInfo(View host,
22352     *                 AccessibilityNodeInfo info) {
22353     *             // Let the default implementation populate the info.
22354     *             super.onInitializeAccessibilityNodeInfo(host, info);
22355     *             // Set some other information.
22356     *             info.setEnabled(host.isEnabled());
22357     *         }
22358     *     });
22359     * }
22360     * </code></pre></p>
22361     * <p>
22362     * This delegate contains methods that correspond to the accessibility methods
22363     * in View. If a delegate has been specified the implementation in View hands
22364     * off handling to the corresponding method in this delegate. The default
22365     * implementation the delegate methods behaves exactly as the corresponding
22366     * method in View for the case of no accessibility delegate been set. Hence,
22367     * to customize the behavior of a View method, clients can override only the
22368     * corresponding delegate method without altering the behavior of the rest
22369     * accessibility related methods of the host view.
22370     * </p>
22371     * <p>
22372     * <strong>Note:</strong> On platform versions prior to
22373     * {@link android.os.Build.VERSION_CODES#M API 23}, delegate methods on
22374     * views in the {@code android.widget.*} package are called <i>before</i>
22375     * host methods. This prevents certain properties such as class name from
22376     * being modified by overriding
22377     * {@link AccessibilityDelegate#onInitializeAccessibilityNodeInfo(View, AccessibilityNodeInfo)},
22378     * as any changes will be overwritten by the host class.
22379     * <p>
22380     * Starting in {@link android.os.Build.VERSION_CODES#M API 23}, delegate
22381     * methods are called <i>after</i> host methods, which all properties to be
22382     * modified without being overwritten by the host class.
22383     */
22384    public static class AccessibilityDelegate {
22385
22386        /**
22387         * Sends an accessibility event of the given type. If accessibility is not
22388         * enabled this method has no effect.
22389         * <p>
22390         * The default implementation behaves as {@link View#sendAccessibilityEvent(int)
22391         *  View#sendAccessibilityEvent(int)} for the case of no accessibility delegate
22392         * been set.
22393         * </p>
22394         *
22395         * @param host The View hosting the delegate.
22396         * @param eventType The type of the event to send.
22397         *
22398         * @see View#sendAccessibilityEvent(int) View#sendAccessibilityEvent(int)
22399         */
22400        public void sendAccessibilityEvent(View host, int eventType) {
22401            host.sendAccessibilityEventInternal(eventType);
22402        }
22403
22404        /**
22405         * Performs the specified accessibility action on the view. For
22406         * possible accessibility actions look at {@link AccessibilityNodeInfo}.
22407         * <p>
22408         * The default implementation behaves as
22409         * {@link View#performAccessibilityAction(int, Bundle)
22410         *  View#performAccessibilityAction(int, Bundle)} for the case of
22411         *  no accessibility delegate been set.
22412         * </p>
22413         *
22414         * @param action The action to perform.
22415         * @return Whether the action was performed.
22416         *
22417         * @see View#performAccessibilityAction(int, Bundle)
22418         *      View#performAccessibilityAction(int, Bundle)
22419         */
22420        public boolean performAccessibilityAction(View host, int action, Bundle args) {
22421            return host.performAccessibilityActionInternal(action, args);
22422        }
22423
22424        /**
22425         * Sends an accessibility event. This method behaves exactly as
22426         * {@link #sendAccessibilityEvent(View, int)} but takes as an argument an
22427         * empty {@link AccessibilityEvent} and does not perform a check whether
22428         * accessibility is enabled.
22429         * <p>
22430         * The default implementation behaves as
22431         * {@link View#sendAccessibilityEventUnchecked(AccessibilityEvent)
22432         *  View#sendAccessibilityEventUnchecked(AccessibilityEvent)} for
22433         * the case of no accessibility delegate been set.
22434         * </p>
22435         *
22436         * @param host The View hosting the delegate.
22437         * @param event The event to send.
22438         *
22439         * @see View#sendAccessibilityEventUnchecked(AccessibilityEvent)
22440         *      View#sendAccessibilityEventUnchecked(AccessibilityEvent)
22441         */
22442        public void sendAccessibilityEventUnchecked(View host, AccessibilityEvent event) {
22443            host.sendAccessibilityEventUncheckedInternal(event);
22444        }
22445
22446        /**
22447         * Dispatches an {@link AccessibilityEvent} to the host {@link View} first and then
22448         * to its children for adding their text content to the event.
22449         * <p>
22450         * The default implementation behaves as
22451         * {@link View#dispatchPopulateAccessibilityEvent(AccessibilityEvent)
22452         *  View#dispatchPopulateAccessibilityEvent(AccessibilityEvent)} for
22453         * the case of no accessibility delegate been set.
22454         * </p>
22455         *
22456         * @param host The View hosting the delegate.
22457         * @param event The event.
22458         * @return True if the event population was completed.
22459         *
22460         * @see View#dispatchPopulateAccessibilityEvent(AccessibilityEvent)
22461         *      View#dispatchPopulateAccessibilityEvent(AccessibilityEvent)
22462         */
22463        public boolean dispatchPopulateAccessibilityEvent(View host, AccessibilityEvent event) {
22464            return host.dispatchPopulateAccessibilityEventInternal(event);
22465        }
22466
22467        /**
22468         * Gives a chance to the host View to populate the accessibility event with its
22469         * text content.
22470         * <p>
22471         * The default implementation behaves as
22472         * {@link View#onPopulateAccessibilityEvent(AccessibilityEvent)
22473         *  View#onPopulateAccessibilityEvent(AccessibilityEvent)} for
22474         * the case of no accessibility delegate been set.
22475         * </p>
22476         *
22477         * @param host The View hosting the delegate.
22478         * @param event The accessibility event which to populate.
22479         *
22480         * @see View#onPopulateAccessibilityEvent(AccessibilityEvent)
22481         *      View#onPopulateAccessibilityEvent(AccessibilityEvent)
22482         */
22483        public void onPopulateAccessibilityEvent(View host, AccessibilityEvent event) {
22484            host.onPopulateAccessibilityEventInternal(event);
22485        }
22486
22487        /**
22488         * Initializes an {@link AccessibilityEvent} with information about the
22489         * the host View which is the event source.
22490         * <p>
22491         * The default implementation behaves as
22492         * {@link View#onInitializeAccessibilityEvent(AccessibilityEvent)
22493         *  View#onInitializeAccessibilityEvent(AccessibilityEvent)} for
22494         * the case of no accessibility delegate been set.
22495         * </p>
22496         *
22497         * @param host The View hosting the delegate.
22498         * @param event The event to initialize.
22499         *
22500         * @see View#onInitializeAccessibilityEvent(AccessibilityEvent)
22501         *      View#onInitializeAccessibilityEvent(AccessibilityEvent)
22502         */
22503        public void onInitializeAccessibilityEvent(View host, AccessibilityEvent event) {
22504            host.onInitializeAccessibilityEventInternal(event);
22505        }
22506
22507        /**
22508         * Initializes an {@link AccessibilityNodeInfo} with information about the host view.
22509         * <p>
22510         * The default implementation behaves as
22511         * {@link View#onInitializeAccessibilityNodeInfo(AccessibilityNodeInfo)
22512         *  View#onInitializeAccessibilityNodeInfo(AccessibilityNodeInfo)} for
22513         * the case of no accessibility delegate been set.
22514         * </p>
22515         *
22516         * @param host The View hosting the delegate.
22517         * @param info The instance to initialize.
22518         *
22519         * @see View#onInitializeAccessibilityNodeInfo(AccessibilityNodeInfo)
22520         *      View#onInitializeAccessibilityNodeInfo(AccessibilityNodeInfo)
22521         */
22522        public void onInitializeAccessibilityNodeInfo(View host, AccessibilityNodeInfo info) {
22523            host.onInitializeAccessibilityNodeInfoInternal(info);
22524        }
22525
22526        /**
22527         * Called when a child of the host View has requested sending an
22528         * {@link AccessibilityEvent} and gives an opportunity to the parent (the host)
22529         * to augment the event.
22530         * <p>
22531         * The default implementation behaves as
22532         * {@link ViewGroup#onRequestSendAccessibilityEvent(View, AccessibilityEvent)
22533         *  ViewGroup#onRequestSendAccessibilityEvent(View, AccessibilityEvent)} for
22534         * the case of no accessibility delegate been set.
22535         * </p>
22536         *
22537         * @param host The View hosting the delegate.
22538         * @param child The child which requests sending the event.
22539         * @param event The event to be sent.
22540         * @return True if the event should be sent
22541         *
22542         * @see ViewGroup#onRequestSendAccessibilityEvent(View, AccessibilityEvent)
22543         *      ViewGroup#onRequestSendAccessibilityEvent(View, AccessibilityEvent)
22544         */
22545        public boolean onRequestSendAccessibilityEvent(ViewGroup host, View child,
22546                AccessibilityEvent event) {
22547            return host.onRequestSendAccessibilityEventInternal(child, event);
22548        }
22549
22550        /**
22551         * Gets the provider for managing a virtual view hierarchy rooted at this View
22552         * and reported to {@link android.accessibilityservice.AccessibilityService}s
22553         * that explore the window content.
22554         * <p>
22555         * The default implementation behaves as
22556         * {@link View#getAccessibilityNodeProvider() View#getAccessibilityNodeProvider()} for
22557         * the case of no accessibility delegate been set.
22558         * </p>
22559         *
22560         * @return The provider.
22561         *
22562         * @see AccessibilityNodeProvider
22563         */
22564        public AccessibilityNodeProvider getAccessibilityNodeProvider(View host) {
22565            return null;
22566        }
22567
22568        /**
22569         * Returns an {@link AccessibilityNodeInfo} representing the host view from the
22570         * point of view of an {@link android.accessibilityservice.AccessibilityService}.
22571         * This method is responsible for obtaining an accessibility node info from a
22572         * pool of reusable instances and calling
22573         * {@link #onInitializeAccessibilityNodeInfo(AccessibilityNodeInfo)} on the host
22574         * view to initialize the former.
22575         * <p>
22576         * <strong>Note:</strong> The client is responsible for recycling the obtained
22577         * instance by calling {@link AccessibilityNodeInfo#recycle()} to minimize object
22578         * creation.
22579         * </p>
22580         * <p>
22581         * The default implementation behaves as
22582         * {@link View#createAccessibilityNodeInfo() View#createAccessibilityNodeInfo()} for
22583         * the case of no accessibility delegate been set.
22584         * </p>
22585         * @return A populated {@link AccessibilityNodeInfo}.
22586         *
22587         * @see AccessibilityNodeInfo
22588         *
22589         * @hide
22590         */
22591        public AccessibilityNodeInfo createAccessibilityNodeInfo(View host) {
22592            return host.createAccessibilityNodeInfoInternal();
22593        }
22594    }
22595
22596    private class MatchIdPredicate implements Predicate<View> {
22597        public int mId;
22598
22599        @Override
22600        public boolean apply(View view) {
22601            return (view.mID == mId);
22602        }
22603    }
22604
22605    private class MatchLabelForPredicate implements Predicate<View> {
22606        private int mLabeledId;
22607
22608        @Override
22609        public boolean apply(View view) {
22610            return (view.mLabelForId == mLabeledId);
22611        }
22612    }
22613
22614    private class SendViewStateChangedAccessibilityEvent implements Runnable {
22615        private int mChangeTypes = 0;
22616        private boolean mPosted;
22617        private boolean mPostedWithDelay;
22618        private long mLastEventTimeMillis;
22619
22620        @Override
22621        public void run() {
22622            mPosted = false;
22623            mPostedWithDelay = false;
22624            mLastEventTimeMillis = SystemClock.uptimeMillis();
22625            if (AccessibilityManager.getInstance(mContext).isEnabled()) {
22626                final AccessibilityEvent event = AccessibilityEvent.obtain();
22627                event.setEventType(AccessibilityEvent.TYPE_WINDOW_CONTENT_CHANGED);
22628                event.setContentChangeTypes(mChangeTypes);
22629                sendAccessibilityEventUnchecked(event);
22630            }
22631            mChangeTypes = 0;
22632        }
22633
22634        public void runOrPost(int changeType) {
22635            mChangeTypes |= changeType;
22636
22637            // If this is a live region or the child of a live region, collect
22638            // all events from this frame and send them on the next frame.
22639            if (inLiveRegion()) {
22640                // If we're already posted with a delay, remove that.
22641                if (mPostedWithDelay) {
22642                    removeCallbacks(this);
22643                    mPostedWithDelay = false;
22644                }
22645                // Only post if we're not already posted.
22646                if (!mPosted) {
22647                    post(this);
22648                    mPosted = true;
22649                }
22650                return;
22651            }
22652
22653            if (mPosted) {
22654                return;
22655            }
22656
22657            final long timeSinceLastMillis = SystemClock.uptimeMillis() - mLastEventTimeMillis;
22658            final long minEventIntevalMillis =
22659                    ViewConfiguration.getSendRecurringAccessibilityEventsInterval();
22660            if (timeSinceLastMillis >= minEventIntevalMillis) {
22661                removeCallbacks(this);
22662                run();
22663            } else {
22664                postDelayed(this, minEventIntevalMillis - timeSinceLastMillis);
22665                mPostedWithDelay = true;
22666            }
22667        }
22668    }
22669
22670    private boolean inLiveRegion() {
22671        if (getAccessibilityLiveRegion() != View.ACCESSIBILITY_LIVE_REGION_NONE) {
22672            return true;
22673        }
22674
22675        ViewParent parent = getParent();
22676        while (parent instanceof View) {
22677            if (((View) parent).getAccessibilityLiveRegion()
22678                    != View.ACCESSIBILITY_LIVE_REGION_NONE) {
22679                return true;
22680            }
22681            parent = parent.getParent();
22682        }
22683
22684        return false;
22685    }
22686
22687    /**
22688     * Dump all private flags in readable format, useful for documentation and
22689     * sanity checking.
22690     */
22691    private static void dumpFlags() {
22692        final HashMap<String, String> found = Maps.newHashMap();
22693        try {
22694            for (Field field : View.class.getDeclaredFields()) {
22695                final int modifiers = field.getModifiers();
22696                if (Modifier.isStatic(modifiers) && Modifier.isFinal(modifiers)) {
22697                    if (field.getType().equals(int.class)) {
22698                        final int value = field.getInt(null);
22699                        dumpFlag(found, field.getName(), value);
22700                    } else if (field.getType().equals(int[].class)) {
22701                        final int[] values = (int[]) field.get(null);
22702                        for (int i = 0; i < values.length; i++) {
22703                            dumpFlag(found, field.getName() + "[" + i + "]", values[i]);
22704                        }
22705                    }
22706                }
22707            }
22708        } catch (IllegalAccessException e) {
22709            throw new RuntimeException(e);
22710        }
22711
22712        final ArrayList<String> keys = Lists.newArrayList();
22713        keys.addAll(found.keySet());
22714        Collections.sort(keys);
22715        for (String key : keys) {
22716            Log.d(VIEW_LOG_TAG, found.get(key));
22717        }
22718    }
22719
22720    private static void dumpFlag(HashMap<String, String> found, String name, int value) {
22721        // Sort flags by prefix, then by bits, always keeping unique keys
22722        final String bits = String.format("%32s", Integer.toBinaryString(value)).replace('0', ' ');
22723        final int prefix = name.indexOf('_');
22724        final String key = (prefix > 0 ? name.substring(0, prefix) : name) + bits + name;
22725        final String output = bits + " " + name;
22726        found.put(key, output);
22727    }
22728
22729    /** {@hide} */
22730    public void encode(@NonNull ViewHierarchyEncoder stream) {
22731        stream.beginObject(this);
22732        encodeProperties(stream);
22733        stream.endObject();
22734    }
22735
22736    /** {@hide} */
22737    @CallSuper
22738    protected void encodeProperties(@NonNull ViewHierarchyEncoder stream) {
22739        Object resolveId = ViewDebug.resolveId(getContext(), mID);
22740        if (resolveId instanceof String) {
22741            stream.addProperty("id", (String) resolveId);
22742        } else {
22743            stream.addProperty("id", mID);
22744        }
22745
22746        stream.addProperty("misc:transformation.alpha",
22747                mTransformationInfo != null ? mTransformationInfo.mAlpha : 0);
22748        stream.addProperty("misc:transitionName", getTransitionName());
22749
22750        // layout
22751        stream.addProperty("layout:left", mLeft);
22752        stream.addProperty("layout:right", mRight);
22753        stream.addProperty("layout:top", mTop);
22754        stream.addProperty("layout:bottom", mBottom);
22755        stream.addProperty("layout:width", getWidth());
22756        stream.addProperty("layout:height", getHeight());
22757        stream.addProperty("layout:layoutDirection", getLayoutDirection());
22758        stream.addProperty("layout:layoutRtl", isLayoutRtl());
22759        stream.addProperty("layout:hasTransientState", hasTransientState());
22760        stream.addProperty("layout:baseline", getBaseline());
22761
22762        // layout params
22763        ViewGroup.LayoutParams layoutParams = getLayoutParams();
22764        if (layoutParams != null) {
22765            stream.addPropertyKey("layoutParams");
22766            layoutParams.encode(stream);
22767        }
22768
22769        // scrolling
22770        stream.addProperty("scrolling:scrollX", mScrollX);
22771        stream.addProperty("scrolling:scrollY", mScrollY);
22772
22773        // padding
22774        stream.addProperty("padding:paddingLeft", mPaddingLeft);
22775        stream.addProperty("padding:paddingRight", mPaddingRight);
22776        stream.addProperty("padding:paddingTop", mPaddingTop);
22777        stream.addProperty("padding:paddingBottom", mPaddingBottom);
22778        stream.addProperty("padding:userPaddingRight", mUserPaddingRight);
22779        stream.addProperty("padding:userPaddingLeft", mUserPaddingLeft);
22780        stream.addProperty("padding:userPaddingBottom", mUserPaddingBottom);
22781        stream.addProperty("padding:userPaddingStart", mUserPaddingStart);
22782        stream.addProperty("padding:userPaddingEnd", mUserPaddingEnd);
22783
22784        // measurement
22785        stream.addProperty("measurement:minHeight", mMinHeight);
22786        stream.addProperty("measurement:minWidth", mMinWidth);
22787        stream.addProperty("measurement:measuredWidth", mMeasuredWidth);
22788        stream.addProperty("measurement:measuredHeight", mMeasuredHeight);
22789
22790        // drawing
22791        stream.addProperty("drawing:elevation", getElevation());
22792        stream.addProperty("drawing:translationX", getTranslationX());
22793        stream.addProperty("drawing:translationY", getTranslationY());
22794        stream.addProperty("drawing:translationZ", getTranslationZ());
22795        stream.addProperty("drawing:rotation", getRotation());
22796        stream.addProperty("drawing:rotationX", getRotationX());
22797        stream.addProperty("drawing:rotationY", getRotationY());
22798        stream.addProperty("drawing:scaleX", getScaleX());
22799        stream.addProperty("drawing:scaleY", getScaleY());
22800        stream.addProperty("drawing:pivotX", getPivotX());
22801        stream.addProperty("drawing:pivotY", getPivotY());
22802        stream.addProperty("drawing:opaque", isOpaque());
22803        stream.addProperty("drawing:alpha", getAlpha());
22804        stream.addProperty("drawing:transitionAlpha", getTransitionAlpha());
22805        stream.addProperty("drawing:shadow", hasShadow());
22806        stream.addProperty("drawing:solidColor", getSolidColor());
22807        stream.addProperty("drawing:layerType", mLayerType);
22808        stream.addProperty("drawing:willNotDraw", willNotDraw());
22809        stream.addProperty("drawing:hardwareAccelerated", isHardwareAccelerated());
22810        stream.addProperty("drawing:willNotCacheDrawing", willNotCacheDrawing());
22811        stream.addProperty("drawing:drawingCacheEnabled", isDrawingCacheEnabled());
22812        stream.addProperty("drawing:overlappingRendering", hasOverlappingRendering());
22813
22814        // focus
22815        stream.addProperty("focus:hasFocus", hasFocus());
22816        stream.addProperty("focus:isFocused", isFocused());
22817        stream.addProperty("focus:isFocusable", isFocusable());
22818        stream.addProperty("focus:isFocusableInTouchMode", isFocusableInTouchMode());
22819
22820        stream.addProperty("misc:clickable", isClickable());
22821        stream.addProperty("misc:pressed", isPressed());
22822        stream.addProperty("misc:selected", isSelected());
22823        stream.addProperty("misc:touchMode", isInTouchMode());
22824        stream.addProperty("misc:hovered", isHovered());
22825        stream.addProperty("misc:activated", isActivated());
22826
22827        stream.addProperty("misc:visibility", getVisibility());
22828        stream.addProperty("misc:fitsSystemWindows", getFitsSystemWindows());
22829        stream.addProperty("misc:filterTouchesWhenObscured", getFilterTouchesWhenObscured());
22830
22831        stream.addProperty("misc:enabled", isEnabled());
22832        stream.addProperty("misc:soundEffectsEnabled", isSoundEffectsEnabled());
22833        stream.addProperty("misc:hapticFeedbackEnabled", isHapticFeedbackEnabled());
22834
22835        // theme attributes
22836        Resources.Theme theme = getContext().getTheme();
22837        if (theme != null) {
22838            stream.addPropertyKey("theme");
22839            theme.encode(stream);
22840        }
22841
22842        // view attribute information
22843        int n = mAttributes != null ? mAttributes.length : 0;
22844        stream.addProperty("meta:__attrCount__", n/2);
22845        for (int i = 0; i < n; i += 2) {
22846            stream.addProperty("meta:__attr__" + mAttributes[i], mAttributes[i+1]);
22847        }
22848
22849        stream.addProperty("misc:scrollBarStyle", getScrollBarStyle());
22850
22851        // text
22852        stream.addProperty("text:textDirection", getTextDirection());
22853        stream.addProperty("text:textAlignment", getTextAlignment());
22854
22855        // accessibility
22856        CharSequence contentDescription = getContentDescription();
22857        stream.addProperty("accessibility:contentDescription",
22858                contentDescription == null ? "" : contentDescription.toString());
22859        stream.addProperty("accessibility:labelFor", getLabelFor());
22860        stream.addProperty("accessibility:importantForAccessibility", getImportantForAccessibility());
22861    }
22862}
22863