View.java revision aa1a94daaa59e98303fdeb1c3066b60a58755dff
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.ViewGroup.LayoutParams;
87import android.view.accessibility.AccessibilityEvent;
88import android.view.accessibility.AccessibilityEventSource;
89import android.view.accessibility.AccessibilityManager;
90import android.view.accessibility.AccessibilityNodeInfo;
91import android.view.accessibility.AccessibilityNodeInfo.AccessibilityAction;
92import android.view.accessibility.AccessibilityNodeProvider;
93import android.view.animation.Animation;
94import android.view.animation.AnimationUtils;
95import android.view.animation.Transformation;
96import android.view.inputmethod.EditorInfo;
97import android.view.inputmethod.InputConnection;
98import android.view.inputmethod.InputMethodManager;
99import android.widget.Checkable;
100import android.widget.FrameLayout;
101import android.widget.ScrollBarDrawable;
102
103import static android.os.Build.VERSION_CODES.*;
104import static java.lang.Math.max;
105
106import com.android.internal.R;
107import com.android.internal.util.Predicate;
108import com.android.internal.view.menu.MenuBuilder;
109import com.google.android.collect.Lists;
110import com.google.android.collect.Maps;
111
112import java.lang.annotation.Retention;
113import java.lang.annotation.RetentionPolicy;
114import java.lang.ref.WeakReference;
115import java.lang.reflect.Field;
116import java.lang.reflect.InvocationTargetException;
117import java.lang.reflect.Method;
118import java.lang.reflect.Modifier;
119import java.util.ArrayList;
120import java.util.Arrays;
121import java.util.Collections;
122import java.util.HashMap;
123import java.util.List;
124import java.util.Locale;
125import java.util.Map;
126import java.util.concurrent.CopyOnWriteArrayList;
127import java.util.concurrent.atomic.AtomicInteger;
128
129/**
130 * <p>
131 * This class represents the basic building block for user interface components. A View
132 * occupies a rectangular area on the screen and is responsible for drawing and
133 * event handling. View is the base class for <em>widgets</em>, which are
134 * used to create interactive UI components (buttons, text fields, etc.). The
135 * {@link android.view.ViewGroup} subclass is the base class for <em>layouts</em>, which
136 * are invisible containers that hold other Views (or other ViewGroups) and define
137 * their layout properties.
138 * </p>
139 *
140 * <div class="special reference">
141 * <h3>Developer Guides</h3>
142 * <p>For information about using this class to develop your application's user interface,
143 * read the <a href="{@docRoot}guide/topics/ui/index.html">User Interface</a> developer guide.
144 * </div>
145 *
146 * <a name="Using"></a>
147 * <h3>Using Views</h3>
148 * <p>
149 * All of the views in a window are arranged in a single tree. You can add views
150 * either from code or by specifying a tree of views in one or more XML layout
151 * files. There are many specialized subclasses of views that act as controls or
152 * are capable of displaying text, images, or other content.
153 * </p>
154 * <p>
155 * Once you have created a tree of views, there are typically a few types of
156 * common operations you may wish to perform:
157 * <ul>
158 * <li><strong>Set properties:</strong> for example setting the text of a
159 * {@link android.widget.TextView}. The available properties and the methods
160 * that set them will vary among the different subclasses of views. Note that
161 * properties that are known at build time can be set in the XML layout
162 * files.</li>
163 * <li><strong>Set focus:</strong> The framework will handled moving focus in
164 * response to user input. To force focus to a specific view, call
165 * {@link #requestFocus}.</li>
166 * <li><strong>Set up listeners:</strong> Views allow clients to set listeners
167 * that will be notified when something interesting happens to the view. For
168 * example, all views will let you set a listener to be notified when the view
169 * gains or loses focus. You can register such a listener using
170 * {@link #setOnFocusChangeListener(android.view.View.OnFocusChangeListener)}.
171 * Other view subclasses offer more specialized listeners. For example, a Button
172 * exposes a listener to notify clients when the button is clicked.</li>
173 * <li><strong>Set visibility:</strong> You can hide or show views using
174 * {@link #setVisibility(int)}.</li>
175 * </ul>
176 * </p>
177 * <p><em>
178 * Note: The Android framework is responsible for measuring, laying out and
179 * drawing views. You should not call methods that perform these actions on
180 * views yourself unless you are actually implementing a
181 * {@link android.view.ViewGroup}.
182 * </em></p>
183 *
184 * <a name="Lifecycle"></a>
185 * <h3>Implementing a Custom View</h3>
186 *
187 * <p>
188 * To implement a custom view, you will usually begin by providing overrides for
189 * some of the standard methods that the framework calls on all views. You do
190 * not need to override all of these methods. In fact, you can start by just
191 * overriding {@link #onDraw(android.graphics.Canvas)}.
192 * <table border="2" width="85%" align="center" cellpadding="5">
193 *     <thead>
194 *         <tr><th>Category</th> <th>Methods</th> <th>Description</th></tr>
195 *     </thead>
196 *
197 *     <tbody>
198 *     <tr>
199 *         <td rowspan="2">Creation</td>
200 *         <td>Constructors</td>
201 *         <td>There is a form of the constructor that are called when the view
202 *         is created from code and a form that is called when the view is
203 *         inflated from a layout file. The second form should parse and apply
204 *         any attributes defined in the layout file.
205 *         </td>
206 *     </tr>
207 *     <tr>
208 *         <td><code>{@link #onFinishInflate()}</code></td>
209 *         <td>Called after a view and all of its children has been inflated
210 *         from XML.</td>
211 *     </tr>
212 *
213 *     <tr>
214 *         <td rowspan="3">Layout</td>
215 *         <td><code>{@link #onMeasure(int, int)}</code></td>
216 *         <td>Called to determine the size requirements for this view and all
217 *         of its children.
218 *         </td>
219 *     </tr>
220 *     <tr>
221 *         <td><code>{@link #onLayout(boolean, int, int, int, int)}</code></td>
222 *         <td>Called when this view should assign a size and position to all
223 *         of its children.
224 *         </td>
225 *     </tr>
226 *     <tr>
227 *         <td><code>{@link #onSizeChanged(int, int, int, int)}</code></td>
228 *         <td>Called when the size of this view has changed.
229 *         </td>
230 *     </tr>
231 *
232 *     <tr>
233 *         <td>Drawing</td>
234 *         <td><code>{@link #onDraw(android.graphics.Canvas)}</code></td>
235 *         <td>Called when the view should render its content.
236 *         </td>
237 *     </tr>
238 *
239 *     <tr>
240 *         <td rowspan="4">Event processing</td>
241 *         <td><code>{@link #onKeyDown(int, KeyEvent)}</code></td>
242 *         <td>Called when a new hardware key event occurs.
243 *         </td>
244 *     </tr>
245 *     <tr>
246 *         <td><code>{@link #onKeyUp(int, KeyEvent)}</code></td>
247 *         <td>Called when a hardware key up event occurs.
248 *         </td>
249 *     </tr>
250 *     <tr>
251 *         <td><code>{@link #onTrackballEvent(MotionEvent)}</code></td>
252 *         <td>Called when a trackball motion event occurs.
253 *         </td>
254 *     </tr>
255 *     <tr>
256 *         <td><code>{@link #onTouchEvent(MotionEvent)}</code></td>
257 *         <td>Called when a touch screen motion event occurs.
258 *         </td>
259 *     </tr>
260 *
261 *     <tr>
262 *         <td rowspan="2">Focus</td>
263 *         <td><code>{@link #onFocusChanged(boolean, int, android.graphics.Rect)}</code></td>
264 *         <td>Called when the view gains or loses focus.
265 *         </td>
266 *     </tr>
267 *
268 *     <tr>
269 *         <td><code>{@link #onWindowFocusChanged(boolean)}</code></td>
270 *         <td>Called when the window containing the view gains or loses focus.
271 *         </td>
272 *     </tr>
273 *
274 *     <tr>
275 *         <td rowspan="3">Attaching</td>
276 *         <td><code>{@link #onAttachedToWindow()}</code></td>
277 *         <td>Called when the view is attached to a window.
278 *         </td>
279 *     </tr>
280 *
281 *     <tr>
282 *         <td><code>{@link #onDetachedFromWindow}</code></td>
283 *         <td>Called when the view is detached from its window.
284 *         </td>
285 *     </tr>
286 *
287 *     <tr>
288 *         <td><code>{@link #onWindowVisibilityChanged(int)}</code></td>
289 *         <td>Called when the visibility of the window containing the view
290 *         has changed.
291 *         </td>
292 *     </tr>
293 *     </tbody>
294 *
295 * </table>
296 * </p>
297 *
298 * <a name="IDs"></a>
299 * <h3>IDs</h3>
300 * Views may have an integer id associated with them. These ids are typically
301 * assigned in the layout XML files, and are used to find specific views within
302 * the view tree. A common pattern is to:
303 * <ul>
304 * <li>Define a Button in the layout file and assign it a unique ID.
305 * <pre>
306 * &lt;Button
307 *     android:id="@+id/my_button"
308 *     android:layout_width="wrap_content"
309 *     android:layout_height="wrap_content"
310 *     android:text="@string/my_button_text"/&gt;
311 * </pre></li>
312 * <li>From the onCreate method of an Activity, find the Button
313 * <pre class="prettyprint">
314 *      Button myButton = (Button) findViewById(R.id.my_button);
315 * </pre></li>
316 * </ul>
317 * <p>
318 * View IDs need not be unique throughout the tree, but it is good practice to
319 * ensure that they are at least unique within the part of the tree you are
320 * searching.
321 * </p>
322 *
323 * <a name="Position"></a>
324 * <h3>Position</h3>
325 * <p>
326 * The geometry of a view is that of a rectangle. A view has a location,
327 * expressed as a pair of <em>left</em> and <em>top</em> coordinates, and
328 * two dimensions, expressed as a width and a height. The unit for location
329 * and dimensions is the pixel.
330 * </p>
331 *
332 * <p>
333 * It is possible to retrieve the location of a view by invoking the methods
334 * {@link #getLeft()} and {@link #getTop()}. The former returns the left, or X,
335 * coordinate of the rectangle representing the view. The latter returns the
336 * top, or Y, coordinate of the rectangle representing the view. These methods
337 * both return the location of the view relative to its parent. For instance,
338 * when getLeft() returns 20, that means the view is located 20 pixels to the
339 * right of the left edge of its direct parent.
340 * </p>
341 *
342 * <p>
343 * In addition, several convenience methods are offered to avoid unnecessary
344 * computations, namely {@link #getRight()} and {@link #getBottom()}.
345 * These methods return the coordinates of the right and bottom edges of the
346 * rectangle representing the view. For instance, calling {@link #getRight()}
347 * is similar to the following computation: <code>getLeft() + getWidth()</code>
348 * (see <a href="#SizePaddingMargins">Size</a> for more information about the width.)
349 * </p>
350 *
351 * <a name="SizePaddingMargins"></a>
352 * <h3>Size, padding and margins</h3>
353 * <p>
354 * The size of a view is expressed with a width and a height. A view actually
355 * possess two pairs of width and height values.
356 * </p>
357 *
358 * <p>
359 * The first pair is known as <em>measured width</em> and
360 * <em>measured height</em>. These dimensions define how big a view wants to be
361 * within its parent (see <a href="#Layout">Layout</a> for more details.) The
362 * measured dimensions can be obtained by calling {@link #getMeasuredWidth()}
363 * and {@link #getMeasuredHeight()}.
364 * </p>
365 *
366 * <p>
367 * The second pair is simply known as <em>width</em> and <em>height</em>, or
368 * sometimes <em>drawing width</em> and <em>drawing height</em>. These
369 * dimensions define the actual size of the view on screen, at drawing time and
370 * after layout. These values may, but do not have to, be different from the
371 * measured width and height. The width and height can be obtained by calling
372 * {@link #getWidth()} and {@link #getHeight()}.
373 * </p>
374 *
375 * <p>
376 * To measure its dimensions, a view takes into account its padding. The padding
377 * is expressed in pixels for the left, top, right and bottom parts of the view.
378 * Padding can be used to offset the content of the view by a specific amount of
379 * pixels. For instance, a left padding of 2 will push the view's content by
380 * 2 pixels to the right of the left edge. Padding can be set using the
381 * {@link #setPadding(int, int, int, int)} or {@link #setPaddingRelative(int, int, int, int)}
382 * method and queried by calling {@link #getPaddingLeft()}, {@link #getPaddingTop()},
383 * {@link #getPaddingRight()}, {@link #getPaddingBottom()}, {@link #getPaddingStart()},
384 * {@link #getPaddingEnd()}.
385 * </p>
386 *
387 * <p>
388 * Even though a view can define a padding, it does not provide any support for
389 * margins. However, view groups provide such a support. Refer to
390 * {@link android.view.ViewGroup} and
391 * {@link android.view.ViewGroup.MarginLayoutParams} for further information.
392 * </p>
393 *
394 * <a name="Layout"></a>
395 * <h3>Layout</h3>
396 * <p>
397 * Layout is a two pass process: a measure pass and a layout pass. The measuring
398 * pass is implemented in {@link #measure(int, int)} and is a top-down traversal
399 * of the view tree. Each view pushes dimension specifications down the tree
400 * during the recursion. At the end of the measure pass, every view has stored
401 * its measurements. The second pass happens in
402 * {@link #layout(int,int,int,int)} and is also top-down. During
403 * this pass each parent is responsible for positioning all of its children
404 * using the sizes computed in the measure pass.
405 * </p>
406 *
407 * <p>
408 * When a view's measure() method returns, its {@link #getMeasuredWidth()} and
409 * {@link #getMeasuredHeight()} values must be set, along with those for all of
410 * that view's descendants. A view's measured width and measured height values
411 * must respect the constraints imposed by the view's parents. This guarantees
412 * that at the end of the measure pass, all parents accept all of their
413 * children's measurements. A parent view may call measure() more than once on
414 * its children. For example, the parent may measure each child once with
415 * unspecified dimensions to find out how big they want to be, then call
416 * measure() on them again with actual numbers if the sum of all the children's
417 * unconstrained sizes is too big or too small.
418 * </p>
419 *
420 * <p>
421 * The measure pass uses two classes to communicate dimensions. The
422 * {@link MeasureSpec} class is used by views to tell their parents how they
423 * want to be measured and positioned. The base LayoutParams class just
424 * describes how big the view wants to be for both width and height. For each
425 * dimension, it can specify one of:
426 * <ul>
427 * <li> an exact number
428 * <li>MATCH_PARENT, which means the view wants to be as big as its parent
429 * (minus padding)
430 * <li> WRAP_CONTENT, which means that the view wants to be just big enough to
431 * enclose its content (plus padding).
432 * </ul>
433 * There are subclasses of LayoutParams for different subclasses of ViewGroup.
434 * For example, AbsoluteLayout has its own subclass of LayoutParams which adds
435 * an X and Y value.
436 * </p>
437 *
438 * <p>
439 * MeasureSpecs are used to push requirements down the tree from parent to
440 * child. A MeasureSpec can be in one of three modes:
441 * <ul>
442 * <li>UNSPECIFIED: This is used by a parent to determine the desired dimension
443 * of a child view. For example, a LinearLayout may call measure() on its child
444 * with the height set to UNSPECIFIED and a width of EXACTLY 240 to find out how
445 * tall the child view wants to be given a width of 240 pixels.
446 * <li>EXACTLY: This is used by the parent to impose an exact size on the
447 * child. The child must use this size, and guarantee that all of its
448 * descendants will fit within this size.
449 * <li>AT_MOST: This is used by the parent to impose a maximum size on the
450 * child. The child must guarantee that it and all of its descendants will fit
451 * within this size.
452 * </ul>
453 * </p>
454 *
455 * <p>
456 * To initiate a layout, call {@link #requestLayout}. This method is typically
457 * called by a view on itself when it believes that is can no longer fit within
458 * its current bounds.
459 * </p>
460 *
461 * <a name="Drawing"></a>
462 * <h3>Drawing</h3>
463 * <p>
464 * Drawing is handled by walking the tree and recording the drawing commands of
465 * any View that needs to update. After this, the drawing commands of the
466 * entire tree are issued to screen, clipped to the newly damaged area.
467 * </p>
468 *
469 * <p>
470 * The tree is largely recorded and drawn in order, with parents drawn before
471 * (i.e., behind) their children, with siblings drawn in the order they appear
472 * in the tree. If you set a background drawable for a View, then the View will
473 * draw it before calling back to its <code>onDraw()</code> method. The child
474 * drawing order can be overridden with
475 * {@link ViewGroup#setChildrenDrawingOrderEnabled(boolean) custom child drawing order}
476 * in a ViewGroup, and with {@link #setZ(float)} custom Z values} set on Views.
477 * </p>
478 *
479 * <p>
480 * To force a view to draw, call {@link #invalidate()}.
481 * </p>
482 *
483 * <a name="EventHandlingThreading"></a>
484 * <h3>Event Handling and Threading</h3>
485 * <p>
486 * The basic cycle of a view is as follows:
487 * <ol>
488 * <li>An event comes in and is dispatched to the appropriate view. The view
489 * handles the event and notifies any listeners.</li>
490 * <li>If in the course of processing the event, the view's bounds may need
491 * to be changed, the view will call {@link #requestLayout()}.</li>
492 * <li>Similarly, if in the course of processing the event the view's appearance
493 * may need to be changed, the view will call {@link #invalidate()}.</li>
494 * <li>If either {@link #requestLayout()} or {@link #invalidate()} were called,
495 * the framework will take care of measuring, laying out, and drawing the tree
496 * as appropriate.</li>
497 * </ol>
498 * </p>
499 *
500 * <p><em>Note: The entire view tree is single threaded. You must always be on
501 * the UI thread when calling any method on any view.</em>
502 * If you are doing work on other threads and want to update the state of a view
503 * from that thread, you should use a {@link Handler}.
504 * </p>
505 *
506 * <a name="FocusHandling"></a>
507 * <h3>Focus Handling</h3>
508 * <p>
509 * The framework will handle routine focus movement in response to user input.
510 * This includes changing the focus as views are removed or hidden, or as new
511 * views become available. Views indicate their willingness to take focus
512 * through the {@link #isFocusable} method. To change whether a view can take
513 * focus, call {@link #setFocusable(boolean)}.  When in touch mode (see notes below)
514 * views indicate whether they still would like focus via {@link #isFocusableInTouchMode}
515 * and can change this via {@link #setFocusableInTouchMode(boolean)}.
516 * </p>
517 * <p>
518 * Focus movement is based on an algorithm which finds the nearest neighbor in a
519 * given direction. In rare cases, the default algorithm may not match the
520 * intended behavior of the developer. In these situations, you can provide
521 * explicit overrides by using these XML attributes in the layout file:
522 * <pre>
523 * nextFocusDown
524 * nextFocusLeft
525 * nextFocusRight
526 * nextFocusUp
527 * </pre>
528 * </p>
529 *
530 *
531 * <p>
532 * To get a particular view to take focus, call {@link #requestFocus()}.
533 * </p>
534 *
535 * <a name="TouchMode"></a>
536 * <h3>Touch Mode</h3>
537 * <p>
538 * When a user is navigating a user interface via directional keys such as a D-pad, it is
539 * necessary to give focus to actionable items such as buttons so the user can see
540 * what will take input.  If the device has touch capabilities, however, and the user
541 * begins interacting with the interface by touching it, it is no longer necessary to
542 * always highlight, or give focus to, a particular view.  This motivates a mode
543 * for interaction named 'touch mode'.
544 * </p>
545 * <p>
546 * For a touch capable device, once the user touches the screen, the device
547 * will enter touch mode.  From this point onward, only views for which
548 * {@link #isFocusableInTouchMode} is true will be focusable, such as text editing widgets.
549 * Other views that are touchable, like buttons, will not take focus when touched; they will
550 * only fire the on click listeners.
551 * </p>
552 * <p>
553 * Any time a user hits a directional key, such as a D-pad direction, the view device will
554 * exit touch mode, and find a view to take focus, so that the user may resume interacting
555 * with the user interface without touching the screen again.
556 * </p>
557 * <p>
558 * The touch mode state is maintained across {@link android.app.Activity}s.  Call
559 * {@link #isInTouchMode} to see whether the device is currently in touch mode.
560 * </p>
561 *
562 * <a name="Scrolling"></a>
563 * <h3>Scrolling</h3>
564 * <p>
565 * The framework provides basic support for views that wish to internally
566 * scroll their content. This includes keeping track of the X and Y scroll
567 * offset as well as mechanisms for drawing scrollbars. See
568 * {@link #scrollBy(int, int)}, {@link #scrollTo(int, int)}, and
569 * {@link #awakenScrollBars()} for more details.
570 * </p>
571 *
572 * <a name="Tags"></a>
573 * <h3>Tags</h3>
574 * <p>
575 * Unlike IDs, tags are not used to identify views. Tags are essentially an
576 * extra piece of information that can be associated with a view. They are most
577 * often used as a convenience to store data related to views in the views
578 * themselves rather than by putting them in a separate structure.
579 * </p>
580 * <p>
581 * Tags may be specified with character sequence values in layout XML as either
582 * a single tag using the {@link android.R.styleable#View_tag android:tag}
583 * attribute or multiple tags using the {@code <tag>} child element:
584 * <pre>
585 *     &ltView ...
586 *           android:tag="@string/mytag_value" /&gt;
587 *     &ltView ...&gt;
588 *         &lttag android:id="@+id/mytag"
589 *              android:value="@string/mytag_value" /&gt;
590 *     &lt/View>
591 * </pre>
592 * </p>
593 * <p>
594 * Tags may also be specified with arbitrary objects from code using
595 * {@link #setTag(Object)} or {@link #setTag(int, Object)}.
596 * </p>
597 *
598 * <a name="Themes"></a>
599 * <h3>Themes</h3>
600 * <p>
601 * By default, Views are created using the theme of the Context object supplied
602 * to their constructor; however, a different theme may be specified by using
603 * the {@link android.R.styleable#View_theme android:theme} attribute in layout
604 * XML or by passing a {@link ContextThemeWrapper} to the constructor from
605 * code.
606 * </p>
607 * <p>
608 * When the {@link android.R.styleable#View_theme android:theme} attribute is
609 * used in XML, the specified theme is applied on top of the inflation
610 * context's theme (see {@link LayoutInflater}) and used for the view itself as
611 * well as any child elements.
612 * </p>
613 * <p>
614 * In the following example, both views will be created using the Material dark
615 * color scheme; however, because an overlay theme is used which only defines a
616 * subset of attributes, the value of
617 * {@link android.R.styleable#Theme_colorAccent android:colorAccent} defined on
618 * the inflation context's theme (e.g. the Activity theme) will be preserved.
619 * <pre>
620 *     &ltLinearLayout
621 *             ...
622 *             android:theme="@android:theme/ThemeOverlay.Material.Dark"&gt;
623 *         &ltView ...&gt;
624 *     &lt/LinearLayout&gt;
625 * </pre>
626 * </p>
627 *
628 * <a name="Properties"></a>
629 * <h3>Properties</h3>
630 * <p>
631 * The View class exposes an {@link #ALPHA} property, as well as several transform-related
632 * properties, such as {@link #TRANSLATION_X} and {@link #TRANSLATION_Y}. These properties are
633 * available both in the {@link Property} form as well as in similarly-named setter/getter
634 * methods (such as {@link #setAlpha(float)} for {@link #ALPHA}). These properties can
635 * be used to set persistent state associated with these rendering-related properties on the view.
636 * The properties and methods can also be used in conjunction with
637 * {@link android.animation.Animator Animator}-based animations, described more in the
638 * <a href="#Animation">Animation</a> section.
639 * </p>
640 *
641 * <a name="Animation"></a>
642 * <h3>Animation</h3>
643 * <p>
644 * Starting with Android 3.0, the preferred way of animating views is to use the
645 * {@link android.animation} package APIs. These {@link android.animation.Animator Animator}-based
646 * classes change actual properties of the View object, such as {@link #setAlpha(float) alpha} and
647 * {@link #setTranslationX(float) translationX}. This behavior is contrasted to that of the pre-3.0
648 * {@link android.view.animation.Animation Animation}-based classes, which instead animate only
649 * how the view is drawn on the display. In particular, the {@link ViewPropertyAnimator} class
650 * makes animating these View properties particularly easy and efficient.
651 * </p>
652 * <p>
653 * Alternatively, you can use the pre-3.0 animation classes to animate how Views are rendered.
654 * You can attach an {@link Animation} object to a view using
655 * {@link #setAnimation(Animation)} or
656 * {@link #startAnimation(Animation)}. The animation can alter the scale,
657 * rotation, translation and alpha of a view over time. If the animation is
658 * attached to a view that has children, the animation will affect the entire
659 * subtree rooted by that node. When an animation is started, the framework will
660 * take care of redrawing the appropriate views until the animation completes.
661 * </p>
662 *
663 * <a name="Security"></a>
664 * <h3>Security</h3>
665 * <p>
666 * Sometimes it is essential that an application be able to verify that an action
667 * is being performed with the full knowledge and consent of the user, such as
668 * granting a permission request, making a purchase or clicking on an advertisement.
669 * Unfortunately, a malicious application could try to spoof the user into
670 * performing these actions, unaware, by concealing the intended purpose of the view.
671 * As a remedy, the framework offers a touch filtering mechanism that can be used to
672 * improve the security of views that provide access to sensitive functionality.
673 * </p><p>
674 * To enable touch filtering, call {@link #setFilterTouchesWhenObscured(boolean)} or set the
675 * android:filterTouchesWhenObscured layout attribute to true.  When enabled, the framework
676 * will discard touches that are received whenever the view's window is obscured by
677 * another visible window.  As a result, the view will not receive touches whenever a
678 * toast, dialog or other window appears above the view's window.
679 * </p><p>
680 * For more fine-grained control over security, consider overriding the
681 * {@link #onFilterTouchEventForSecurity(MotionEvent)} method to implement your own
682 * security policy. See also {@link MotionEvent#FLAG_WINDOW_IS_OBSCURED}.
683 * </p>
684 *
685 * @attr ref android.R.styleable#View_alpha
686 * @attr ref android.R.styleable#View_background
687 * @attr ref android.R.styleable#View_clickable
688 * @attr ref android.R.styleable#View_contentDescription
689 * @attr ref android.R.styleable#View_drawingCacheQuality
690 * @attr ref android.R.styleable#View_duplicateParentState
691 * @attr ref android.R.styleable#View_id
692 * @attr ref android.R.styleable#View_requiresFadingEdge
693 * @attr ref android.R.styleable#View_fadeScrollbars
694 * @attr ref android.R.styleable#View_fadingEdgeLength
695 * @attr ref android.R.styleable#View_filterTouchesWhenObscured
696 * @attr ref android.R.styleable#View_fitsSystemWindows
697 * @attr ref android.R.styleable#View_isScrollContainer
698 * @attr ref android.R.styleable#View_focusable
699 * @attr ref android.R.styleable#View_focusableInTouchMode
700 * @attr ref android.R.styleable#View_hapticFeedbackEnabled
701 * @attr ref android.R.styleable#View_keepScreenOn
702 * @attr ref android.R.styleable#View_layerType
703 * @attr ref android.R.styleable#View_layoutDirection
704 * @attr ref android.R.styleable#View_longClickable
705 * @attr ref android.R.styleable#View_minHeight
706 * @attr ref android.R.styleable#View_minWidth
707 * @attr ref android.R.styleable#View_nextFocusDown
708 * @attr ref android.R.styleable#View_nextFocusLeft
709 * @attr ref android.R.styleable#View_nextFocusRight
710 * @attr ref android.R.styleable#View_nextFocusUp
711 * @attr ref android.R.styleable#View_onClick
712 * @attr ref android.R.styleable#View_padding
713 * @attr ref android.R.styleable#View_paddingBottom
714 * @attr ref android.R.styleable#View_paddingLeft
715 * @attr ref android.R.styleable#View_paddingRight
716 * @attr ref android.R.styleable#View_paddingTop
717 * @attr ref android.R.styleable#View_paddingStart
718 * @attr ref android.R.styleable#View_paddingEnd
719 * @attr ref android.R.styleable#View_saveEnabled
720 * @attr ref android.R.styleable#View_rotation
721 * @attr ref android.R.styleable#View_rotationX
722 * @attr ref android.R.styleable#View_rotationY
723 * @attr ref android.R.styleable#View_scaleX
724 * @attr ref android.R.styleable#View_scaleY
725 * @attr ref android.R.styleable#View_scrollX
726 * @attr ref android.R.styleable#View_scrollY
727 * @attr ref android.R.styleable#View_scrollbarSize
728 * @attr ref android.R.styleable#View_scrollbarStyle
729 * @attr ref android.R.styleable#View_scrollbars
730 * @attr ref android.R.styleable#View_scrollbarDefaultDelayBeforeFade
731 * @attr ref android.R.styleable#View_scrollbarFadeDuration
732 * @attr ref android.R.styleable#View_scrollbarTrackHorizontal
733 * @attr ref android.R.styleable#View_scrollbarThumbHorizontal
734 * @attr ref android.R.styleable#View_scrollbarThumbVertical
735 * @attr ref android.R.styleable#View_scrollbarTrackVertical
736 * @attr ref android.R.styleable#View_scrollbarAlwaysDrawHorizontalTrack
737 * @attr ref android.R.styleable#View_scrollbarAlwaysDrawVerticalTrack
738 * @attr ref android.R.styleable#View_stateListAnimator
739 * @attr ref android.R.styleable#View_transitionName
740 * @attr ref android.R.styleable#View_soundEffectsEnabled
741 * @attr ref android.R.styleable#View_tag
742 * @attr ref android.R.styleable#View_textAlignment
743 * @attr ref android.R.styleable#View_textDirection
744 * @attr ref android.R.styleable#View_transformPivotX
745 * @attr ref android.R.styleable#View_transformPivotY
746 * @attr ref android.R.styleable#View_translationX
747 * @attr ref android.R.styleable#View_translationY
748 * @attr ref android.R.styleable#View_translationZ
749 * @attr ref android.R.styleable#View_visibility
750 * @attr ref android.R.styleable#View_theme
751 *
752 * @see android.view.ViewGroup
753 */
754@UiThread
755public class View implements Drawable.Callback, KeyEvent.Callback,
756        AccessibilityEventSource {
757    private static final boolean DBG = false;
758
759    /**
760     * The logging tag used by this class with android.util.Log.
761     */
762    protected static final String VIEW_LOG_TAG = "View";
763
764    /**
765     * When set to true, apps will draw debugging information about their layouts.
766     *
767     * @hide
768     */
769    public static final String DEBUG_LAYOUT_PROPERTY = "debug.layout";
770
771    /**
772     * When set to true, this view will save its attribute data.
773     *
774     * @hide
775     */
776    public static boolean mDebugViewAttributes = false;
777
778    /**
779     * Used to mark a View that has no ID.
780     */
781    public static final int NO_ID = -1;
782
783    /**
784     * Signals that compatibility booleans have been initialized according to
785     * target SDK versions.
786     */
787    private static boolean sCompatibilityDone = false;
788
789    /**
790     * Use the old (broken) way of building MeasureSpecs.
791     */
792    private static boolean sUseBrokenMakeMeasureSpec = false;
793
794    /**
795     * Always return a size of 0 for MeasureSpec values with a mode of UNSPECIFIED
796     */
797    static boolean sUseZeroUnspecifiedMeasureSpec = false;
798
799    /**
800     * Ignore any optimizations using the measure cache.
801     */
802    private static boolean sIgnoreMeasureCache = false;
803
804    /**
805     * Ignore an optimization that skips unnecessary EXACTLY layout passes.
806     */
807    private static boolean sAlwaysRemeasureExactly = false;
808
809    /**
810     * Relax constraints around whether setLayoutParams() must be called after
811     * modifying the layout params.
812     */
813    private static boolean sLayoutParamsAlwaysChanged = false;
814
815    /**
816     * This view does not want keystrokes. Use with TAKES_FOCUS_MASK when
817     * calling setFlags.
818     */
819    private static final int NOT_FOCUSABLE = 0x00000000;
820
821    /**
822     * This view wants keystrokes. Use with TAKES_FOCUS_MASK when calling
823     * setFlags.
824     */
825    private static final int FOCUSABLE = 0x00000001;
826
827    /**
828     * Mask for use with setFlags indicating bits used for focus.
829     */
830    private static final int FOCUSABLE_MASK = 0x00000001;
831
832    /**
833     * This view will adjust its padding to fit sytem windows (e.g. status bar)
834     */
835    private static final int FITS_SYSTEM_WINDOWS = 0x00000002;
836
837    /** @hide */
838    @IntDef({VISIBLE, INVISIBLE, GONE})
839    @Retention(RetentionPolicy.SOURCE)
840    public @interface Visibility {}
841
842    /**
843     * This view is visible.
844     * Use with {@link #setVisibility} and <a href="#attr_android:visibility">{@code
845     * android:visibility}.
846     */
847    public static final int VISIBLE = 0x00000000;
848
849    /**
850     * This view is invisible, but it still takes up space for layout purposes.
851     * Use with {@link #setVisibility} and <a href="#attr_android:visibility">{@code
852     * android:visibility}.
853     */
854    public static final int INVISIBLE = 0x00000004;
855
856    /**
857     * This view is invisible, and it doesn't take any space for layout
858     * purposes. Use with {@link #setVisibility} and <a href="#attr_android:visibility">{@code
859     * android:visibility}.
860     */
861    public static final int GONE = 0x00000008;
862
863    /**
864     * Mask for use with setFlags indicating bits used for visibility.
865     * {@hide}
866     */
867    static final int VISIBILITY_MASK = 0x0000000C;
868
869    private static final int[] VISIBILITY_FLAGS = {VISIBLE, INVISIBLE, GONE};
870
871    /**
872     * This view is enabled. Interpretation varies by subclass.
873     * Use with ENABLED_MASK when calling setFlags.
874     * {@hide}
875     */
876    static final int ENABLED = 0x00000000;
877
878    /**
879     * This view is disabled. Interpretation varies by subclass.
880     * Use with ENABLED_MASK when calling setFlags.
881     * {@hide}
882     */
883    static final int DISABLED = 0x00000020;
884
885   /**
886    * Mask for use with setFlags indicating bits used for indicating whether
887    * this view is enabled
888    * {@hide}
889    */
890    static final int ENABLED_MASK = 0x00000020;
891
892    /**
893     * This view won't draw. {@link #onDraw(android.graphics.Canvas)} won't be
894     * called and further optimizations will be performed. It is okay to have
895     * this flag set and a background. Use with DRAW_MASK when calling setFlags.
896     * {@hide}
897     */
898    static final int WILL_NOT_DRAW = 0x00000080;
899
900    /**
901     * Mask for use with setFlags indicating bits used for indicating whether
902     * this view is will draw
903     * {@hide}
904     */
905    static final int DRAW_MASK = 0x00000080;
906
907    /**
908     * <p>This view doesn't show scrollbars.</p>
909     * {@hide}
910     */
911    static final int SCROLLBARS_NONE = 0x00000000;
912
913    /**
914     * <p>This view shows horizontal scrollbars.</p>
915     * {@hide}
916     */
917    static final int SCROLLBARS_HORIZONTAL = 0x00000100;
918
919    /**
920     * <p>This view shows vertical scrollbars.</p>
921     * {@hide}
922     */
923    static final int SCROLLBARS_VERTICAL = 0x00000200;
924
925    /**
926     * <p>Mask for use with setFlags indicating bits used for indicating which
927     * scrollbars are enabled.</p>
928     * {@hide}
929     */
930    static final int SCROLLBARS_MASK = 0x00000300;
931
932    /**
933     * Indicates that the view should filter touches when its window is obscured.
934     * Refer to the class comments for more information about this security feature.
935     * {@hide}
936     */
937    static final int FILTER_TOUCHES_WHEN_OBSCURED = 0x00000400;
938
939    /**
940     * Set for framework elements that use FITS_SYSTEM_WINDOWS, to indicate
941     * that they are optional and should be skipped if the window has
942     * requested system UI flags that ignore those insets for layout.
943     */
944    static final int OPTIONAL_FITS_SYSTEM_WINDOWS = 0x00000800;
945
946    /**
947     * <p>This view doesn't show fading edges.</p>
948     * {@hide}
949     */
950    static final int FADING_EDGE_NONE = 0x00000000;
951
952    /**
953     * <p>This view shows horizontal fading edges.</p>
954     * {@hide}
955     */
956    static final int FADING_EDGE_HORIZONTAL = 0x00001000;
957
958    /**
959     * <p>This view shows vertical fading edges.</p>
960     * {@hide}
961     */
962    static final int FADING_EDGE_VERTICAL = 0x00002000;
963
964    /**
965     * <p>Mask for use with setFlags indicating bits used for indicating which
966     * fading edges are enabled.</p>
967     * {@hide}
968     */
969    static final int FADING_EDGE_MASK = 0x00003000;
970
971    /**
972     * <p>Indicates this view can be clicked. When clickable, a View reacts
973     * to clicks by notifying the OnClickListener.<p>
974     * {@hide}
975     */
976    static final int CLICKABLE = 0x00004000;
977
978    /**
979     * <p>Indicates this view is caching its drawing into a bitmap.</p>
980     * {@hide}
981     */
982    static final int DRAWING_CACHE_ENABLED = 0x00008000;
983
984    /**
985     * <p>Indicates that no icicle should be saved for this view.<p>
986     * {@hide}
987     */
988    static final int SAVE_DISABLED = 0x000010000;
989
990    /**
991     * <p>Mask for use with setFlags indicating bits used for the saveEnabled
992     * property.</p>
993     * {@hide}
994     */
995    static final int SAVE_DISABLED_MASK = 0x000010000;
996
997    /**
998     * <p>Indicates that no drawing cache should ever be created for this view.<p>
999     * {@hide}
1000     */
1001    static final int WILL_NOT_CACHE_DRAWING = 0x000020000;
1002
1003    /**
1004     * <p>Indicates this view can take / keep focus when int touch mode.</p>
1005     * {@hide}
1006     */
1007    static final int FOCUSABLE_IN_TOUCH_MODE = 0x00040000;
1008
1009    /** @hide */
1010    @Retention(RetentionPolicy.SOURCE)
1011    @IntDef({DRAWING_CACHE_QUALITY_LOW, DRAWING_CACHE_QUALITY_HIGH, DRAWING_CACHE_QUALITY_AUTO})
1012    public @interface DrawingCacheQuality {}
1013
1014    /**
1015     * <p>Enables low quality mode for the drawing cache.</p>
1016     */
1017    public static final int DRAWING_CACHE_QUALITY_LOW = 0x00080000;
1018
1019    /**
1020     * <p>Enables high quality mode for the drawing cache.</p>
1021     */
1022    public static final int DRAWING_CACHE_QUALITY_HIGH = 0x00100000;
1023
1024    /**
1025     * <p>Enables automatic quality mode for the drawing cache.</p>
1026     */
1027    public static final int DRAWING_CACHE_QUALITY_AUTO = 0x00000000;
1028
1029    private static final int[] DRAWING_CACHE_QUALITY_FLAGS = {
1030            DRAWING_CACHE_QUALITY_AUTO, DRAWING_CACHE_QUALITY_LOW, DRAWING_CACHE_QUALITY_HIGH
1031    };
1032
1033    /**
1034     * <p>Mask for use with setFlags indicating bits used for the cache
1035     * quality property.</p>
1036     * {@hide}
1037     */
1038    static final int DRAWING_CACHE_QUALITY_MASK = 0x00180000;
1039
1040    /**
1041     * <p>
1042     * Indicates this view can be long clicked. When long clickable, a View
1043     * reacts to long clicks by notifying the OnLongClickListener or showing a
1044     * context menu.
1045     * </p>
1046     * {@hide}
1047     */
1048    static final int LONG_CLICKABLE = 0x00200000;
1049
1050    /**
1051     * <p>Indicates that this view gets its drawable states from its direct parent
1052     * and ignores its original internal states.</p>
1053     *
1054     * @hide
1055     */
1056    static final int DUPLICATE_PARENT_STATE = 0x00400000;
1057
1058    /**
1059     * <p>
1060     * Indicates this view can be context clicked. When context clickable, a View reacts to a
1061     * context click (e.g. a primary stylus button press or right mouse click) by notifying the
1062     * OnContextClickListener.
1063     * </p>
1064     * {@hide}
1065     */
1066    static final int CONTEXT_CLICKABLE = 0x00800000;
1067
1068
1069    /** @hide */
1070    @IntDef({
1071        SCROLLBARS_INSIDE_OVERLAY,
1072        SCROLLBARS_INSIDE_INSET,
1073        SCROLLBARS_OUTSIDE_OVERLAY,
1074        SCROLLBARS_OUTSIDE_INSET
1075    })
1076    @Retention(RetentionPolicy.SOURCE)
1077    public @interface ScrollBarStyle {}
1078
1079    /**
1080     * The scrollbar style to display the scrollbars inside the content area,
1081     * without increasing the padding. The scrollbars will be overlaid with
1082     * translucency on the view's content.
1083     */
1084    public static final int SCROLLBARS_INSIDE_OVERLAY = 0;
1085
1086    /**
1087     * The scrollbar style to display the scrollbars inside the padded area,
1088     * increasing the padding of the view. The scrollbars will not overlap the
1089     * content area of the view.
1090     */
1091    public static final int SCROLLBARS_INSIDE_INSET = 0x01000000;
1092
1093    /**
1094     * The scrollbar style to display the scrollbars at the edge of the view,
1095     * without increasing the padding. The scrollbars will be overlaid with
1096     * translucency.
1097     */
1098    public static final int SCROLLBARS_OUTSIDE_OVERLAY = 0x02000000;
1099
1100    /**
1101     * The scrollbar style to display the scrollbars at the edge of the view,
1102     * increasing the padding of the view. The scrollbars will only overlap the
1103     * background, if any.
1104     */
1105    public static final int SCROLLBARS_OUTSIDE_INSET = 0x03000000;
1106
1107    /**
1108     * Mask to check if the scrollbar style is overlay or inset.
1109     * {@hide}
1110     */
1111    static final int SCROLLBARS_INSET_MASK = 0x01000000;
1112
1113    /**
1114     * Mask to check if the scrollbar style is inside or outside.
1115     * {@hide}
1116     */
1117    static final int SCROLLBARS_OUTSIDE_MASK = 0x02000000;
1118
1119    /**
1120     * Mask for scrollbar style.
1121     * {@hide}
1122     */
1123    static final int SCROLLBARS_STYLE_MASK = 0x03000000;
1124
1125    /**
1126     * View flag indicating that the screen should remain on while the
1127     * window containing this view is visible to the user.  This effectively
1128     * takes care of automatically setting the WindowManager's
1129     * {@link WindowManager.LayoutParams#FLAG_KEEP_SCREEN_ON}.
1130     */
1131    public static final int KEEP_SCREEN_ON = 0x04000000;
1132
1133    /**
1134     * View flag indicating whether this view should have sound effects enabled
1135     * for events such as clicking and touching.
1136     */
1137    public static final int SOUND_EFFECTS_ENABLED = 0x08000000;
1138
1139    /**
1140     * View flag indicating whether this view should have haptic feedback
1141     * enabled for events such as long presses.
1142     */
1143    public static final int HAPTIC_FEEDBACK_ENABLED = 0x10000000;
1144
1145    /**
1146     * <p>Indicates that the view hierarchy should stop saving state when
1147     * it reaches this view.  If state saving is initiated immediately at
1148     * the view, it will be allowed.
1149     * {@hide}
1150     */
1151    static final int PARENT_SAVE_DISABLED = 0x20000000;
1152
1153    /**
1154     * <p>Mask for use with setFlags indicating bits used for PARENT_SAVE_DISABLED.</p>
1155     * {@hide}
1156     */
1157    static final int PARENT_SAVE_DISABLED_MASK = 0x20000000;
1158
1159    /** @hide */
1160    @IntDef(flag = true,
1161            value = {
1162                FOCUSABLES_ALL,
1163                FOCUSABLES_TOUCH_MODE
1164            })
1165    @Retention(RetentionPolicy.SOURCE)
1166    public @interface FocusableMode {}
1167
1168    /**
1169     * View flag indicating whether {@link #addFocusables(ArrayList, int, int)}
1170     * should add all focusable Views regardless if they are focusable in touch mode.
1171     */
1172    public static final int FOCUSABLES_ALL = 0x00000000;
1173
1174    /**
1175     * View flag indicating whether {@link #addFocusables(ArrayList, int, int)}
1176     * should add only Views focusable in touch mode.
1177     */
1178    public static final int FOCUSABLES_TOUCH_MODE = 0x00000001;
1179
1180    /** @hide */
1181    @IntDef({
1182            FOCUS_BACKWARD,
1183            FOCUS_FORWARD,
1184            FOCUS_LEFT,
1185            FOCUS_UP,
1186            FOCUS_RIGHT,
1187            FOCUS_DOWN
1188    })
1189    @Retention(RetentionPolicy.SOURCE)
1190    public @interface FocusDirection {}
1191
1192    /** @hide */
1193    @IntDef({
1194            FOCUS_LEFT,
1195            FOCUS_UP,
1196            FOCUS_RIGHT,
1197            FOCUS_DOWN
1198    })
1199    @Retention(RetentionPolicy.SOURCE)
1200    public @interface FocusRealDirection {} // Like @FocusDirection, but without forward/backward
1201
1202    /**
1203     * Use with {@link #focusSearch(int)}. Move focus to the previous selectable
1204     * item.
1205     */
1206    public static final int FOCUS_BACKWARD = 0x00000001;
1207
1208    /**
1209     * Use with {@link #focusSearch(int)}. Move focus to the next selectable
1210     * item.
1211     */
1212    public static final int FOCUS_FORWARD = 0x00000002;
1213
1214    /**
1215     * Use with {@link #focusSearch(int)}. Move focus to the left.
1216     */
1217    public static final int FOCUS_LEFT = 0x00000011;
1218
1219    /**
1220     * Use with {@link #focusSearch(int)}. Move focus up.
1221     */
1222    public static final int FOCUS_UP = 0x00000021;
1223
1224    /**
1225     * Use with {@link #focusSearch(int)}. Move focus to the right.
1226     */
1227    public static final int FOCUS_RIGHT = 0x00000042;
1228
1229    /**
1230     * Use with {@link #focusSearch(int)}. Move focus down.
1231     */
1232    public static final int FOCUS_DOWN = 0x00000082;
1233
1234    /**
1235     * Bits of {@link #getMeasuredWidthAndState()} and
1236     * {@link #getMeasuredWidthAndState()} that provide the actual measured size.
1237     */
1238    public static final int MEASURED_SIZE_MASK = 0x00ffffff;
1239
1240    /**
1241     * Bits of {@link #getMeasuredWidthAndState()} and
1242     * {@link #getMeasuredWidthAndState()} that provide the additional state bits.
1243     */
1244    public static final int MEASURED_STATE_MASK = 0xff000000;
1245
1246    /**
1247     * Bit shift of {@link #MEASURED_STATE_MASK} to get to the height bits
1248     * for functions that combine both width and height into a single int,
1249     * such as {@link #getMeasuredState()} and the childState argument of
1250     * {@link #resolveSizeAndState(int, int, int)}.
1251     */
1252    public static final int MEASURED_HEIGHT_STATE_SHIFT = 16;
1253
1254    /**
1255     * Bit of {@link #getMeasuredWidthAndState()} and
1256     * {@link #getMeasuredWidthAndState()} that indicates the measured size
1257     * is smaller that the space the view would like to have.
1258     */
1259    public static final int MEASURED_STATE_TOO_SMALL = 0x01000000;
1260
1261    /**
1262     * Base View state sets
1263     */
1264    // Singles
1265    /**
1266     * Indicates the view has no states set. States are used with
1267     * {@link android.graphics.drawable.Drawable} to change the drawing of the
1268     * view depending on its state.
1269     *
1270     * @see android.graphics.drawable.Drawable
1271     * @see #getDrawableState()
1272     */
1273    protected static final int[] EMPTY_STATE_SET;
1274    /**
1275     * Indicates the view is enabled. States are used with
1276     * {@link android.graphics.drawable.Drawable} to change the drawing of the
1277     * view depending on its state.
1278     *
1279     * @see android.graphics.drawable.Drawable
1280     * @see #getDrawableState()
1281     */
1282    protected static final int[] ENABLED_STATE_SET;
1283    /**
1284     * Indicates the view is focused. States are used with
1285     * {@link android.graphics.drawable.Drawable} to change the drawing of the
1286     * view depending on its state.
1287     *
1288     * @see android.graphics.drawable.Drawable
1289     * @see #getDrawableState()
1290     */
1291    protected static final int[] FOCUSED_STATE_SET;
1292    /**
1293     * Indicates the view is selected. States are used with
1294     * {@link android.graphics.drawable.Drawable} to change the drawing of the
1295     * view depending on its state.
1296     *
1297     * @see android.graphics.drawable.Drawable
1298     * @see #getDrawableState()
1299     */
1300    protected static final int[] SELECTED_STATE_SET;
1301    /**
1302     * Indicates the view is pressed. States are used with
1303     * {@link android.graphics.drawable.Drawable} to change the drawing of the
1304     * view depending on its state.
1305     *
1306     * @see android.graphics.drawable.Drawable
1307     * @see #getDrawableState()
1308     */
1309    protected static final int[] PRESSED_STATE_SET;
1310    /**
1311     * Indicates the view's window has focus. States are used with
1312     * {@link android.graphics.drawable.Drawable} to change the drawing of the
1313     * view depending on its state.
1314     *
1315     * @see android.graphics.drawable.Drawable
1316     * @see #getDrawableState()
1317     */
1318    protected static final int[] WINDOW_FOCUSED_STATE_SET;
1319    // Doubles
1320    /**
1321     * Indicates the view is enabled and has the focus.
1322     *
1323     * @see #ENABLED_STATE_SET
1324     * @see #FOCUSED_STATE_SET
1325     */
1326    protected static final int[] ENABLED_FOCUSED_STATE_SET;
1327    /**
1328     * Indicates the view is enabled and selected.
1329     *
1330     * @see #ENABLED_STATE_SET
1331     * @see #SELECTED_STATE_SET
1332     */
1333    protected static final int[] ENABLED_SELECTED_STATE_SET;
1334    /**
1335     * Indicates the view is enabled and that its window has focus.
1336     *
1337     * @see #ENABLED_STATE_SET
1338     * @see #WINDOW_FOCUSED_STATE_SET
1339     */
1340    protected static final int[] ENABLED_WINDOW_FOCUSED_STATE_SET;
1341    /**
1342     * Indicates the view is focused and selected.
1343     *
1344     * @see #FOCUSED_STATE_SET
1345     * @see #SELECTED_STATE_SET
1346     */
1347    protected static final int[] FOCUSED_SELECTED_STATE_SET;
1348    /**
1349     * Indicates the view has the focus and that its window has the focus.
1350     *
1351     * @see #FOCUSED_STATE_SET
1352     * @see #WINDOW_FOCUSED_STATE_SET
1353     */
1354    protected static final int[] FOCUSED_WINDOW_FOCUSED_STATE_SET;
1355    /**
1356     * Indicates the view is selected and that its window has the focus.
1357     *
1358     * @see #SELECTED_STATE_SET
1359     * @see #WINDOW_FOCUSED_STATE_SET
1360     */
1361    protected static final int[] SELECTED_WINDOW_FOCUSED_STATE_SET;
1362    // Triples
1363    /**
1364     * Indicates the view is enabled, focused and selected.
1365     *
1366     * @see #ENABLED_STATE_SET
1367     * @see #FOCUSED_STATE_SET
1368     * @see #SELECTED_STATE_SET
1369     */
1370    protected static final int[] ENABLED_FOCUSED_SELECTED_STATE_SET;
1371    /**
1372     * Indicates the view is enabled, focused and its window has the focus.
1373     *
1374     * @see #ENABLED_STATE_SET
1375     * @see #FOCUSED_STATE_SET
1376     * @see #WINDOW_FOCUSED_STATE_SET
1377     */
1378    protected static final int[] ENABLED_FOCUSED_WINDOW_FOCUSED_STATE_SET;
1379    /**
1380     * Indicates the view is enabled, selected and its window has the focus.
1381     *
1382     * @see #ENABLED_STATE_SET
1383     * @see #SELECTED_STATE_SET
1384     * @see #WINDOW_FOCUSED_STATE_SET
1385     */
1386    protected static final int[] ENABLED_SELECTED_WINDOW_FOCUSED_STATE_SET;
1387    /**
1388     * Indicates the view is focused, selected and its window has the focus.
1389     *
1390     * @see #FOCUSED_STATE_SET
1391     * @see #SELECTED_STATE_SET
1392     * @see #WINDOW_FOCUSED_STATE_SET
1393     */
1394    protected static final int[] FOCUSED_SELECTED_WINDOW_FOCUSED_STATE_SET;
1395    /**
1396     * Indicates the view is enabled, focused, selected and its window
1397     * has the focus.
1398     *
1399     * @see #ENABLED_STATE_SET
1400     * @see #FOCUSED_STATE_SET
1401     * @see #SELECTED_STATE_SET
1402     * @see #WINDOW_FOCUSED_STATE_SET
1403     */
1404    protected static final int[] ENABLED_FOCUSED_SELECTED_WINDOW_FOCUSED_STATE_SET;
1405    /**
1406     * Indicates the view is pressed and its window has the focus.
1407     *
1408     * @see #PRESSED_STATE_SET
1409     * @see #WINDOW_FOCUSED_STATE_SET
1410     */
1411    protected static final int[] PRESSED_WINDOW_FOCUSED_STATE_SET;
1412    /**
1413     * Indicates the view is pressed and selected.
1414     *
1415     * @see #PRESSED_STATE_SET
1416     * @see #SELECTED_STATE_SET
1417     */
1418    protected static final int[] PRESSED_SELECTED_STATE_SET;
1419    /**
1420     * Indicates the view is pressed, selected and its window has the focus.
1421     *
1422     * @see #PRESSED_STATE_SET
1423     * @see #SELECTED_STATE_SET
1424     * @see #WINDOW_FOCUSED_STATE_SET
1425     */
1426    protected static final int[] PRESSED_SELECTED_WINDOW_FOCUSED_STATE_SET;
1427    /**
1428     * Indicates the view is pressed and focused.
1429     *
1430     * @see #PRESSED_STATE_SET
1431     * @see #FOCUSED_STATE_SET
1432     */
1433    protected static final int[] PRESSED_FOCUSED_STATE_SET;
1434    /**
1435     * Indicates the view is pressed, focused and its window has the focus.
1436     *
1437     * @see #PRESSED_STATE_SET
1438     * @see #FOCUSED_STATE_SET
1439     * @see #WINDOW_FOCUSED_STATE_SET
1440     */
1441    protected static final int[] PRESSED_FOCUSED_WINDOW_FOCUSED_STATE_SET;
1442    /**
1443     * Indicates the view is pressed, focused and selected.
1444     *
1445     * @see #PRESSED_STATE_SET
1446     * @see #SELECTED_STATE_SET
1447     * @see #FOCUSED_STATE_SET
1448     */
1449    protected static final int[] PRESSED_FOCUSED_SELECTED_STATE_SET;
1450    /**
1451     * Indicates the view is pressed, focused, selected and its window has the focus.
1452     *
1453     * @see #PRESSED_STATE_SET
1454     * @see #FOCUSED_STATE_SET
1455     * @see #SELECTED_STATE_SET
1456     * @see #WINDOW_FOCUSED_STATE_SET
1457     */
1458    protected static final int[] PRESSED_FOCUSED_SELECTED_WINDOW_FOCUSED_STATE_SET;
1459    /**
1460     * Indicates the view is pressed and enabled.
1461     *
1462     * @see #PRESSED_STATE_SET
1463     * @see #ENABLED_STATE_SET
1464     */
1465    protected static final int[] PRESSED_ENABLED_STATE_SET;
1466    /**
1467     * Indicates the view is pressed, enabled and its window has the focus.
1468     *
1469     * @see #PRESSED_STATE_SET
1470     * @see #ENABLED_STATE_SET
1471     * @see #WINDOW_FOCUSED_STATE_SET
1472     */
1473    protected static final int[] PRESSED_ENABLED_WINDOW_FOCUSED_STATE_SET;
1474    /**
1475     * Indicates the view is pressed, enabled and selected.
1476     *
1477     * @see #PRESSED_STATE_SET
1478     * @see #ENABLED_STATE_SET
1479     * @see #SELECTED_STATE_SET
1480     */
1481    protected static final int[] PRESSED_ENABLED_SELECTED_STATE_SET;
1482    /**
1483     * Indicates the view is pressed, enabled, selected and its window has the
1484     * focus.
1485     *
1486     * @see #PRESSED_STATE_SET
1487     * @see #ENABLED_STATE_SET
1488     * @see #SELECTED_STATE_SET
1489     * @see #WINDOW_FOCUSED_STATE_SET
1490     */
1491    protected static final int[] PRESSED_ENABLED_SELECTED_WINDOW_FOCUSED_STATE_SET;
1492    /**
1493     * Indicates the view is pressed, enabled and focused.
1494     *
1495     * @see #PRESSED_STATE_SET
1496     * @see #ENABLED_STATE_SET
1497     * @see #FOCUSED_STATE_SET
1498     */
1499    protected static final int[] PRESSED_ENABLED_FOCUSED_STATE_SET;
1500    /**
1501     * Indicates the view is pressed, enabled, focused and its window has the
1502     * focus.
1503     *
1504     * @see #PRESSED_STATE_SET
1505     * @see #ENABLED_STATE_SET
1506     * @see #FOCUSED_STATE_SET
1507     * @see #WINDOW_FOCUSED_STATE_SET
1508     */
1509    protected static final int[] PRESSED_ENABLED_FOCUSED_WINDOW_FOCUSED_STATE_SET;
1510    /**
1511     * Indicates the view is pressed, enabled, focused and selected.
1512     *
1513     * @see #PRESSED_STATE_SET
1514     * @see #ENABLED_STATE_SET
1515     * @see #SELECTED_STATE_SET
1516     * @see #FOCUSED_STATE_SET
1517     */
1518    protected static final int[] PRESSED_ENABLED_FOCUSED_SELECTED_STATE_SET;
1519    /**
1520     * Indicates the view is pressed, enabled, focused, selected and its window
1521     * has the focus.
1522     *
1523     * @see #PRESSED_STATE_SET
1524     * @see #ENABLED_STATE_SET
1525     * @see #SELECTED_STATE_SET
1526     * @see #FOCUSED_STATE_SET
1527     * @see #WINDOW_FOCUSED_STATE_SET
1528     */
1529    protected static final int[] PRESSED_ENABLED_FOCUSED_SELECTED_WINDOW_FOCUSED_STATE_SET;
1530
1531    static {
1532        EMPTY_STATE_SET = StateSet.get(0);
1533
1534        WINDOW_FOCUSED_STATE_SET = StateSet.get(StateSet.VIEW_STATE_WINDOW_FOCUSED);
1535
1536        SELECTED_STATE_SET = StateSet.get(StateSet.VIEW_STATE_SELECTED);
1537        SELECTED_WINDOW_FOCUSED_STATE_SET = StateSet.get(
1538                StateSet.VIEW_STATE_WINDOW_FOCUSED | StateSet.VIEW_STATE_SELECTED);
1539
1540        FOCUSED_STATE_SET = StateSet.get(StateSet.VIEW_STATE_FOCUSED);
1541        FOCUSED_WINDOW_FOCUSED_STATE_SET = StateSet.get(
1542                StateSet.VIEW_STATE_WINDOW_FOCUSED | StateSet.VIEW_STATE_FOCUSED);
1543        FOCUSED_SELECTED_STATE_SET = StateSet.get(
1544                StateSet.VIEW_STATE_SELECTED | StateSet.VIEW_STATE_FOCUSED);
1545        FOCUSED_SELECTED_WINDOW_FOCUSED_STATE_SET = StateSet.get(
1546                StateSet.VIEW_STATE_WINDOW_FOCUSED | StateSet.VIEW_STATE_SELECTED
1547                        | StateSet.VIEW_STATE_FOCUSED);
1548
1549        ENABLED_STATE_SET = StateSet.get(StateSet.VIEW_STATE_ENABLED);
1550        ENABLED_WINDOW_FOCUSED_STATE_SET = StateSet.get(
1551                StateSet.VIEW_STATE_WINDOW_FOCUSED | StateSet.VIEW_STATE_ENABLED);
1552        ENABLED_SELECTED_STATE_SET = StateSet.get(
1553                StateSet.VIEW_STATE_SELECTED | StateSet.VIEW_STATE_ENABLED);
1554        ENABLED_SELECTED_WINDOW_FOCUSED_STATE_SET = StateSet.get(
1555                StateSet.VIEW_STATE_WINDOW_FOCUSED | StateSet.VIEW_STATE_SELECTED
1556                        | StateSet.VIEW_STATE_ENABLED);
1557        ENABLED_FOCUSED_STATE_SET = StateSet.get(
1558                StateSet.VIEW_STATE_FOCUSED | StateSet.VIEW_STATE_ENABLED);
1559        ENABLED_FOCUSED_WINDOW_FOCUSED_STATE_SET = StateSet.get(
1560                StateSet.VIEW_STATE_WINDOW_FOCUSED | StateSet.VIEW_STATE_FOCUSED
1561                        | StateSet.VIEW_STATE_ENABLED);
1562        ENABLED_FOCUSED_SELECTED_STATE_SET = StateSet.get(
1563                StateSet.VIEW_STATE_SELECTED | StateSet.VIEW_STATE_FOCUSED
1564                        | StateSet.VIEW_STATE_ENABLED);
1565        ENABLED_FOCUSED_SELECTED_WINDOW_FOCUSED_STATE_SET = StateSet.get(
1566                StateSet.VIEW_STATE_WINDOW_FOCUSED | StateSet.VIEW_STATE_SELECTED
1567                        | StateSet.VIEW_STATE_FOCUSED| StateSet.VIEW_STATE_ENABLED);
1568
1569        PRESSED_STATE_SET = StateSet.get(StateSet.VIEW_STATE_PRESSED);
1570        PRESSED_WINDOW_FOCUSED_STATE_SET = StateSet.get(
1571                StateSet.VIEW_STATE_WINDOW_FOCUSED | StateSet.VIEW_STATE_PRESSED);
1572        PRESSED_SELECTED_STATE_SET = StateSet.get(
1573                StateSet.VIEW_STATE_SELECTED | StateSet.VIEW_STATE_PRESSED);
1574        PRESSED_SELECTED_WINDOW_FOCUSED_STATE_SET = StateSet.get(
1575                StateSet.VIEW_STATE_WINDOW_FOCUSED | StateSet.VIEW_STATE_SELECTED
1576                        | StateSet.VIEW_STATE_PRESSED);
1577        PRESSED_FOCUSED_STATE_SET = StateSet.get(
1578                StateSet.VIEW_STATE_FOCUSED | StateSet.VIEW_STATE_PRESSED);
1579        PRESSED_FOCUSED_WINDOW_FOCUSED_STATE_SET = StateSet.get(
1580                StateSet.VIEW_STATE_WINDOW_FOCUSED | StateSet.VIEW_STATE_FOCUSED
1581                        | StateSet.VIEW_STATE_PRESSED);
1582        PRESSED_FOCUSED_SELECTED_STATE_SET = StateSet.get(
1583                StateSet.VIEW_STATE_SELECTED | StateSet.VIEW_STATE_FOCUSED
1584                        | StateSet.VIEW_STATE_PRESSED);
1585        PRESSED_FOCUSED_SELECTED_WINDOW_FOCUSED_STATE_SET = StateSet.get(
1586                StateSet.VIEW_STATE_WINDOW_FOCUSED | StateSet.VIEW_STATE_SELECTED
1587                        | StateSet.VIEW_STATE_FOCUSED | StateSet.VIEW_STATE_PRESSED);
1588        PRESSED_ENABLED_STATE_SET = StateSet.get(
1589                StateSet.VIEW_STATE_ENABLED | StateSet.VIEW_STATE_PRESSED);
1590        PRESSED_ENABLED_WINDOW_FOCUSED_STATE_SET = StateSet.get(
1591                StateSet.VIEW_STATE_WINDOW_FOCUSED | StateSet.VIEW_STATE_ENABLED
1592                        | StateSet.VIEW_STATE_PRESSED);
1593        PRESSED_ENABLED_SELECTED_STATE_SET = StateSet.get(
1594                StateSet.VIEW_STATE_SELECTED | StateSet.VIEW_STATE_ENABLED
1595                        | StateSet.VIEW_STATE_PRESSED);
1596        PRESSED_ENABLED_SELECTED_WINDOW_FOCUSED_STATE_SET = StateSet.get(
1597                StateSet.VIEW_STATE_WINDOW_FOCUSED | StateSet.VIEW_STATE_SELECTED
1598                        | StateSet.VIEW_STATE_ENABLED | StateSet.VIEW_STATE_PRESSED);
1599        PRESSED_ENABLED_FOCUSED_STATE_SET = StateSet.get(
1600                StateSet.VIEW_STATE_FOCUSED | StateSet.VIEW_STATE_ENABLED
1601                        | StateSet.VIEW_STATE_PRESSED);
1602        PRESSED_ENABLED_FOCUSED_WINDOW_FOCUSED_STATE_SET = StateSet.get(
1603                StateSet.VIEW_STATE_WINDOW_FOCUSED | StateSet.VIEW_STATE_FOCUSED
1604                        | StateSet.VIEW_STATE_ENABLED | StateSet.VIEW_STATE_PRESSED);
1605        PRESSED_ENABLED_FOCUSED_SELECTED_STATE_SET = StateSet.get(
1606                StateSet.VIEW_STATE_SELECTED | StateSet.VIEW_STATE_FOCUSED
1607                        | StateSet.VIEW_STATE_ENABLED | StateSet.VIEW_STATE_PRESSED);
1608        PRESSED_ENABLED_FOCUSED_SELECTED_WINDOW_FOCUSED_STATE_SET = StateSet.get(
1609                StateSet.VIEW_STATE_WINDOW_FOCUSED | StateSet.VIEW_STATE_SELECTED
1610                        | StateSet.VIEW_STATE_FOCUSED| StateSet.VIEW_STATE_ENABLED
1611                        | StateSet.VIEW_STATE_PRESSED);
1612    }
1613
1614    /**
1615     * Accessibility event types that are dispatched for text population.
1616     */
1617    private static final int POPULATING_ACCESSIBILITY_EVENT_TYPES =
1618            AccessibilityEvent.TYPE_VIEW_CLICKED
1619            | AccessibilityEvent.TYPE_VIEW_LONG_CLICKED
1620            | AccessibilityEvent.TYPE_VIEW_SELECTED
1621            | AccessibilityEvent.TYPE_VIEW_FOCUSED
1622            | AccessibilityEvent.TYPE_WINDOW_STATE_CHANGED
1623            | AccessibilityEvent.TYPE_VIEW_HOVER_ENTER
1624            | AccessibilityEvent.TYPE_VIEW_HOVER_EXIT
1625            | AccessibilityEvent.TYPE_VIEW_TEXT_CHANGED
1626            | AccessibilityEvent.TYPE_VIEW_TEXT_SELECTION_CHANGED
1627            | AccessibilityEvent.TYPE_VIEW_ACCESSIBILITY_FOCUSED
1628            | AccessibilityEvent.TYPE_VIEW_TEXT_TRAVERSED_AT_MOVEMENT_GRANULARITY;
1629
1630    /**
1631     * Temporary Rect currently for use in setBackground().  This will probably
1632     * be extended in the future to hold our own class with more than just
1633     * a Rect. :)
1634     */
1635    static final ThreadLocal<Rect> sThreadLocal = new ThreadLocal<Rect>();
1636
1637    /**
1638     * Map used to store views' tags.
1639     */
1640    private SparseArray<Object> mKeyedTags;
1641
1642    /**
1643     * The next available accessibility id.
1644     */
1645    private static int sNextAccessibilityViewId;
1646
1647    /**
1648     * The animation currently associated with this view.
1649     * @hide
1650     */
1651    protected Animation mCurrentAnimation = null;
1652
1653    /**
1654     * Width as measured during measure pass.
1655     * {@hide}
1656     */
1657    @ViewDebug.ExportedProperty(category = "measurement")
1658    int mMeasuredWidth;
1659
1660    /**
1661     * Height as measured during measure pass.
1662     * {@hide}
1663     */
1664    @ViewDebug.ExportedProperty(category = "measurement")
1665    int mMeasuredHeight;
1666
1667    /**
1668     * Flag to indicate that this view was marked INVALIDATED, or had its display list
1669     * invalidated, prior to the current drawing iteration. If true, the view must re-draw
1670     * its display list. This flag, used only when hw accelerated, allows us to clear the
1671     * flag while retaining this information until it's needed (at getDisplayList() time and
1672     * in drawChild(), when we decide to draw a view's children's display lists into our own).
1673     *
1674     * {@hide}
1675     */
1676    boolean mRecreateDisplayList = false;
1677
1678    /**
1679     * The view's identifier.
1680     * {@hide}
1681     *
1682     * @see #setId(int)
1683     * @see #getId()
1684     */
1685    @IdRes
1686    @ViewDebug.ExportedProperty(resolveId = true)
1687    int mID = NO_ID;
1688
1689    /**
1690     * The stable ID of this view for accessibility purposes.
1691     */
1692    int mAccessibilityViewId = NO_ID;
1693
1694    private int mAccessibilityCursorPosition = ACCESSIBILITY_CURSOR_POSITION_UNDEFINED;
1695
1696    SendViewStateChangedAccessibilityEvent mSendViewStateChangedAccessibilityEvent;
1697
1698    /**
1699     * The view's tag.
1700     * {@hide}
1701     *
1702     * @see #setTag(Object)
1703     * @see #getTag()
1704     */
1705    protected Object mTag = null;
1706
1707    // for mPrivateFlags:
1708    /** {@hide} */
1709    static final int PFLAG_WANTS_FOCUS                 = 0x00000001;
1710    /** {@hide} */
1711    static final int PFLAG_FOCUSED                     = 0x00000002;
1712    /** {@hide} */
1713    static final int PFLAG_SELECTED                    = 0x00000004;
1714    /** {@hide} */
1715    static final int PFLAG_IS_ROOT_NAMESPACE           = 0x00000008;
1716    /** {@hide} */
1717    static final int PFLAG_HAS_BOUNDS                  = 0x00000010;
1718    /** {@hide} */
1719    static final int PFLAG_DRAWN                       = 0x00000020;
1720    /**
1721     * When this flag is set, this view is running an animation on behalf of its
1722     * children and should therefore not cancel invalidate requests, even if they
1723     * lie outside of this view's bounds.
1724     *
1725     * {@hide}
1726     */
1727    static final int PFLAG_DRAW_ANIMATION              = 0x00000040;
1728    /** {@hide} */
1729    static final int PFLAG_SKIP_DRAW                   = 0x00000080;
1730    /** {@hide} */
1731    static final int PFLAG_REQUEST_TRANSPARENT_REGIONS = 0x00000200;
1732    /** {@hide} */
1733    static final int PFLAG_DRAWABLE_STATE_DIRTY        = 0x00000400;
1734    /** {@hide} */
1735    static final int PFLAG_MEASURED_DIMENSION_SET      = 0x00000800;
1736    /** {@hide} */
1737    static final int PFLAG_FORCE_LAYOUT                = 0x00001000;
1738    /** {@hide} */
1739    static final int PFLAG_LAYOUT_REQUIRED             = 0x00002000;
1740
1741    private static final int PFLAG_PRESSED             = 0x00004000;
1742
1743    /** {@hide} */
1744    static final int PFLAG_DRAWING_CACHE_VALID         = 0x00008000;
1745    /**
1746     * Flag used to indicate that this view should be drawn once more (and only once
1747     * more) after its animation has completed.
1748     * {@hide}
1749     */
1750    static final int PFLAG_ANIMATION_STARTED           = 0x00010000;
1751
1752    private static final int PFLAG_SAVE_STATE_CALLED   = 0x00020000;
1753
1754    /**
1755     * Indicates that the View returned true when onSetAlpha() was called and that
1756     * the alpha must be restored.
1757     * {@hide}
1758     */
1759    static final int PFLAG_ALPHA_SET                   = 0x00040000;
1760
1761    /**
1762     * Set by {@link #setScrollContainer(boolean)}.
1763     */
1764    static final int PFLAG_SCROLL_CONTAINER            = 0x00080000;
1765
1766    /**
1767     * Set by {@link #setScrollContainer(boolean)}.
1768     */
1769    static final int PFLAG_SCROLL_CONTAINER_ADDED      = 0x00100000;
1770
1771    /**
1772     * View flag indicating whether this view was invalidated (fully or partially.)
1773     *
1774     * @hide
1775     */
1776    static final int PFLAG_DIRTY                       = 0x00200000;
1777
1778    /**
1779     * View flag indicating whether this view was invalidated by an opaque
1780     * invalidate request.
1781     *
1782     * @hide
1783     */
1784    static final int PFLAG_DIRTY_OPAQUE                = 0x00400000;
1785
1786    /**
1787     * Mask for {@link #PFLAG_DIRTY} and {@link #PFLAG_DIRTY_OPAQUE}.
1788     *
1789     * @hide
1790     */
1791    static final int PFLAG_DIRTY_MASK                  = 0x00600000;
1792
1793    /**
1794     * Indicates whether the background is opaque.
1795     *
1796     * @hide
1797     */
1798    static final int PFLAG_OPAQUE_BACKGROUND           = 0x00800000;
1799
1800    /**
1801     * Indicates whether the scrollbars are opaque.
1802     *
1803     * @hide
1804     */
1805    static final int PFLAG_OPAQUE_SCROLLBARS           = 0x01000000;
1806
1807    /**
1808     * Indicates whether the view is opaque.
1809     *
1810     * @hide
1811     */
1812    static final int PFLAG_OPAQUE_MASK                 = 0x01800000;
1813
1814    /**
1815     * Indicates a prepressed state;
1816     * the short time between ACTION_DOWN and recognizing
1817     * a 'real' press. Prepressed is used to recognize quick taps
1818     * even when they are shorter than ViewConfiguration.getTapTimeout().
1819     *
1820     * @hide
1821     */
1822    private static final int PFLAG_PREPRESSED          = 0x02000000;
1823
1824    /**
1825     * Indicates whether the view is temporarily detached.
1826     *
1827     * @hide
1828     */
1829    static final int PFLAG_CANCEL_NEXT_UP_EVENT        = 0x04000000;
1830
1831    /**
1832     * Indicates that we should awaken scroll bars once attached
1833     *
1834     * PLEASE NOTE: This flag is now unused as we now send onVisibilityChanged
1835     * during window attachment and it is no longer needed. Feel free to repurpose it.
1836     *
1837     * @hide
1838     */
1839    private static final int PFLAG_AWAKEN_SCROLL_BARS_ON_ATTACH = 0x08000000;
1840
1841    /**
1842     * Indicates that the view has received HOVER_ENTER.  Cleared on HOVER_EXIT.
1843     * @hide
1844     */
1845    private static final int PFLAG_HOVERED             = 0x10000000;
1846
1847    /**
1848     * no longer needed, should be reused
1849     */
1850    private static final int PFLAG_DOES_NOTHING_REUSE_PLEASE = 0x20000000;
1851
1852    /** {@hide} */
1853    static final int PFLAG_ACTIVATED                   = 0x40000000;
1854
1855    /**
1856     * Indicates that this view was specifically invalidated, not just dirtied because some
1857     * child view was invalidated. The flag is used to determine when we need to recreate
1858     * a view's display list (as opposed to just returning a reference to its existing
1859     * display list).
1860     *
1861     * @hide
1862     */
1863    static final int PFLAG_INVALIDATED                 = 0x80000000;
1864
1865    /**
1866     * Masks for mPrivateFlags2, as generated by dumpFlags():
1867     *
1868     * |-------|-------|-------|-------|
1869     *                                 1 PFLAG2_DRAG_CAN_ACCEPT
1870     *                                1  PFLAG2_DRAG_HOVERED
1871     *                              11   PFLAG2_LAYOUT_DIRECTION_MASK
1872     *                             1     PFLAG2_LAYOUT_DIRECTION_RESOLVED_RTL
1873     *                            1      PFLAG2_LAYOUT_DIRECTION_RESOLVED
1874     *                            11     PFLAG2_LAYOUT_DIRECTION_RESOLVED_MASK
1875     *                           1       PFLAG2_TEXT_DIRECTION_FLAGS[1]
1876     *                          1        PFLAG2_TEXT_DIRECTION_FLAGS[2]
1877     *                          11       PFLAG2_TEXT_DIRECTION_FLAGS[3]
1878     *                         1         PFLAG2_TEXT_DIRECTION_FLAGS[4]
1879     *                         1 1       PFLAG2_TEXT_DIRECTION_FLAGS[5]
1880     *                         11        PFLAG2_TEXT_DIRECTION_FLAGS[6]
1881     *                         111       PFLAG2_TEXT_DIRECTION_FLAGS[7]
1882     *                         111       PFLAG2_TEXT_DIRECTION_MASK
1883     *                        1          PFLAG2_TEXT_DIRECTION_RESOLVED
1884     *                       1           PFLAG2_TEXT_DIRECTION_RESOLVED_DEFAULT
1885     *                     111           PFLAG2_TEXT_DIRECTION_RESOLVED_MASK
1886     *                    1              PFLAG2_TEXT_ALIGNMENT_FLAGS[1]
1887     *                   1               PFLAG2_TEXT_ALIGNMENT_FLAGS[2]
1888     *                   11              PFLAG2_TEXT_ALIGNMENT_FLAGS[3]
1889     *                  1                PFLAG2_TEXT_ALIGNMENT_FLAGS[4]
1890     *                  1 1              PFLAG2_TEXT_ALIGNMENT_FLAGS[5]
1891     *                  11               PFLAG2_TEXT_ALIGNMENT_FLAGS[6]
1892     *                  111              PFLAG2_TEXT_ALIGNMENT_MASK
1893     *                 1                 PFLAG2_TEXT_ALIGNMENT_RESOLVED
1894     *                1                  PFLAG2_TEXT_ALIGNMENT_RESOLVED_DEFAULT
1895     *              111                  PFLAG2_TEXT_ALIGNMENT_RESOLVED_MASK
1896     *           111                     PFLAG2_IMPORTANT_FOR_ACCESSIBILITY_MASK
1897     *         11                        PFLAG2_ACCESSIBILITY_LIVE_REGION_MASK
1898     *       1                           PFLAG2_ACCESSIBILITY_FOCUSED
1899     *      1                            PFLAG2_SUBTREE_ACCESSIBILITY_STATE_CHANGED
1900     *     1                             PFLAG2_VIEW_QUICK_REJECTED
1901     *    1                              PFLAG2_PADDING_RESOLVED
1902     *   1                               PFLAG2_DRAWABLE_RESOLVED
1903     *  1                                PFLAG2_HAS_TRANSIENT_STATE
1904     * |-------|-------|-------|-------|
1905     */
1906
1907    /**
1908     * Indicates that this view has reported that it can accept the current drag's content.
1909     * Cleared when the drag operation concludes.
1910     * @hide
1911     */
1912    static final int PFLAG2_DRAG_CAN_ACCEPT            = 0x00000001;
1913
1914    /**
1915     * Indicates that this view is currently directly under the drag location in a
1916     * drag-and-drop operation involving content that it can accept.  Cleared when
1917     * the drag exits the view, or when the drag operation concludes.
1918     * @hide
1919     */
1920    static final int PFLAG2_DRAG_HOVERED               = 0x00000002;
1921
1922    /** @hide */
1923    @IntDef({
1924        LAYOUT_DIRECTION_LTR,
1925        LAYOUT_DIRECTION_RTL,
1926        LAYOUT_DIRECTION_INHERIT,
1927        LAYOUT_DIRECTION_LOCALE
1928    })
1929    @Retention(RetentionPolicy.SOURCE)
1930    // Not called LayoutDirection to avoid conflict with android.util.LayoutDirection
1931    public @interface LayoutDir {}
1932
1933    /** @hide */
1934    @IntDef({
1935        LAYOUT_DIRECTION_LTR,
1936        LAYOUT_DIRECTION_RTL
1937    })
1938    @Retention(RetentionPolicy.SOURCE)
1939    public @interface ResolvedLayoutDir {}
1940
1941    /**
1942     * A flag to indicate that the layout direction of this view has not been defined yet.
1943     * @hide
1944     */
1945    public static final int LAYOUT_DIRECTION_UNDEFINED = LayoutDirection.UNDEFINED;
1946
1947    /**
1948     * Horizontal layout direction of this view is from Left to Right.
1949     * Use with {@link #setLayoutDirection}.
1950     */
1951    public static final int LAYOUT_DIRECTION_LTR = LayoutDirection.LTR;
1952
1953    /**
1954     * Horizontal layout direction of this view is from Right to Left.
1955     * Use with {@link #setLayoutDirection}.
1956     */
1957    public static final int LAYOUT_DIRECTION_RTL = LayoutDirection.RTL;
1958
1959    /**
1960     * Horizontal layout direction of this view is inherited from its parent.
1961     * Use with {@link #setLayoutDirection}.
1962     */
1963    public static final int LAYOUT_DIRECTION_INHERIT = LayoutDirection.INHERIT;
1964
1965    /**
1966     * Horizontal layout direction of this view is from deduced from the default language
1967     * script for the locale. Use with {@link #setLayoutDirection}.
1968     */
1969    public static final int LAYOUT_DIRECTION_LOCALE = LayoutDirection.LOCALE;
1970
1971    /**
1972     * Bit shift to get the horizontal layout direction. (bits after DRAG_HOVERED)
1973     * @hide
1974     */
1975    static final int PFLAG2_LAYOUT_DIRECTION_MASK_SHIFT = 2;
1976
1977    /**
1978     * Mask for use with private flags indicating bits used for horizontal layout direction.
1979     * @hide
1980     */
1981    static final int PFLAG2_LAYOUT_DIRECTION_MASK = 0x00000003 << PFLAG2_LAYOUT_DIRECTION_MASK_SHIFT;
1982
1983    /**
1984     * Indicates whether the view horizontal layout direction has been resolved and drawn to the
1985     * right-to-left direction.
1986     * @hide
1987     */
1988    static final int PFLAG2_LAYOUT_DIRECTION_RESOLVED_RTL = 4 << PFLAG2_LAYOUT_DIRECTION_MASK_SHIFT;
1989
1990    /**
1991     * Indicates whether the view horizontal layout direction has been resolved.
1992     * @hide
1993     */
1994    static final int PFLAG2_LAYOUT_DIRECTION_RESOLVED = 8 << PFLAG2_LAYOUT_DIRECTION_MASK_SHIFT;
1995
1996    /**
1997     * Mask for use with private flags indicating bits used for resolved horizontal layout direction.
1998     * @hide
1999     */
2000    static final int PFLAG2_LAYOUT_DIRECTION_RESOLVED_MASK = 0x0000000C
2001            << PFLAG2_LAYOUT_DIRECTION_MASK_SHIFT;
2002
2003    /*
2004     * Array of horizontal layout direction flags for mapping attribute "layoutDirection" to correct
2005     * flag value.
2006     * @hide
2007     */
2008    private static final int[] LAYOUT_DIRECTION_FLAGS = {
2009            LAYOUT_DIRECTION_LTR,
2010            LAYOUT_DIRECTION_RTL,
2011            LAYOUT_DIRECTION_INHERIT,
2012            LAYOUT_DIRECTION_LOCALE
2013    };
2014
2015    /**
2016     * Default horizontal layout direction.
2017     */
2018    private static final int LAYOUT_DIRECTION_DEFAULT = LAYOUT_DIRECTION_INHERIT;
2019
2020    /**
2021     * Default horizontal layout direction.
2022     * @hide
2023     */
2024    static final int LAYOUT_DIRECTION_RESOLVED_DEFAULT = LAYOUT_DIRECTION_LTR;
2025
2026    /**
2027     * Text direction is inherited through {@link ViewGroup}
2028     */
2029    public static final int TEXT_DIRECTION_INHERIT = 0;
2030
2031    /**
2032     * Text direction is using "first strong algorithm". The first strong directional character
2033     * determines the paragraph direction. If there is no strong directional character, the
2034     * paragraph direction is the view's resolved layout direction.
2035     */
2036    public static final int TEXT_DIRECTION_FIRST_STRONG = 1;
2037
2038    /**
2039     * Text direction is using "any-RTL" algorithm. The paragraph direction is RTL if it contains
2040     * any strong RTL character, otherwise it is LTR if it contains any strong LTR characters.
2041     * If there are neither, the paragraph direction is the view's resolved layout direction.
2042     */
2043    public static final int TEXT_DIRECTION_ANY_RTL = 2;
2044
2045    /**
2046     * Text direction is forced to LTR.
2047     */
2048    public static final int TEXT_DIRECTION_LTR = 3;
2049
2050    /**
2051     * Text direction is forced to RTL.
2052     */
2053    public static final int TEXT_DIRECTION_RTL = 4;
2054
2055    /**
2056     * Text direction is coming from the system Locale.
2057     */
2058    public static final int TEXT_DIRECTION_LOCALE = 5;
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 LTR.
2064     */
2065    public static final int TEXT_DIRECTION_FIRST_STRONG_LTR = 6;
2066
2067    /**
2068     * Text direction is using "first strong algorithm". The first strong directional character
2069     * determines the paragraph direction. If there is no strong directional character, the
2070     * paragraph direction is RTL.
2071     */
2072    public static final int TEXT_DIRECTION_FIRST_STRONG_RTL = 7;
2073
2074    /**
2075     * Default text direction is inherited
2076     */
2077    private static final int TEXT_DIRECTION_DEFAULT = TEXT_DIRECTION_INHERIT;
2078
2079    /**
2080     * Default resolved text direction
2081     * @hide
2082     */
2083    static final int TEXT_DIRECTION_RESOLVED_DEFAULT = TEXT_DIRECTION_FIRST_STRONG;
2084
2085    /**
2086     * Bit shift to get the horizontal layout direction. (bits after LAYOUT_DIRECTION_RESOLVED)
2087     * @hide
2088     */
2089    static final int PFLAG2_TEXT_DIRECTION_MASK_SHIFT = 6;
2090
2091    /**
2092     * Mask for use with private flags indicating bits used for text direction.
2093     * @hide
2094     */
2095    static final int PFLAG2_TEXT_DIRECTION_MASK = 0x00000007
2096            << PFLAG2_TEXT_DIRECTION_MASK_SHIFT;
2097
2098    /**
2099     * Array of text direction flags for mapping attribute "textDirection" to correct
2100     * flag value.
2101     * @hide
2102     */
2103    private static final int[] PFLAG2_TEXT_DIRECTION_FLAGS = {
2104            TEXT_DIRECTION_INHERIT << PFLAG2_TEXT_DIRECTION_MASK_SHIFT,
2105            TEXT_DIRECTION_FIRST_STRONG << PFLAG2_TEXT_DIRECTION_MASK_SHIFT,
2106            TEXT_DIRECTION_ANY_RTL << PFLAG2_TEXT_DIRECTION_MASK_SHIFT,
2107            TEXT_DIRECTION_LTR << PFLAG2_TEXT_DIRECTION_MASK_SHIFT,
2108            TEXT_DIRECTION_RTL << PFLAG2_TEXT_DIRECTION_MASK_SHIFT,
2109            TEXT_DIRECTION_LOCALE << PFLAG2_TEXT_DIRECTION_MASK_SHIFT,
2110            TEXT_DIRECTION_FIRST_STRONG_LTR << PFLAG2_TEXT_DIRECTION_MASK_SHIFT,
2111            TEXT_DIRECTION_FIRST_STRONG_RTL << PFLAG2_TEXT_DIRECTION_MASK_SHIFT
2112    };
2113
2114    /**
2115     * Indicates whether the view text direction has been resolved.
2116     * @hide
2117     */
2118    static final int PFLAG2_TEXT_DIRECTION_RESOLVED = 0x00000008
2119            << PFLAG2_TEXT_DIRECTION_MASK_SHIFT;
2120
2121    /**
2122     * Bit shift to get the horizontal layout direction. (bits after DRAG_HOVERED)
2123     * @hide
2124     */
2125    static final int PFLAG2_TEXT_DIRECTION_RESOLVED_MASK_SHIFT = 10;
2126
2127    /**
2128     * Mask for use with private flags indicating bits used for resolved text direction.
2129     * @hide
2130     */
2131    static final int PFLAG2_TEXT_DIRECTION_RESOLVED_MASK = 0x00000007
2132            << PFLAG2_TEXT_DIRECTION_RESOLVED_MASK_SHIFT;
2133
2134    /**
2135     * Indicates whether the view text direction has been resolved to the "first strong" heuristic.
2136     * @hide
2137     */
2138    static final int PFLAG2_TEXT_DIRECTION_RESOLVED_DEFAULT =
2139            TEXT_DIRECTION_RESOLVED_DEFAULT << PFLAG2_TEXT_DIRECTION_RESOLVED_MASK_SHIFT;
2140
2141    /** @hide */
2142    @IntDef({
2143        TEXT_ALIGNMENT_INHERIT,
2144        TEXT_ALIGNMENT_GRAVITY,
2145        TEXT_ALIGNMENT_CENTER,
2146        TEXT_ALIGNMENT_TEXT_START,
2147        TEXT_ALIGNMENT_TEXT_END,
2148        TEXT_ALIGNMENT_VIEW_START,
2149        TEXT_ALIGNMENT_VIEW_END
2150    })
2151    @Retention(RetentionPolicy.SOURCE)
2152    public @interface TextAlignment {}
2153
2154    /**
2155     * Default text alignment. The text alignment of this View is inherited from its parent.
2156     * Use with {@link #setTextAlignment(int)}
2157     */
2158    public static final int TEXT_ALIGNMENT_INHERIT = 0;
2159
2160    /**
2161     * Default for the root view. The gravity determines the text alignment, ALIGN_NORMAL,
2162     * ALIGN_CENTER, or ALIGN_OPPOSITE, which are relative to each paragraph’s text direction.
2163     *
2164     * Use with {@link #setTextAlignment(int)}
2165     */
2166    public static final int TEXT_ALIGNMENT_GRAVITY = 1;
2167
2168    /**
2169     * Align to the start of the paragraph, e.g. ALIGN_NORMAL.
2170     *
2171     * Use with {@link #setTextAlignment(int)}
2172     */
2173    public static final int TEXT_ALIGNMENT_TEXT_START = 2;
2174
2175    /**
2176     * Align to the end of the paragraph, e.g. ALIGN_OPPOSITE.
2177     *
2178     * Use with {@link #setTextAlignment(int)}
2179     */
2180    public static final int TEXT_ALIGNMENT_TEXT_END = 3;
2181
2182    /**
2183     * Center the paragraph, e.g. ALIGN_CENTER.
2184     *
2185     * Use with {@link #setTextAlignment(int)}
2186     */
2187    public static final int TEXT_ALIGNMENT_CENTER = 4;
2188
2189    /**
2190     * Align to the start of the view, which is ALIGN_LEFT if the view’s resolved
2191     * layoutDirection is LTR, and ALIGN_RIGHT otherwise.
2192     *
2193     * Use with {@link #setTextAlignment(int)}
2194     */
2195    public static final int TEXT_ALIGNMENT_VIEW_START = 5;
2196
2197    /**
2198     * Align to the end of the view, which is ALIGN_RIGHT if the view’s resolved
2199     * layoutDirection is LTR, and ALIGN_LEFT otherwise.
2200     *
2201     * Use with {@link #setTextAlignment(int)}
2202     */
2203    public static final int TEXT_ALIGNMENT_VIEW_END = 6;
2204
2205    /**
2206     * Default text alignment is inherited
2207     */
2208    private static final int TEXT_ALIGNMENT_DEFAULT = TEXT_ALIGNMENT_GRAVITY;
2209
2210    /**
2211     * Default resolved text alignment
2212     * @hide
2213     */
2214    static final int TEXT_ALIGNMENT_RESOLVED_DEFAULT = TEXT_ALIGNMENT_GRAVITY;
2215
2216    /**
2217      * Bit shift to get the horizontal layout direction. (bits after DRAG_HOVERED)
2218      * @hide
2219      */
2220    static final int PFLAG2_TEXT_ALIGNMENT_MASK_SHIFT = 13;
2221
2222    /**
2223      * Mask for use with private flags indicating bits used for text alignment.
2224      * @hide
2225      */
2226    static final int PFLAG2_TEXT_ALIGNMENT_MASK = 0x00000007 << PFLAG2_TEXT_ALIGNMENT_MASK_SHIFT;
2227
2228    /**
2229     * Array of text direction flags for mapping attribute "textAlignment" to correct
2230     * flag value.
2231     * @hide
2232     */
2233    private static final int[] PFLAG2_TEXT_ALIGNMENT_FLAGS = {
2234            TEXT_ALIGNMENT_INHERIT << PFLAG2_TEXT_ALIGNMENT_MASK_SHIFT,
2235            TEXT_ALIGNMENT_GRAVITY << PFLAG2_TEXT_ALIGNMENT_MASK_SHIFT,
2236            TEXT_ALIGNMENT_TEXT_START << PFLAG2_TEXT_ALIGNMENT_MASK_SHIFT,
2237            TEXT_ALIGNMENT_TEXT_END << PFLAG2_TEXT_ALIGNMENT_MASK_SHIFT,
2238            TEXT_ALIGNMENT_CENTER << PFLAG2_TEXT_ALIGNMENT_MASK_SHIFT,
2239            TEXT_ALIGNMENT_VIEW_START << PFLAG2_TEXT_ALIGNMENT_MASK_SHIFT,
2240            TEXT_ALIGNMENT_VIEW_END << PFLAG2_TEXT_ALIGNMENT_MASK_SHIFT
2241    };
2242
2243    /**
2244     * Indicates whether the view text alignment has been resolved.
2245     * @hide
2246     */
2247    static final int PFLAG2_TEXT_ALIGNMENT_RESOLVED = 0x00000008 << PFLAG2_TEXT_ALIGNMENT_MASK_SHIFT;
2248
2249    /**
2250     * Bit shift to get the resolved text alignment.
2251     * @hide
2252     */
2253    static final int PFLAG2_TEXT_ALIGNMENT_RESOLVED_MASK_SHIFT = 17;
2254
2255    /**
2256     * Mask for use with private flags indicating bits used for text alignment.
2257     * @hide
2258     */
2259    static final int PFLAG2_TEXT_ALIGNMENT_RESOLVED_MASK = 0x00000007
2260            << PFLAG2_TEXT_ALIGNMENT_RESOLVED_MASK_SHIFT;
2261
2262    /**
2263     * Indicates whether if the view text alignment has been resolved to gravity
2264     */
2265    private static final int PFLAG2_TEXT_ALIGNMENT_RESOLVED_DEFAULT =
2266            TEXT_ALIGNMENT_RESOLVED_DEFAULT << PFLAG2_TEXT_ALIGNMENT_RESOLVED_MASK_SHIFT;
2267
2268    // Accessiblity constants for mPrivateFlags2
2269
2270    /**
2271     * Shift for the bits in {@link #mPrivateFlags2} related to the
2272     * "importantForAccessibility" attribute.
2273     */
2274    static final int PFLAG2_IMPORTANT_FOR_ACCESSIBILITY_SHIFT = 20;
2275
2276    /**
2277     * Automatically determine whether a view is important for accessibility.
2278     */
2279    public static final int IMPORTANT_FOR_ACCESSIBILITY_AUTO = 0x00000000;
2280
2281    /**
2282     * The view is important for accessibility.
2283     */
2284    public static final int IMPORTANT_FOR_ACCESSIBILITY_YES = 0x00000001;
2285
2286    /**
2287     * The view is not important for accessibility.
2288     */
2289    public static final int IMPORTANT_FOR_ACCESSIBILITY_NO = 0x00000002;
2290
2291    /**
2292     * The view is not important for accessibility, nor are any of its
2293     * descendant views.
2294     */
2295    public static final int IMPORTANT_FOR_ACCESSIBILITY_NO_HIDE_DESCENDANTS = 0x00000004;
2296
2297    /**
2298     * The default whether the view is important for accessibility.
2299     */
2300    static final int IMPORTANT_FOR_ACCESSIBILITY_DEFAULT = IMPORTANT_FOR_ACCESSIBILITY_AUTO;
2301
2302    /**
2303     * Mask for obtainig the bits which specify how to determine
2304     * whether a view is important for accessibility.
2305     */
2306    static final int PFLAG2_IMPORTANT_FOR_ACCESSIBILITY_MASK = (IMPORTANT_FOR_ACCESSIBILITY_AUTO
2307        | IMPORTANT_FOR_ACCESSIBILITY_YES | IMPORTANT_FOR_ACCESSIBILITY_NO
2308        | IMPORTANT_FOR_ACCESSIBILITY_NO_HIDE_DESCENDANTS)
2309        << PFLAG2_IMPORTANT_FOR_ACCESSIBILITY_SHIFT;
2310
2311    /**
2312     * Shift for the bits in {@link #mPrivateFlags2} related to the
2313     * "accessibilityLiveRegion" attribute.
2314     */
2315    static final int PFLAG2_ACCESSIBILITY_LIVE_REGION_SHIFT = 23;
2316
2317    /**
2318     * Live region mode specifying that accessibility services should not
2319     * automatically announce changes to this view. This is the default live
2320     * region mode for most views.
2321     * <p>
2322     * Use with {@link #setAccessibilityLiveRegion(int)}.
2323     */
2324    public static final int ACCESSIBILITY_LIVE_REGION_NONE = 0x00000000;
2325
2326    /**
2327     * Live region mode specifying that accessibility services should announce
2328     * changes to this view.
2329     * <p>
2330     * Use with {@link #setAccessibilityLiveRegion(int)}.
2331     */
2332    public static final int ACCESSIBILITY_LIVE_REGION_POLITE = 0x00000001;
2333
2334    /**
2335     * Live region mode specifying that accessibility services should interrupt
2336     * ongoing speech to immediately announce changes to this view.
2337     * <p>
2338     * Use with {@link #setAccessibilityLiveRegion(int)}.
2339     */
2340    public static final int ACCESSIBILITY_LIVE_REGION_ASSERTIVE = 0x00000002;
2341
2342    /**
2343     * The default whether the view is important for accessibility.
2344     */
2345    static final int ACCESSIBILITY_LIVE_REGION_DEFAULT = ACCESSIBILITY_LIVE_REGION_NONE;
2346
2347    /**
2348     * Mask for obtaining the bits which specify a view's accessibility live
2349     * region mode.
2350     */
2351    static final int PFLAG2_ACCESSIBILITY_LIVE_REGION_MASK = (ACCESSIBILITY_LIVE_REGION_NONE
2352            | ACCESSIBILITY_LIVE_REGION_POLITE | ACCESSIBILITY_LIVE_REGION_ASSERTIVE)
2353            << PFLAG2_ACCESSIBILITY_LIVE_REGION_SHIFT;
2354
2355    /**
2356     * Flag indicating whether a view has accessibility focus.
2357     */
2358    static final int PFLAG2_ACCESSIBILITY_FOCUSED = 0x04000000;
2359
2360    /**
2361     * Flag whether the accessibility state of the subtree rooted at this view changed.
2362     */
2363    static final int PFLAG2_SUBTREE_ACCESSIBILITY_STATE_CHANGED = 0x08000000;
2364
2365    /**
2366     * Flag indicating whether a view failed the quickReject() check in draw(). This condition
2367     * is used to check whether later changes to the view's transform should invalidate the
2368     * view to force the quickReject test to run again.
2369     */
2370    static final int PFLAG2_VIEW_QUICK_REJECTED = 0x10000000;
2371
2372    /**
2373     * Flag indicating that start/end padding has been resolved into left/right padding
2374     * for use in measurement, layout, drawing, etc. This is set by {@link #resolvePadding()}
2375     * and checked by {@link #measure(int, int)} to determine if padding needs to be resolved
2376     * during measurement. In some special cases this is required such as when an adapter-based
2377     * view measures prospective children without attaching them to a window.
2378     */
2379    static final int PFLAG2_PADDING_RESOLVED = 0x20000000;
2380
2381    /**
2382     * Flag indicating that the start/end drawables has been resolved into left/right ones.
2383     */
2384    static final int PFLAG2_DRAWABLE_RESOLVED = 0x40000000;
2385
2386    /**
2387     * Indicates that the view is tracking some sort of transient state
2388     * that the app should not need to be aware of, but that the framework
2389     * should take special care to preserve.
2390     */
2391    static final int PFLAG2_HAS_TRANSIENT_STATE = 0x80000000;
2392
2393    /**
2394     * Group of bits indicating that RTL properties resolution is done.
2395     */
2396    static final int ALL_RTL_PROPERTIES_RESOLVED = PFLAG2_LAYOUT_DIRECTION_RESOLVED |
2397            PFLAG2_TEXT_DIRECTION_RESOLVED |
2398            PFLAG2_TEXT_ALIGNMENT_RESOLVED |
2399            PFLAG2_PADDING_RESOLVED |
2400            PFLAG2_DRAWABLE_RESOLVED;
2401
2402    // There are a couple of flags left in mPrivateFlags2
2403
2404    /* End of masks for mPrivateFlags2 */
2405
2406    /**
2407     * Masks for mPrivateFlags3, as generated by dumpFlags():
2408     *
2409     * |-------|-------|-------|-------|
2410     *                                 1 PFLAG3_VIEW_IS_ANIMATING_TRANSFORM
2411     *                                1  PFLAG3_VIEW_IS_ANIMATING_ALPHA
2412     *                               1   PFLAG3_IS_LAID_OUT
2413     *                              1    PFLAG3_MEASURE_NEEDED_BEFORE_LAYOUT
2414     *                             1     PFLAG3_CALLED_SUPER
2415     *                            1      PFLAG3_APPLYING_INSETS
2416     *                           1       PFLAG3_FITTING_SYSTEM_WINDOWS
2417     *                          1        PFLAG3_NESTED_SCROLLING_ENABLED
2418     *                         1         PFLAG3_SCROLL_INDICATOR_TOP
2419     *                        1          PFLAG3_SCROLL_INDICATOR_BOTTOM
2420     *                       1           PFLAG3_SCROLL_INDICATOR_LEFT
2421     *                      1            PFLAG3_SCROLL_INDICATOR_RIGHT
2422     *                     1             PFLAG3_SCROLL_INDICATOR_START
2423     *                    1              PFLAG3_SCROLL_INDICATOR_END
2424     *                   1               PFLAG3_ASSIST_BLOCKED
2425     *            1111111                PFLAG3_POINTER_ICON_MASK
2426     *           1                       PFLAG3_PARTIAL_LAYOUT_REQUESTED
2427     *          1                        PFLAG3_LAYOUT_PARAMS_CHANGED
2428     * |-------|-------|-------|-------|
2429     */
2430
2431    /**
2432     * Flag indicating that view has a transform animation set on it. This is used to track whether
2433     * an animation is cleared between successive frames, in order to tell the associated
2434     * DisplayList to clear its animation matrix.
2435     */
2436    static final int PFLAG3_VIEW_IS_ANIMATING_TRANSFORM = 0x1;
2437
2438    /**
2439     * Flag indicating that view has an alpha animation set on it. This is used to track whether an
2440     * animation is cleared between successive frames, in order to tell the associated
2441     * DisplayList to restore its alpha value.
2442     */
2443    static final int PFLAG3_VIEW_IS_ANIMATING_ALPHA = 0x2;
2444
2445    /**
2446     * Flag indicating that the view has been through at least one layout since it
2447     * was last attached to a window.
2448     */
2449    static final int PFLAG3_IS_LAID_OUT = 0x4;
2450
2451    /**
2452     * Flag indicating that a call to measure() was skipped and should be done
2453     * instead when layout() is invoked.
2454     */
2455    static final int PFLAG3_MEASURE_NEEDED_BEFORE_LAYOUT = 0x8;
2456
2457    /**
2458     * Flag indicating that an overridden method correctly called down to
2459     * the superclass implementation as required by the API spec.
2460     */
2461    static final int PFLAG3_CALLED_SUPER = 0x10;
2462
2463    /**
2464     * Flag indicating that we're in the process of applying window insets.
2465     */
2466    static final int PFLAG3_APPLYING_INSETS = 0x20;
2467
2468    /**
2469     * Flag indicating that we're in the process of fitting system windows using the old method.
2470     */
2471    static final int PFLAG3_FITTING_SYSTEM_WINDOWS = 0x40;
2472
2473    /**
2474     * Flag indicating that nested scrolling is enabled for this view.
2475     * The view will optionally cooperate with views up its parent chain to allow for
2476     * integrated nested scrolling along the same axis.
2477     */
2478    static final int PFLAG3_NESTED_SCROLLING_ENABLED = 0x80;
2479
2480    /**
2481     * Flag indicating that the bottom scroll indicator should be displayed
2482     * when this view can scroll up.
2483     */
2484    static final int PFLAG3_SCROLL_INDICATOR_TOP = 0x0100;
2485
2486    /**
2487     * Flag indicating that the bottom scroll indicator should be displayed
2488     * when this view can scroll down.
2489     */
2490    static final int PFLAG3_SCROLL_INDICATOR_BOTTOM = 0x0200;
2491
2492    /**
2493     * Flag indicating that the left scroll indicator should be displayed
2494     * when this view can scroll left.
2495     */
2496    static final int PFLAG3_SCROLL_INDICATOR_LEFT = 0x0400;
2497
2498    /**
2499     * Flag indicating that the right scroll indicator should be displayed
2500     * when this view can scroll right.
2501     */
2502    static final int PFLAG3_SCROLL_INDICATOR_RIGHT = 0x0800;
2503
2504    /**
2505     * Flag indicating that the start scroll indicator should be displayed
2506     * when this view can scroll in the start direction.
2507     */
2508    static final int PFLAG3_SCROLL_INDICATOR_START = 0x1000;
2509
2510    /**
2511     * Flag indicating that the end scroll indicator should be displayed
2512     * when this view can scroll in the end direction.
2513     */
2514    static final int PFLAG3_SCROLL_INDICATOR_END = 0x2000;
2515
2516
2517    /* End of masks for mPrivateFlags3 */
2518
2519    static final int DRAG_MASK = PFLAG2_DRAG_CAN_ACCEPT | PFLAG2_DRAG_HOVERED;
2520
2521    static final int SCROLL_INDICATORS_NONE = 0x0000;
2522
2523    /**
2524     * Mask for use with setFlags indicating bits used for indicating which
2525     * scroll indicators are enabled.
2526     */
2527    static final int SCROLL_INDICATORS_PFLAG3_MASK = PFLAG3_SCROLL_INDICATOR_TOP
2528            | PFLAG3_SCROLL_INDICATOR_BOTTOM | PFLAG3_SCROLL_INDICATOR_LEFT
2529            | PFLAG3_SCROLL_INDICATOR_RIGHT | PFLAG3_SCROLL_INDICATOR_START
2530            | PFLAG3_SCROLL_INDICATOR_END;
2531
2532    /**
2533     * Left-shift required to translate between public scroll indicator flags
2534     * and internal PFLAGS3 flags. When used as a right-shift, translates
2535     * PFLAGS3 flags to public flags.
2536     */
2537    static final int SCROLL_INDICATORS_TO_PFLAGS3_LSHIFT = 8;
2538
2539    /** @hide */
2540    @Retention(RetentionPolicy.SOURCE)
2541    @IntDef(flag = true,
2542            value = {
2543                    SCROLL_INDICATOR_TOP,
2544                    SCROLL_INDICATOR_BOTTOM,
2545                    SCROLL_INDICATOR_LEFT,
2546                    SCROLL_INDICATOR_RIGHT,
2547                    SCROLL_INDICATOR_START,
2548                    SCROLL_INDICATOR_END,
2549            })
2550    public @interface ScrollIndicators {}
2551
2552    /**
2553     * Scroll indicator direction for the top 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_TOP =
2560            PFLAG3_SCROLL_INDICATOR_TOP >> SCROLL_INDICATORS_TO_PFLAGS3_LSHIFT;
2561
2562    /**
2563     * Scroll indicator direction for the bottom 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_BOTTOM =
2570            PFLAG3_SCROLL_INDICATOR_BOTTOM >> SCROLL_INDICATORS_TO_PFLAGS3_LSHIFT;
2571
2572    /**
2573     * Scroll indicator direction for the left 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_LEFT =
2580            PFLAG3_SCROLL_INDICATOR_LEFT >> SCROLL_INDICATORS_TO_PFLAGS3_LSHIFT;
2581
2582    /**
2583     * Scroll indicator direction for the right edge of the view.
2584     *
2585     * @see #setScrollIndicators(int)
2586     * @see #setScrollIndicators(int, int)
2587     * @see #getScrollIndicators()
2588     */
2589    public static final int SCROLL_INDICATOR_RIGHT =
2590            PFLAG3_SCROLL_INDICATOR_RIGHT >> SCROLL_INDICATORS_TO_PFLAGS3_LSHIFT;
2591
2592    /**
2593     * Scroll indicator direction for the starting edge of the view.
2594     * <p>
2595     * Resolved according to the view's layout direction, see
2596     * {@link #getLayoutDirection()} for more information.
2597     *
2598     * @see #setScrollIndicators(int)
2599     * @see #setScrollIndicators(int, int)
2600     * @see #getScrollIndicators()
2601     */
2602    public static final int SCROLL_INDICATOR_START =
2603            PFLAG3_SCROLL_INDICATOR_START >> SCROLL_INDICATORS_TO_PFLAGS3_LSHIFT;
2604
2605    /**
2606     * Scroll indicator direction for the ending edge of the view.
2607     * <p>
2608     * Resolved according to the view's layout direction, see
2609     * {@link #getLayoutDirection()} for more information.
2610     *
2611     * @see #setScrollIndicators(int)
2612     * @see #setScrollIndicators(int, int)
2613     * @see #getScrollIndicators()
2614     */
2615    public static final int SCROLL_INDICATOR_END =
2616            PFLAG3_SCROLL_INDICATOR_END >> SCROLL_INDICATORS_TO_PFLAGS3_LSHIFT;
2617
2618    /**
2619     * <p>Indicates that we are allowing {@link ViewStructure} to traverse
2620     * into this view.<p>
2621     */
2622    static final int PFLAG3_ASSIST_BLOCKED = 0x4000;
2623
2624    /**
2625     * The mask for use with private flags indicating bits used for pointer icon shapes.
2626     */
2627    static final int PFLAG3_POINTER_ICON_MASK = 0x7f8000;
2628
2629    /**
2630     * Left-shift used for pointer icon shape values in private flags.
2631     */
2632    static final int PFLAG3_POINTER_ICON_LSHIFT = 15;
2633
2634    /**
2635     * Value indicating {@link PointerIcon.STYLE_NOT_SPECIFIED}.
2636     */
2637    private static final int PFLAG3_POINTER_ICON_NOT_SPECIFIED = 0 << PFLAG3_POINTER_ICON_LSHIFT;
2638
2639    /**
2640     * Value indicating {@link PointerIcon.STYLE_NULL}.
2641     */
2642    private static final int PFLAG3_POINTER_ICON_NULL = 1 << PFLAG3_POINTER_ICON_LSHIFT;
2643
2644    /**
2645     * Value incicating {@link PointerIcon.STYLE_CUSTOM}.
2646     */
2647    private static final int PFLAG3_POINTER_ICON_CUSTOM = 2 << PFLAG3_POINTER_ICON_LSHIFT;
2648
2649    /**
2650     * The base value for other pointer icon shapes.
2651     */
2652    private static final int PFLAG3_POINTER_ICON_VALUE_START = 3 << PFLAG3_POINTER_ICON_LSHIFT;
2653
2654    /**
2655     * Flag indicating that this view has requested a partial layout and
2656     * is added to the AttachInfo's list of views that need a partial layout
2657     * request handled on the next traversal.
2658     */
2659    static final int PFLAG3_PARTIAL_LAYOUT_REQUESTED = 0x800000;
2660
2661    /**
2662     * Flag indicating that this view's LayoutParams have been explicitly changed
2663     * since the last layout pass.
2664     */
2665    static final int PFLAG3_LAYOUT_PARAMS_CHANGED = 0x1000000;
2666
2667    /**
2668     * Always allow a user to over-scroll this view, provided it is a
2669     * view that can scroll.
2670     *
2671     * @see #getOverScrollMode()
2672     * @see #setOverScrollMode(int)
2673     */
2674    public static final int OVER_SCROLL_ALWAYS = 0;
2675
2676    /**
2677     * Allow a user to over-scroll this view only if the content is large
2678     * enough to meaningfully scroll, provided it is a view that can scroll.
2679     *
2680     * @see #getOverScrollMode()
2681     * @see #setOverScrollMode(int)
2682     */
2683    public static final int OVER_SCROLL_IF_CONTENT_SCROLLS = 1;
2684
2685    /**
2686     * Never allow a user to over-scroll this view.
2687     *
2688     * @see #getOverScrollMode()
2689     * @see #setOverScrollMode(int)
2690     */
2691    public static final int OVER_SCROLL_NEVER = 2;
2692
2693    /**
2694     * Special constant for {@link #setSystemUiVisibility(int)}: View has
2695     * requested the system UI (status bar) to be visible (the default).
2696     *
2697     * @see #setSystemUiVisibility(int)
2698     */
2699    public static final int SYSTEM_UI_FLAG_VISIBLE = 0;
2700
2701    /**
2702     * Flag for {@link #setSystemUiVisibility(int)}: View has requested the
2703     * system UI to enter an unobtrusive "low profile" mode.
2704     *
2705     * <p>This is for use in games, book readers, video players, or any other
2706     * "immersive" application where the usual system chrome is deemed too distracting.
2707     *
2708     * <p>In low profile mode, the status bar and/or navigation icons may dim.
2709     *
2710     * @see #setSystemUiVisibility(int)
2711     */
2712    public static final int SYSTEM_UI_FLAG_LOW_PROFILE = 0x00000001;
2713
2714    /**
2715     * Flag for {@link #setSystemUiVisibility(int)}: View has requested that the
2716     * system navigation be temporarily hidden.
2717     *
2718     * <p>This is an even less obtrusive state than that called for by
2719     * {@link #SYSTEM_UI_FLAG_LOW_PROFILE}; on devices that draw essential navigation controls
2720     * (Home, Back, and the like) on screen, <code>SYSTEM_UI_FLAG_HIDE_NAVIGATION</code> will cause
2721     * those to disappear. This is useful (in conjunction with the
2722     * {@link android.view.WindowManager.LayoutParams#FLAG_FULLSCREEN FLAG_FULLSCREEN} and
2723     * {@link android.view.WindowManager.LayoutParams#FLAG_LAYOUT_IN_SCREEN FLAG_LAYOUT_IN_SCREEN}
2724     * window flags) for displaying content using every last pixel on the display.
2725     *
2726     * <p>There is a limitation: because navigation controls are so important, the least user
2727     * interaction will cause them to reappear immediately.  When this happens, both
2728     * this flag and {@link #SYSTEM_UI_FLAG_FULLSCREEN} will be cleared automatically,
2729     * so that both elements reappear at the same time.
2730     *
2731     * @see #setSystemUiVisibility(int)
2732     */
2733    public static final int SYSTEM_UI_FLAG_HIDE_NAVIGATION = 0x00000002;
2734
2735    /**
2736     * Flag for {@link #setSystemUiVisibility(int)}: View has requested to go
2737     * into the normal fullscreen mode so that its content can take over the screen
2738     * while still allowing the user to interact with the application.
2739     *
2740     * <p>This has the same visual effect as
2741     * {@link android.view.WindowManager.LayoutParams#FLAG_FULLSCREEN
2742     * WindowManager.LayoutParams.FLAG_FULLSCREEN},
2743     * meaning that non-critical screen decorations (such as the status bar) will be
2744     * hidden while the user is in the View's window, focusing the experience on
2745     * that content.  Unlike the window flag, if you are using ActionBar in
2746     * overlay mode with {@link Window#FEATURE_ACTION_BAR_OVERLAY
2747     * Window.FEATURE_ACTION_BAR_OVERLAY}, then enabling this flag will also
2748     * hide the action bar.
2749     *
2750     * <p>This approach to going fullscreen is best used over the window flag when
2751     * it is a transient state -- that is, the application does this at certain
2752     * points in its user interaction where it wants to allow the user to focus
2753     * on content, but not as a continuous state.  For situations where the application
2754     * would like to simply stay full screen the entire time (such as a game that
2755     * wants to take over the screen), the
2756     * {@link android.view.WindowManager.LayoutParams#FLAG_FULLSCREEN window flag}
2757     * is usually a better approach.  The state set here will be removed by the system
2758     * in various situations (such as the user moving to another application) like
2759     * the other system UI states.
2760     *
2761     * <p>When using this flag, the application should provide some easy facility
2762     * for the user to go out of it.  A common example would be in an e-book
2763     * reader, where tapping on the screen brings back whatever screen and UI
2764     * decorations that had been hidden while the user was immersed in reading
2765     * the book.
2766     *
2767     * @see #setSystemUiVisibility(int)
2768     */
2769    public static final int SYSTEM_UI_FLAG_FULLSCREEN = 0x00000004;
2770
2771    /**
2772     * Flag for {@link #setSystemUiVisibility(int)}: When using other layout
2773     * flags, we would like a stable view of the content insets given to
2774     * {@link #fitSystemWindows(Rect)}.  This means that the insets seen there
2775     * will always represent the worst case that the application can expect
2776     * as a continuous state.  In the stock Android UI this is the space for
2777     * the system bar, nav bar, and status bar, but not more transient elements
2778     * such as an input method.
2779     *
2780     * The stable layout your UI sees is based on the system UI modes you can
2781     * switch to.  That is, if you specify {@link #SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN}
2782     * then you will get a stable layout for changes of the
2783     * {@link #SYSTEM_UI_FLAG_FULLSCREEN} mode; if you specify
2784     * {@link #SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN} and
2785     * {@link #SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION}, then you can transition
2786     * to {@link #SYSTEM_UI_FLAG_FULLSCREEN} and {@link #SYSTEM_UI_FLAG_HIDE_NAVIGATION}
2787     * with a stable layout.  (Note that you should avoid using
2788     * {@link #SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION} by itself.)
2789     *
2790     * If you have set the window flag {@link WindowManager.LayoutParams#FLAG_FULLSCREEN}
2791     * to hide the status bar (instead of using {@link #SYSTEM_UI_FLAG_FULLSCREEN}),
2792     * then a hidden status bar will be considered a "stable" state for purposes
2793     * here.  This allows your UI to continually hide the status bar, while still
2794     * using the system UI flags to hide the action bar while still retaining
2795     * a stable layout.  Note that changing the window fullscreen flag will never
2796     * provide a stable layout for a clean transition.
2797     *
2798     * <p>If you are using ActionBar in
2799     * overlay mode with {@link Window#FEATURE_ACTION_BAR_OVERLAY
2800     * Window.FEATURE_ACTION_BAR_OVERLAY}, this flag will also impact the
2801     * insets it adds to those given to the application.
2802     */
2803    public static final int SYSTEM_UI_FLAG_LAYOUT_STABLE = 0x00000100;
2804
2805    /**
2806     * Flag for {@link #setSystemUiVisibility(int)}: View would like its window
2807     * to be laid out as if it has requested
2808     * {@link #SYSTEM_UI_FLAG_HIDE_NAVIGATION}, even if it currently hasn't.  This
2809     * allows it to avoid artifacts when switching in and out of that mode, at
2810     * the expense that some of its user interface may be covered by screen
2811     * decorations when they are shown.  You can perform layout of your inner
2812     * UI elements to account for the navigation system UI through the
2813     * {@link #fitSystemWindows(Rect)} method.
2814     */
2815    public static final int SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION = 0x00000200;
2816
2817    /**
2818     * Flag for {@link #setSystemUiVisibility(int)}: View would like its window
2819     * to be laid out as if it has requested
2820     * {@link #SYSTEM_UI_FLAG_FULLSCREEN}, even if it currently hasn't.  This
2821     * allows it to avoid artifacts when switching in and out of that mode, at
2822     * the expense that some of its user interface may be covered by screen
2823     * decorations when they are shown.  You can perform layout of your inner
2824     * UI elements to account for non-fullscreen system UI through the
2825     * {@link #fitSystemWindows(Rect)} method.
2826     */
2827    public static final int SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN = 0x00000400;
2828
2829    /**
2830     * Flag for {@link #setSystemUiVisibility(int)}: View would like to remain interactive when
2831     * hiding the navigation bar with {@link #SYSTEM_UI_FLAG_HIDE_NAVIGATION}.  If this flag is
2832     * not set, {@link #SYSTEM_UI_FLAG_HIDE_NAVIGATION} will be force cleared by the system on any
2833     * user interaction.
2834     * <p>Since this flag is a modifier for {@link #SYSTEM_UI_FLAG_HIDE_NAVIGATION}, it only
2835     * has an effect when used in combination with that flag.</p>
2836     */
2837    public static final int SYSTEM_UI_FLAG_IMMERSIVE = 0x00000800;
2838
2839    /**
2840     * Flag for {@link #setSystemUiVisibility(int)}: View would like to remain interactive when
2841     * hiding the status bar with {@link #SYSTEM_UI_FLAG_FULLSCREEN} and/or hiding the navigation
2842     * bar with {@link #SYSTEM_UI_FLAG_HIDE_NAVIGATION}.  Use this flag to create an immersive
2843     * experience while also hiding the system bars.  If this flag is not set,
2844     * {@link #SYSTEM_UI_FLAG_HIDE_NAVIGATION} will be force cleared by the system on any user
2845     * interaction, and {@link #SYSTEM_UI_FLAG_FULLSCREEN} will be force-cleared by the system
2846     * if the user swipes from the top of the screen.
2847     * <p>When system bars are hidden in immersive mode, they can be revealed temporarily with
2848     * system gestures, such as swiping from the top of the screen.  These transient system bars
2849     * will overlay app’s content, may have some degree of transparency, and will automatically
2850     * hide after a short timeout.
2851     * </p><p>Since this flag is a modifier for {@link #SYSTEM_UI_FLAG_FULLSCREEN} and
2852     * {@link #SYSTEM_UI_FLAG_HIDE_NAVIGATION}, it only has an effect when used in combination
2853     * with one or both of those flags.</p>
2854     */
2855    public static final int SYSTEM_UI_FLAG_IMMERSIVE_STICKY = 0x00001000;
2856
2857    /**
2858     * Flag for {@link #setSystemUiVisibility(int)}: Requests the status bar to draw in a mode that
2859     * is compatible with light status bar backgrounds.
2860     *
2861     * <p>For this to take effect, the window must request
2862     * {@link android.view.WindowManager.LayoutParams#FLAG_DRAWS_SYSTEM_BAR_BACKGROUNDS
2863     *         FLAG_DRAWS_SYSTEM_BAR_BACKGROUNDS} but not
2864     * {@link android.view.WindowManager.LayoutParams#FLAG_TRANSLUCENT_STATUS
2865     *         FLAG_TRANSLUCENT_STATUS}.
2866     *
2867     * @see android.R.attr#windowLightStatusBar
2868     */
2869    public static final int SYSTEM_UI_FLAG_LIGHT_STATUS_BAR = 0x00002000;
2870
2871    /**
2872     * @deprecated Use {@link #SYSTEM_UI_FLAG_LOW_PROFILE} instead.
2873     */
2874    public static final int STATUS_BAR_HIDDEN = SYSTEM_UI_FLAG_LOW_PROFILE;
2875
2876    /**
2877     * @deprecated Use {@link #SYSTEM_UI_FLAG_VISIBLE} instead.
2878     */
2879    public static final int STATUS_BAR_VISIBLE = SYSTEM_UI_FLAG_VISIBLE;
2880
2881    /**
2882     * @hide
2883     *
2884     * NOTE: This flag may only be used in subtreeSystemUiVisibility. It is masked
2885     * out of the public fields to keep the undefined bits out of the developer's way.
2886     *
2887     * Flag to make the status bar not expandable.  Unless you also
2888     * set {@link #STATUS_BAR_DISABLE_NOTIFICATION_ICONS}, new notifications will continue to show.
2889     */
2890    public static final int STATUS_BAR_DISABLE_EXPAND = 0x00010000;
2891
2892    /**
2893     * @hide
2894     *
2895     * NOTE: This flag may only be used in subtreeSystemUiVisibility. It is masked
2896     * out of the public fields to keep the undefined bits out of the developer's way.
2897     *
2898     * Flag to hide notification icons and scrolling ticker text.
2899     */
2900    public static final int STATUS_BAR_DISABLE_NOTIFICATION_ICONS = 0x00020000;
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 disable incoming notification alerts.  This will not block
2909     * icons, but it will block sound, vibrating and other visual or aural notifications.
2910     */
2911    public static final int STATUS_BAR_DISABLE_NOTIFICATION_ALERTS = 0x00040000;
2912
2913    /**
2914     * @hide
2915     *
2916     * NOTE: This flag may only be used in subtreeSystemUiVisibility. It is masked
2917     * out of the public fields to keep the undefined bits out of the developer's way.
2918     *
2919     * Flag to hide only the scrolling ticker.  Note that
2920     * {@link #STATUS_BAR_DISABLE_NOTIFICATION_ICONS} implies
2921     * {@link #STATUS_BAR_DISABLE_NOTIFICATION_TICKER}.
2922     */
2923    public static final int STATUS_BAR_DISABLE_NOTIFICATION_TICKER = 0x00080000;
2924
2925    /**
2926     * @hide
2927     *
2928     * NOTE: This flag may only be used in subtreeSystemUiVisibility. It is masked
2929     * out of the public fields to keep the undefined bits out of the developer's way.
2930     *
2931     * Flag to hide the center system info area.
2932     */
2933    public static final int STATUS_BAR_DISABLE_SYSTEM_INFO = 0x00100000;
2934
2935    /**
2936     * @hide
2937     *
2938     * NOTE: This flag may only be used in subtreeSystemUiVisibility. It is masked
2939     * out of the public fields to keep the undefined bits out of the developer's way.
2940     *
2941     * Flag to hide only the home button.  Don't use this
2942     * unless you're a special part of the system UI (i.e., setup wizard, keyguard).
2943     */
2944    public static final int STATUS_BAR_DISABLE_HOME = 0x00200000;
2945
2946    /**
2947     * @hide
2948     *
2949     * NOTE: This flag may only be used in subtreeSystemUiVisibility. It is masked
2950     * out of the public fields to keep the undefined bits out of the developer's way.
2951     *
2952     * Flag to hide only the back button. Don't use this
2953     * unless you're a special part of the system UI (i.e., setup wizard, keyguard).
2954     */
2955    public static final int STATUS_BAR_DISABLE_BACK = 0x00400000;
2956
2957    /**
2958     * @hide
2959     *
2960     * NOTE: This flag may only be used in subtreeSystemUiVisibility. It is masked
2961     * out of the public fields to keep the undefined bits out of the developer's way.
2962     *
2963     * Flag to hide only the clock.  You might use this if your activity has
2964     * its own clock making the status bar's clock redundant.
2965     */
2966    public static final int STATUS_BAR_DISABLE_CLOCK = 0x00800000;
2967
2968    /**
2969     * @hide
2970     *
2971     * NOTE: This flag may only be used in subtreeSystemUiVisibility. It is masked
2972     * out of the public fields to keep the undefined bits out of the developer's way.
2973     *
2974     * Flag to hide only the recent apps button. Don't use this
2975     * unless you're a special part of the system UI (i.e., setup wizard, keyguard).
2976     */
2977    public static final int STATUS_BAR_DISABLE_RECENT = 0x01000000;
2978
2979    /**
2980     * @hide
2981     *
2982     * NOTE: This flag may only be used in subtreeSystemUiVisibility. It is masked
2983     * out of the public fields to keep the undefined bits out of the developer's way.
2984     *
2985     * Flag to disable the global search gesture. Don't use this
2986     * unless you're a special part of the system UI (i.e., setup wizard, keyguard).
2987     */
2988    public static final int STATUS_BAR_DISABLE_SEARCH = 0x02000000;
2989
2990    /**
2991     * @hide
2992     *
2993     * NOTE: This flag may only be used in subtreeSystemUiVisibility. It is masked
2994     * out of the public fields to keep the undefined bits out of the developer's way.
2995     *
2996     * Flag to specify that the status bar is displayed in transient mode.
2997     */
2998    public static final int STATUS_BAR_TRANSIENT = 0x04000000;
2999
3000    /**
3001     * @hide
3002     *
3003     * NOTE: This flag may only be used in subtreeSystemUiVisibility. It is masked
3004     * out of the public fields to keep the undefined bits out of the developer's way.
3005     *
3006     * Flag to specify that the navigation bar is displayed in transient mode.
3007     */
3008    public static final int NAVIGATION_BAR_TRANSIENT = 0x08000000;
3009
3010    /**
3011     * @hide
3012     *
3013     * NOTE: This flag may only be used in subtreeSystemUiVisibility. It is masked
3014     * out of the public fields to keep the undefined bits out of the developer's way.
3015     *
3016     * Flag to specify that the hidden status bar would like to be shown.
3017     */
3018    public static final int STATUS_BAR_UNHIDE = 0x10000000;
3019
3020    /**
3021     * @hide
3022     *
3023     * NOTE: This flag may only be used in subtreeSystemUiVisibility. It is masked
3024     * out of the public fields to keep the undefined bits out of the developer's way.
3025     *
3026     * Flag to specify that the hidden navigation bar would like to be shown.
3027     */
3028    public static final int NAVIGATION_BAR_UNHIDE = 0x20000000;
3029
3030    /**
3031     * @hide
3032     *
3033     * NOTE: This flag may only be used in subtreeSystemUiVisibility. It is masked
3034     * out of the public fields to keep the undefined bits out of the developer's way.
3035     *
3036     * Flag to specify that the status bar is displayed in translucent mode.
3037     */
3038    public static final int STATUS_BAR_TRANSLUCENT = 0x40000000;
3039
3040    /**
3041     * @hide
3042     *
3043     * NOTE: This flag may only be used in subtreeSystemUiVisibility. It is masked
3044     * out of the public fields to keep the undefined bits out of the developer's way.
3045     *
3046     * Flag to specify that the navigation bar is displayed in translucent mode.
3047     */
3048    public static final int NAVIGATION_BAR_TRANSLUCENT = 0x80000000;
3049
3050    /**
3051     * @hide
3052     *
3053     * Whether Recents is visible or not.
3054     */
3055    public static final int RECENT_APPS_VISIBLE = 0x00004000;
3056
3057    /**
3058     * @hide
3059     *
3060     * Makes navigation bar transparent (but not the status bar).
3061     */
3062    public static final int NAVIGATION_BAR_TRANSPARENT = 0x00008000;
3063
3064    /**
3065     * @hide
3066     *
3067     * Makes status bar transparent (but not the navigation bar).
3068     */
3069    public static final int STATUS_BAR_TRANSPARENT = 0x0000008;
3070
3071    /**
3072     * @hide
3073     *
3074     * Makes both status bar and navigation bar transparent.
3075     */
3076    public static final int SYSTEM_UI_TRANSPARENT = NAVIGATION_BAR_TRANSPARENT
3077            | STATUS_BAR_TRANSPARENT;
3078
3079    /**
3080     * @hide
3081     */
3082    public static final int PUBLIC_STATUS_BAR_VISIBILITY_MASK = 0x00003FF7;
3083
3084    /**
3085     * These are the system UI flags that can be cleared by events outside
3086     * of an application.  Currently this is just the ability to tap on the
3087     * screen while hiding the navigation bar to have it return.
3088     * @hide
3089     */
3090    public static final int SYSTEM_UI_CLEARABLE_FLAGS =
3091            SYSTEM_UI_FLAG_LOW_PROFILE | SYSTEM_UI_FLAG_HIDE_NAVIGATION
3092            | SYSTEM_UI_FLAG_FULLSCREEN;
3093
3094    /**
3095     * Flags that can impact the layout in relation to system UI.
3096     */
3097    public static final int SYSTEM_UI_LAYOUT_FLAGS =
3098            SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION
3099            | SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN;
3100
3101    /** @hide */
3102    @IntDef(flag = true,
3103            value = { FIND_VIEWS_WITH_TEXT, FIND_VIEWS_WITH_CONTENT_DESCRIPTION })
3104    @Retention(RetentionPolicy.SOURCE)
3105    public @interface FindViewFlags {}
3106
3107    /**
3108     * Find views that render the specified text.
3109     *
3110     * @see #findViewsWithText(ArrayList, CharSequence, int)
3111     */
3112    public static final int FIND_VIEWS_WITH_TEXT = 0x00000001;
3113
3114    /**
3115     * Find find views that contain the specified content description.
3116     *
3117     * @see #findViewsWithText(ArrayList, CharSequence, int)
3118     */
3119    public static final int FIND_VIEWS_WITH_CONTENT_DESCRIPTION = 0x00000002;
3120
3121    /**
3122     * Find views that contain {@link AccessibilityNodeProvider}. Such
3123     * a View is a root of virtual view hierarchy and may contain the searched
3124     * text. If this flag is set Views with providers are automatically
3125     * added and it is a responsibility of the client to call the APIs of
3126     * the provider to determine whether the virtual tree rooted at this View
3127     * contains the text, i.e. getting the list of {@link AccessibilityNodeInfo}s
3128     * representing the virtual views with this text.
3129     *
3130     * @see #findViewsWithText(ArrayList, CharSequence, int)
3131     *
3132     * @hide
3133     */
3134    public static final int FIND_VIEWS_WITH_ACCESSIBILITY_NODE_PROVIDERS = 0x00000004;
3135
3136    /**
3137     * The undefined cursor position.
3138     *
3139     * @hide
3140     */
3141    public static final int ACCESSIBILITY_CURSOR_POSITION_UNDEFINED = -1;
3142
3143    /**
3144     * Indicates that the screen has changed state and is now off.
3145     *
3146     * @see #onScreenStateChanged(int)
3147     */
3148    public static final int SCREEN_STATE_OFF = 0x0;
3149
3150    /**
3151     * Indicates that the screen has changed state and is now on.
3152     *
3153     * @see #onScreenStateChanged(int)
3154     */
3155    public static final int SCREEN_STATE_ON = 0x1;
3156
3157    /**
3158     * Indicates no axis of view scrolling.
3159     */
3160    public static final int SCROLL_AXIS_NONE = 0;
3161
3162    /**
3163     * Indicates scrolling along the horizontal axis.
3164     */
3165    public static final int SCROLL_AXIS_HORIZONTAL = 1 << 0;
3166
3167    /**
3168     * Indicates scrolling along the vertical axis.
3169     */
3170    public static final int SCROLL_AXIS_VERTICAL = 1 << 1;
3171
3172    /**
3173     * Controls the over-scroll mode for this view.
3174     * See {@link #overScrollBy(int, int, int, int, int, int, int, int, boolean)},
3175     * {@link #OVER_SCROLL_ALWAYS}, {@link #OVER_SCROLL_IF_CONTENT_SCROLLS},
3176     * and {@link #OVER_SCROLL_NEVER}.
3177     */
3178    private int mOverScrollMode;
3179
3180    /**
3181     * The parent this view is attached to.
3182     * {@hide}
3183     *
3184     * @see #getParent()
3185     */
3186    protected ViewParent mParent;
3187
3188    /**
3189     * {@hide}
3190     */
3191    AttachInfo mAttachInfo;
3192
3193    /**
3194     * {@hide}
3195     */
3196    @ViewDebug.ExportedProperty(flagMapping = {
3197        @ViewDebug.FlagToString(mask = PFLAG_FORCE_LAYOUT, equals = PFLAG_FORCE_LAYOUT,
3198                name = "FORCE_LAYOUT"),
3199        @ViewDebug.FlagToString(mask = PFLAG_LAYOUT_REQUIRED, equals = PFLAG_LAYOUT_REQUIRED,
3200                name = "LAYOUT_REQUIRED"),
3201        @ViewDebug.FlagToString(mask = PFLAG_DRAWING_CACHE_VALID, equals = PFLAG_DRAWING_CACHE_VALID,
3202            name = "DRAWING_CACHE_INVALID", outputIf = false),
3203        @ViewDebug.FlagToString(mask = PFLAG_DRAWN, equals = PFLAG_DRAWN, name = "DRAWN", outputIf = true),
3204        @ViewDebug.FlagToString(mask = PFLAG_DRAWN, equals = PFLAG_DRAWN, name = "NOT_DRAWN", outputIf = false),
3205        @ViewDebug.FlagToString(mask = PFLAG_DIRTY_MASK, equals = PFLAG_DIRTY_OPAQUE, name = "DIRTY_OPAQUE"),
3206        @ViewDebug.FlagToString(mask = PFLAG_DIRTY_MASK, equals = PFLAG_DIRTY, name = "DIRTY")
3207    }, formatToHexString = true)
3208    int mPrivateFlags;
3209    int mPrivateFlags2;
3210    int mPrivateFlags3;
3211
3212    /**
3213     * This view's request for the visibility of the status bar.
3214     * @hide
3215     */
3216    @ViewDebug.ExportedProperty(flagMapping = {
3217        @ViewDebug.FlagToString(mask = SYSTEM_UI_FLAG_LOW_PROFILE,
3218                                equals = SYSTEM_UI_FLAG_LOW_PROFILE,
3219                                name = "SYSTEM_UI_FLAG_LOW_PROFILE", outputIf = true),
3220        @ViewDebug.FlagToString(mask = SYSTEM_UI_FLAG_HIDE_NAVIGATION,
3221                                equals = SYSTEM_UI_FLAG_HIDE_NAVIGATION,
3222                                name = "SYSTEM_UI_FLAG_HIDE_NAVIGATION", outputIf = true),
3223        @ViewDebug.FlagToString(mask = PUBLIC_STATUS_BAR_VISIBILITY_MASK,
3224                                equals = SYSTEM_UI_FLAG_VISIBLE,
3225                                name = "SYSTEM_UI_FLAG_VISIBLE", outputIf = true)
3226    }, formatToHexString = true)
3227    int mSystemUiVisibility;
3228
3229    /**
3230     * Reference count for transient state.
3231     * @see #setHasTransientState(boolean)
3232     */
3233    int mTransientStateCount = 0;
3234
3235    /**
3236     * Count of how many windows this view has been attached to.
3237     */
3238    int mWindowAttachCount;
3239
3240    /**
3241     * The layout parameters associated with this view and used by the parent
3242     * {@link android.view.ViewGroup} to determine how this view should be
3243     * laid out.
3244     * {@hide}
3245     */
3246    protected ViewGroup.LayoutParams mLayoutParams;
3247
3248    /**
3249     * The view flags hold various views states.
3250     * {@hide}
3251     */
3252    @ViewDebug.ExportedProperty(formatToHexString = true)
3253    int mViewFlags;
3254
3255    static class TransformationInfo {
3256        /**
3257         * The transform matrix for the View. This transform is calculated internally
3258         * based on the translation, rotation, and scale properties.
3259         *
3260         * Do *not* use this variable directly; instead call getMatrix(), which will
3261         * load the value from the View's RenderNode.
3262         */
3263        private final Matrix mMatrix = new Matrix();
3264
3265        /**
3266         * The inverse transform matrix for the View. This transform is calculated
3267         * internally based on the translation, rotation, and scale properties.
3268         *
3269         * Do *not* use this variable directly; instead call getInverseMatrix(),
3270         * which will load the value from the View's RenderNode.
3271         */
3272        private Matrix mInverseMatrix;
3273
3274        /**
3275         * The opacity of the View. This is a value from 0 to 1, where 0 means
3276         * completely transparent and 1 means completely opaque.
3277         */
3278        @ViewDebug.ExportedProperty
3279        float mAlpha = 1f;
3280
3281        /**
3282         * The opacity of the view as manipulated by the Fade transition. This is a hidden
3283         * property only used by transitions, which is composited with the other alpha
3284         * values to calculate the final visual alpha value.
3285         */
3286        float mTransitionAlpha = 1f;
3287    }
3288
3289    TransformationInfo mTransformationInfo;
3290
3291    /**
3292     * Current clip bounds. to which all drawing of this view are constrained.
3293     */
3294    Rect mClipBounds = null;
3295
3296    private boolean mLastIsOpaque;
3297
3298    /**
3299     * The distance in pixels from the left edge of this view's parent
3300     * to the left edge of this view.
3301     * {@hide}
3302     */
3303    @ViewDebug.ExportedProperty(category = "layout")
3304    protected int mLeft;
3305    /**
3306     * The distance in pixels from the left edge of this view's parent
3307     * to the right edge of this view.
3308     * {@hide}
3309     */
3310    @ViewDebug.ExportedProperty(category = "layout")
3311    protected int mRight;
3312    /**
3313     * The distance in pixels from the top edge of this view's parent
3314     * to the top edge of this view.
3315     * {@hide}
3316     */
3317    @ViewDebug.ExportedProperty(category = "layout")
3318    protected int mTop;
3319    /**
3320     * The distance in pixels from the top edge of this view's parent
3321     * to the bottom edge of this view.
3322     * {@hide}
3323     */
3324    @ViewDebug.ExportedProperty(category = "layout")
3325    protected int mBottom;
3326
3327    /**
3328     * The offset, in pixels, by which the content of this view is scrolled
3329     * horizontally.
3330     * {@hide}
3331     */
3332    @ViewDebug.ExportedProperty(category = "scrolling")
3333    protected int mScrollX;
3334    /**
3335     * The offset, in pixels, by which the content of this view is scrolled
3336     * vertically.
3337     * {@hide}
3338     */
3339    @ViewDebug.ExportedProperty(category = "scrolling")
3340    protected int mScrollY;
3341
3342    /**
3343     * The left padding in pixels, that is the distance in pixels between the
3344     * left edge of this view and the left edge of its content.
3345     * {@hide}
3346     */
3347    @ViewDebug.ExportedProperty(category = "padding")
3348    protected int mPaddingLeft = 0;
3349    /**
3350     * The right padding in pixels, that is the distance in pixels between the
3351     * right edge of this view and the right edge of its content.
3352     * {@hide}
3353     */
3354    @ViewDebug.ExportedProperty(category = "padding")
3355    protected int mPaddingRight = 0;
3356    /**
3357     * The top padding in pixels, that is the distance in pixels between the
3358     * top edge of this view and the top edge of its content.
3359     * {@hide}
3360     */
3361    @ViewDebug.ExportedProperty(category = "padding")
3362    protected int mPaddingTop;
3363    /**
3364     * The bottom padding in pixels, that is the distance in pixels between the
3365     * bottom edge of this view and the bottom edge of its content.
3366     * {@hide}
3367     */
3368    @ViewDebug.ExportedProperty(category = "padding")
3369    protected int mPaddingBottom;
3370
3371    /**
3372     * The layout insets in pixels, that is the distance in pixels between the
3373     * visible edges of this view its bounds.
3374     */
3375    private Insets mLayoutInsets;
3376
3377    /**
3378     * Briefly describes the view and is primarily used for accessibility support.
3379     */
3380    private CharSequence mContentDescription;
3381
3382    /**
3383     * Specifies the id of a view for which this view serves as a label for
3384     * accessibility purposes.
3385     */
3386    private int mLabelForId = View.NO_ID;
3387
3388    /**
3389     * Predicate for matching labeled view id with its label for
3390     * accessibility purposes.
3391     */
3392    private MatchLabelForPredicate mMatchLabelForPredicate;
3393
3394    /**
3395     * Specifies a view before which this one is visited in accessibility traversal.
3396     */
3397    private int mAccessibilityTraversalBeforeId = NO_ID;
3398
3399    /**
3400     * Specifies a view after which this one is visited in accessibility traversal.
3401     */
3402    private int mAccessibilityTraversalAfterId = NO_ID;
3403
3404    /**
3405     * Predicate for matching a view by its id.
3406     */
3407    private MatchIdPredicate mMatchIdPredicate;
3408
3409    /**
3410     * Cache the paddingRight set by the user to append to the scrollbar's size.
3411     *
3412     * @hide
3413     */
3414    @ViewDebug.ExportedProperty(category = "padding")
3415    protected int mUserPaddingRight;
3416
3417    /**
3418     * Cache the paddingBottom set by the user to append to the scrollbar's size.
3419     *
3420     * @hide
3421     */
3422    @ViewDebug.ExportedProperty(category = "padding")
3423    protected int mUserPaddingBottom;
3424
3425    /**
3426     * Cache the paddingLeft set by the user to append to the scrollbar's size.
3427     *
3428     * @hide
3429     */
3430    @ViewDebug.ExportedProperty(category = "padding")
3431    protected int mUserPaddingLeft;
3432
3433    /**
3434     * Cache the paddingStart set by the user to append to the scrollbar's size.
3435     *
3436     */
3437    @ViewDebug.ExportedProperty(category = "padding")
3438    int mUserPaddingStart;
3439
3440    /**
3441     * Cache the paddingEnd set by the user to append to the scrollbar's size.
3442     *
3443     */
3444    @ViewDebug.ExportedProperty(category = "padding")
3445    int mUserPaddingEnd;
3446
3447    /**
3448     * Cache initial left padding.
3449     *
3450     * @hide
3451     */
3452    int mUserPaddingLeftInitial;
3453
3454    /**
3455     * Cache initial right padding.
3456     *
3457     * @hide
3458     */
3459    int mUserPaddingRightInitial;
3460
3461    /**
3462     * Default undefined padding
3463     */
3464    private static final int UNDEFINED_PADDING = Integer.MIN_VALUE;
3465
3466    /**
3467     * Cache if a left padding has been defined
3468     */
3469    private boolean mLeftPaddingDefined = false;
3470
3471    /**
3472     * Cache if a right padding has been defined
3473     */
3474    private boolean mRightPaddingDefined = false;
3475
3476    /**
3477     * @hide
3478     */
3479    int mOldWidthMeasureSpec = Integer.MIN_VALUE;
3480    /**
3481     * @hide
3482     */
3483    int mOldHeightMeasureSpec = Integer.MIN_VALUE;
3484
3485    private LongSparseLongArray mMeasureCache;
3486
3487    @ViewDebug.ExportedProperty(deepExport = true, prefix = "bg_")
3488    private Drawable mBackground;
3489    private TintInfo mBackgroundTint;
3490
3491    @ViewDebug.ExportedProperty(deepExport = true, prefix = "fg_")
3492    private ForegroundInfo mForegroundInfo;
3493
3494    private Drawable mScrollIndicatorDrawable;
3495
3496    /**
3497     * RenderNode used for backgrounds.
3498     * <p>
3499     * When non-null and valid, this is expected to contain an up-to-date copy
3500     * of the background drawable. It is cleared on temporary detach, and reset
3501     * on cleanup.
3502     */
3503    private RenderNode mBackgroundRenderNode;
3504
3505    private int mBackgroundResource;
3506    private boolean mBackgroundSizeChanged;
3507
3508    private String mTransitionName;
3509
3510    static class TintInfo {
3511        ColorStateList mTintList;
3512        PorterDuff.Mode mTintMode;
3513        boolean mHasTintMode;
3514        boolean mHasTintList;
3515    }
3516
3517    private static class ForegroundInfo {
3518        private Drawable mDrawable;
3519        private TintInfo mTintInfo;
3520        private int mGravity = Gravity.FILL;
3521        private boolean mInsidePadding = true;
3522        private boolean mBoundsChanged = true;
3523        private final Rect mSelfBounds = new Rect();
3524        private final Rect mOverlayBounds = new Rect();
3525    }
3526
3527    static class ListenerInfo {
3528        /**
3529         * Listener used to dispatch focus change events.
3530         * This field should be made private, so it is hidden from the SDK.
3531         * {@hide}
3532         */
3533        protected OnFocusChangeListener mOnFocusChangeListener;
3534
3535        /**
3536         * Listeners for layout change events.
3537         */
3538        private ArrayList<OnLayoutChangeListener> mOnLayoutChangeListeners;
3539
3540        protected OnScrollChangeListener mOnScrollChangeListener;
3541
3542        /**
3543         * Listeners for attach events.
3544         */
3545        private CopyOnWriteArrayList<OnAttachStateChangeListener> mOnAttachStateChangeListeners;
3546
3547        /**
3548         * Listener used to dispatch click events.
3549         * This field should be made private, so it is hidden from the SDK.
3550         * {@hide}
3551         */
3552        public OnClickListener mOnClickListener;
3553
3554        /**
3555         * Listener used to dispatch long click events.
3556         * This field should be made private, so it is hidden from the SDK.
3557         * {@hide}
3558         */
3559        protected OnLongClickListener mOnLongClickListener;
3560
3561        /**
3562         * Listener used to dispatch context click events. This field should be made private, so it
3563         * is hidden from the SDK.
3564         * {@hide}
3565         */
3566        protected OnContextClickListener mOnContextClickListener;
3567
3568        /**
3569         * Listener used to build the context menu.
3570         * This field should be made private, so it is hidden from the SDK.
3571         * {@hide}
3572         */
3573        protected OnCreateContextMenuListener mOnCreateContextMenuListener;
3574
3575        private OnKeyListener mOnKeyListener;
3576
3577        private OnTouchListener mOnTouchListener;
3578
3579        private OnHoverListener mOnHoverListener;
3580
3581        private OnGenericMotionListener mOnGenericMotionListener;
3582
3583        private OnDragListener mOnDragListener;
3584
3585        private OnSystemUiVisibilityChangeListener mOnSystemUiVisibilityChangeListener;
3586
3587        OnApplyWindowInsetsListener mOnApplyWindowInsetsListener;
3588    }
3589
3590    ListenerInfo mListenerInfo;
3591
3592    // Temporary values used to hold (x,y) coordinates when delegating from the
3593    // two-arg performLongClick() method to the legacy no-arg version.
3594    private float mLongClickX = Float.NaN;
3595    private float mLongClickY = Float.NaN;
3596
3597    /**
3598     * The application environment this view lives in.
3599     * This field should be made private, so it is hidden from the SDK.
3600     * {@hide}
3601     */
3602    @ViewDebug.ExportedProperty(deepExport = true)
3603    protected Context mContext;
3604
3605    private final Resources mResources;
3606
3607    private ScrollabilityCache mScrollCache;
3608
3609    private int[] mDrawableState = null;
3610
3611    ViewOutlineProvider mOutlineProvider = ViewOutlineProvider.BACKGROUND;
3612
3613    /**
3614     * Animator that automatically runs based on state changes.
3615     */
3616    private StateListAnimator mStateListAnimator;
3617
3618    /**
3619     * When this view has focus and the next focus is {@link #FOCUS_LEFT},
3620     * the user may specify which view to go to next.
3621     */
3622    private int mNextFocusLeftId = View.NO_ID;
3623
3624    /**
3625     * When this view has focus and the next focus is {@link #FOCUS_RIGHT},
3626     * the user may specify which view to go to next.
3627     */
3628    private int mNextFocusRightId = View.NO_ID;
3629
3630    /**
3631     * When this view has focus and the next focus is {@link #FOCUS_UP},
3632     * the user may specify which view to go to next.
3633     */
3634    private int mNextFocusUpId = View.NO_ID;
3635
3636    /**
3637     * When this view has focus and the next focus is {@link #FOCUS_DOWN},
3638     * the user may specify which view to go to next.
3639     */
3640    private int mNextFocusDownId = View.NO_ID;
3641
3642    /**
3643     * When this view has focus and the next focus is {@link #FOCUS_FORWARD},
3644     * the user may specify which view to go to next.
3645     */
3646    int mNextFocusForwardId = View.NO_ID;
3647
3648    private CheckForLongPress mPendingCheckForLongPress;
3649    private CheckForTap mPendingCheckForTap = null;
3650    private PerformClick mPerformClick;
3651    private SendViewScrolledAccessibilityEvent mSendViewScrolledAccessibilityEvent;
3652
3653    private UnsetPressedState mUnsetPressedState;
3654
3655    /**
3656     * Whether the long press's action has been invoked.  The tap's action is invoked on the
3657     * up event while a long press is invoked as soon as the long press duration is reached, so
3658     * a long press could be performed before the tap is checked, in which case the tap's action
3659     * should not be invoked.
3660     */
3661    private boolean mHasPerformedLongPress;
3662
3663    /**
3664     * Whether a context click button is currently pressed down. This is true when the stylus is
3665     * touching the screen and the primary button has been pressed, or if a mouse's right button is
3666     * pressed. This is false once the button is released or if the stylus has been lifted.
3667     */
3668    private boolean mInContextButtonPress;
3669
3670    /**
3671     * Whether the next up event should be ignored for the purposes of gesture recognition. This is
3672     * true after a stylus button press has occured, when the next up event should not be recognized
3673     * as a tap.
3674     */
3675    private boolean mIgnoreNextUpEvent;
3676
3677    /**
3678     * The minimum height of the view. We'll try our best to have the height
3679     * of this view to at least this amount.
3680     */
3681    @ViewDebug.ExportedProperty(category = "measurement")
3682    private int mMinHeight;
3683
3684    /**
3685     * The minimum width of the view. We'll try our best to have the width
3686     * of this view to at least this amount.
3687     */
3688    @ViewDebug.ExportedProperty(category = "measurement")
3689    private int mMinWidth;
3690
3691    /**
3692     * The delegate to handle touch events that are physically in this view
3693     * but should be handled by another view.
3694     */
3695    private TouchDelegate mTouchDelegate = null;
3696
3697    /**
3698     * Solid color to use as a background when creating the drawing cache. Enables
3699     * the cache to use 16 bit bitmaps instead of 32 bit.
3700     */
3701    private int mDrawingCacheBackgroundColor = 0;
3702
3703    /**
3704     * Special tree observer used when mAttachInfo is null.
3705     */
3706    private ViewTreeObserver mFloatingTreeObserver;
3707
3708    /**
3709     * Cache the touch slop from the context that created the view.
3710     */
3711    private int mTouchSlop;
3712
3713    /**
3714     * Object that handles automatic animation of view properties.
3715     */
3716    private ViewPropertyAnimator mAnimator = null;
3717
3718    /**
3719     * Flag indicating that a drag can cross window boundaries.  When
3720     * {@link #startDragAndDrop(ClipData, DragShadowBuilder, Object, int)} is called
3721     * with this flag set, all visible applications will be able to participate
3722     * in the drag operation and receive the dragged content.
3723     *
3724     * If this is the only flag set, then the drag recipient will only have access to text data
3725     * and intents contained in the {@link ClipData} object. Access to URIs contained in the
3726     * {@link ClipData} is determined by other DRAG_FLAG_GLOBAL_* flags.
3727     */
3728    public static final int DRAG_FLAG_GLOBAL = 1 << 8;  // 256
3729
3730    /**
3731     * When this flag is used with {@link #DRAG_FLAG_GLOBAL}, the drag recipient will be able to
3732     * request read access to the content URI(s) contained in the {@link ClipData} object.
3733     * @see android.content.Intent.FLAG_GRANT_READ_URI_PERMISSION
3734     */
3735    public static final int DRAG_FLAG_GLOBAL_URI_READ = Intent.FLAG_GRANT_READ_URI_PERMISSION;
3736
3737    /**
3738     * When this flag is used with {@link #DRAG_FLAG_GLOBAL}, the drag recipient will be able to
3739     * request write access to the content URI(s) contained in the {@link ClipData} object.
3740     * @see android.content.Intent.FLAG_GRANT_WRITE_URI_PERMISSION
3741     */
3742    public static final int DRAG_FLAG_GLOBAL_URI_WRITE = Intent.FLAG_GRANT_WRITE_URI_PERMISSION;
3743
3744    /**
3745     * When this flag is used with {@link #DRAG_FLAG_GLOBAL_URI_READ} and/or {@link
3746     * #DRAG_FLAG_GLOBAL_URI_WRITE}, the URI permission grant can be persisted across device
3747     * reboots until explicitly revoked with
3748     * {@link android.content.Context#revokeUriPermission(Uri,int) Context.revokeUriPermission}.
3749     * @see android.content.Intent.FLAG_GRANT_PERSISTABLE_URI_PERMISSION
3750     */
3751    public static final int DRAG_FLAG_GLOBAL_PERSISTABLE_URI_PERMISSION =
3752            Intent.FLAG_GRANT_PERSISTABLE_URI_PERMISSION;
3753
3754    /**
3755     * When this flag is used with {@link #DRAG_FLAG_GLOBAL_URI_READ} and/or {@link
3756     * #DRAG_FLAG_GLOBAL_URI_WRITE}, the URI permission grant applies to any URI that is a prefix
3757     * match against the original granted URI.
3758     * @see android.content.Intent.FLAG_GRANT_PREFIX_URI_PERMISSION
3759     */
3760    public static final int DRAG_FLAG_GLOBAL_PREFIX_URI_PERMISSION =
3761            Intent.FLAG_GRANT_PREFIX_URI_PERMISSION;
3762
3763    /**
3764     * Flag indicating that the drag shadow will be opaque.  When
3765     * {@link #startDragAndDrop(ClipData, DragShadowBuilder, Object, int)} is called
3766     * with this flag set, the drag shadow will be opaque, otherwise, it will be semitransparent.
3767     */
3768    public static final int DRAG_FLAG_OPAQUE = 1 << 9;
3769
3770    /**
3771     * Vertical scroll factor cached by {@link #getVerticalScrollFactor}.
3772     */
3773    private float mVerticalScrollFactor;
3774
3775    /**
3776     * Position of the vertical scroll bar.
3777     */
3778    private int mVerticalScrollbarPosition;
3779
3780    /**
3781     * Position the scroll bar at the default position as determined by the system.
3782     */
3783    public static final int SCROLLBAR_POSITION_DEFAULT = 0;
3784
3785    /**
3786     * Position the scroll bar along the left edge.
3787     */
3788    public static final int SCROLLBAR_POSITION_LEFT = 1;
3789
3790    /**
3791     * Position the scroll bar along the right edge.
3792     */
3793    public static final int SCROLLBAR_POSITION_RIGHT = 2;
3794
3795    /**
3796     * Indicates that the view does not have a layer.
3797     *
3798     * @see #getLayerType()
3799     * @see #setLayerType(int, android.graphics.Paint)
3800     * @see #LAYER_TYPE_SOFTWARE
3801     * @see #LAYER_TYPE_HARDWARE
3802     */
3803    public static final int LAYER_TYPE_NONE = 0;
3804
3805    /**
3806     * <p>Indicates that the view has a software layer. A software layer is backed
3807     * by a bitmap and causes the view to be rendered using Android's software
3808     * rendering pipeline, even if hardware acceleration is enabled.</p>
3809     *
3810     * <p>Software layers have various usages:</p>
3811     * <p>When the application is not using hardware acceleration, a software layer
3812     * is useful to apply a specific color filter and/or blending mode and/or
3813     * translucency to a view and all its children.</p>
3814     * <p>When the application is using hardware acceleration, a software layer
3815     * is useful to render drawing primitives not supported by the hardware
3816     * accelerated pipeline. It can also be used to cache a complex view tree
3817     * into a texture and reduce the complexity of drawing operations. For instance,
3818     * when animating a complex view tree with a translation, a software layer can
3819     * be used to render the view tree only once.</p>
3820     * <p>Software layers should be avoided when the affected view tree updates
3821     * often. Every update will require to re-render the software layer, which can
3822     * potentially be slow (particularly when hardware acceleration is turned on
3823     * since the layer will have to be uploaded into a hardware texture after every
3824     * update.)</p>
3825     *
3826     * @see #getLayerType()
3827     * @see #setLayerType(int, android.graphics.Paint)
3828     * @see #LAYER_TYPE_NONE
3829     * @see #LAYER_TYPE_HARDWARE
3830     */
3831    public static final int LAYER_TYPE_SOFTWARE = 1;
3832
3833    /**
3834     * <p>Indicates that the view has a hardware layer. A hardware layer is backed
3835     * by a hardware specific texture (generally Frame Buffer Objects or FBO on
3836     * OpenGL hardware) and causes the view to be rendered using Android's hardware
3837     * rendering pipeline, but only if hardware acceleration is turned on for the
3838     * view hierarchy. When hardware acceleration is turned off, hardware layers
3839     * behave exactly as {@link #LAYER_TYPE_SOFTWARE software layers}.</p>
3840     *
3841     * <p>A hardware layer is useful to apply a specific color filter and/or
3842     * blending mode and/or translucency to a view and all its children.</p>
3843     * <p>A hardware layer can be used to cache a complex view tree into a
3844     * texture and reduce the complexity of drawing operations. For instance,
3845     * when animating a complex view tree with a translation, a hardware layer can
3846     * be used to render the view tree only once.</p>
3847     * <p>A hardware layer can also be used to increase the rendering quality when
3848     * rotation transformations are applied on a view. It can also be used to
3849     * prevent potential clipping issues when applying 3D transforms on a view.</p>
3850     *
3851     * @see #getLayerType()
3852     * @see #setLayerType(int, android.graphics.Paint)
3853     * @see #LAYER_TYPE_NONE
3854     * @see #LAYER_TYPE_SOFTWARE
3855     */
3856    public static final int LAYER_TYPE_HARDWARE = 2;
3857
3858    @ViewDebug.ExportedProperty(category = "drawing", mapping = {
3859            @ViewDebug.IntToString(from = LAYER_TYPE_NONE, to = "NONE"),
3860            @ViewDebug.IntToString(from = LAYER_TYPE_SOFTWARE, to = "SOFTWARE"),
3861            @ViewDebug.IntToString(from = LAYER_TYPE_HARDWARE, to = "HARDWARE")
3862    })
3863    int mLayerType = LAYER_TYPE_NONE;
3864    Paint mLayerPaint;
3865
3866    /**
3867     * Set to true when drawing cache is enabled and cannot be created.
3868     *
3869     * @hide
3870     */
3871    public boolean mCachingFailed;
3872    private Bitmap mDrawingCache;
3873    private Bitmap mUnscaledDrawingCache;
3874
3875    /**
3876     * RenderNode holding View properties, potentially holding a DisplayList of View content.
3877     * <p>
3878     * When non-null and valid, this is expected to contain an up-to-date copy
3879     * of the View content. Its DisplayList content is cleared on temporary detach and reset on
3880     * cleanup.
3881     */
3882    final RenderNode mRenderNode;
3883
3884    /**
3885     * Set to true when the view is sending hover accessibility events because it
3886     * is the innermost hovered view.
3887     */
3888    private boolean mSendingHoverAccessibilityEvents;
3889
3890    /**
3891     * Delegate for injecting accessibility functionality.
3892     */
3893    AccessibilityDelegate mAccessibilityDelegate;
3894
3895    /**
3896     * The view's overlay layer. Developers get a reference to the overlay via getOverlay()
3897     * and add/remove objects to/from the overlay directly through the Overlay methods.
3898     */
3899    ViewOverlay mOverlay;
3900
3901    /**
3902     * The currently active parent view for receiving delegated nested scrolling events.
3903     * This is set by {@link #startNestedScroll(int)} during a touch interaction and cleared
3904     * by {@link #stopNestedScroll()} at the same point where we clear
3905     * requestDisallowInterceptTouchEvent.
3906     */
3907    private ViewParent mNestedScrollingParent;
3908
3909    /**
3910     * Consistency verifier for debugging purposes.
3911     * @hide
3912     */
3913    protected final InputEventConsistencyVerifier mInputEventConsistencyVerifier =
3914            InputEventConsistencyVerifier.isInstrumentationEnabled() ?
3915                    new InputEventConsistencyVerifier(this, 0) : null;
3916
3917    private static final AtomicInteger sNextGeneratedId = new AtomicInteger(1);
3918
3919    private int[] mTempNestedScrollConsumed;
3920
3921    /**
3922     * An overlay is going to draw this View instead of being drawn as part of this
3923     * View's parent. mGhostView is the View in the Overlay that must be invalidated
3924     * when this view is invalidated.
3925     */
3926    GhostView mGhostView;
3927
3928    /**
3929     * Holds pairs of adjacent attribute data: attribute name followed by its value.
3930     * @hide
3931     */
3932    @ViewDebug.ExportedProperty(category = "attributes", hasAdjacentMapping = true)
3933    public String[] mAttributes;
3934
3935    /**
3936     * Maps a Resource id to its name.
3937     */
3938    private static SparseArray<String> mAttributeMap;
3939
3940    /**
3941     * Queue of pending runnables. Used to postpone calls to post() until this
3942     * view is attached and has a handler.
3943     */
3944    private HandlerActionQueue mRunQueue;
3945
3946    /**
3947     * @hide
3948     */
3949    String mStartActivityRequestWho;
3950
3951    /**
3952     * Simple constructor to use when creating a view from code.
3953     *
3954     * @param context The Context the view is running in, through which it can
3955     *        access the current theme, resources, etc.
3956     */
3957    public View(Context context) {
3958        mContext = context;
3959        mResources = context != null ? context.getResources() : null;
3960        mViewFlags = SOUND_EFFECTS_ENABLED | HAPTIC_FEEDBACK_ENABLED;
3961        // Set some flags defaults
3962        mPrivateFlags2 =
3963                (LAYOUT_DIRECTION_DEFAULT << PFLAG2_LAYOUT_DIRECTION_MASK_SHIFT) |
3964                (TEXT_DIRECTION_DEFAULT << PFLAG2_TEXT_DIRECTION_MASK_SHIFT) |
3965                (PFLAG2_TEXT_DIRECTION_RESOLVED_DEFAULT) |
3966                (TEXT_ALIGNMENT_DEFAULT << PFLAG2_TEXT_ALIGNMENT_MASK_SHIFT) |
3967                (PFLAG2_TEXT_ALIGNMENT_RESOLVED_DEFAULT) |
3968                (IMPORTANT_FOR_ACCESSIBILITY_DEFAULT << PFLAG2_IMPORTANT_FOR_ACCESSIBILITY_SHIFT);
3969        mTouchSlop = ViewConfiguration.get(context).getScaledTouchSlop();
3970        setOverScrollMode(OVER_SCROLL_IF_CONTENT_SCROLLS);
3971        mUserPaddingStart = UNDEFINED_PADDING;
3972        mUserPaddingEnd = UNDEFINED_PADDING;
3973        mRenderNode = RenderNode.create(getClass().getName(), this);
3974
3975        if (!sCompatibilityDone && context != null) {
3976            final int targetSdkVersion = context.getApplicationInfo().targetSdkVersion;
3977
3978            // Older apps may need this compatibility hack for measurement.
3979            sUseBrokenMakeMeasureSpec = targetSdkVersion <= JELLY_BEAN_MR1;
3980
3981            // Older apps expect onMeasure() to always be called on a layout pass, regardless
3982            // of whether a layout was requested on that View.
3983            sIgnoreMeasureCache = targetSdkVersion < KITKAT;
3984
3985            Canvas.sCompatibilityRestore = targetSdkVersion < M;
3986
3987            // In M and newer, our widgets can pass a "hint" value in the size
3988            // for UNSPECIFIED MeasureSpecs. This lets child views of scrolling containers
3989            // know what the expected parent size is going to be, so e.g. list items can size
3990            // themselves at 1/3 the size of their container. It breaks older apps though,
3991            // specifically apps that use some popular open source libraries.
3992            sUseZeroUnspecifiedMeasureSpec = targetSdkVersion < M;
3993
3994            // Old versions of the platform would give different results from
3995            // LinearLayout measurement passes using EXACTLY and non-EXACTLY
3996            // modes, so we always need to run an additional EXACTLY pass.
3997            sAlwaysRemeasureExactly = targetSdkVersion <= M;
3998
3999            // Prior to N, layout params could change without requiring a
4000            // subsequent call to setLayoutParams() and they would usually
4001            // work. Partial layout breaks this assumption.
4002            sLayoutParamsAlwaysChanged = targetSdkVersion <= M;
4003
4004            sCompatibilityDone = true;
4005        }
4006    }
4007
4008    /**
4009     * Constructor that is called when inflating a view from XML. This is called
4010     * when a view is being constructed from an XML file, supplying attributes
4011     * that were specified in the XML file. This version uses a default style of
4012     * 0, so the only attribute values applied are those in the Context's Theme
4013     * and the given AttributeSet.
4014     *
4015     * <p>
4016     * The method onFinishInflate() will be called after all children have been
4017     * added.
4018     *
4019     * @param context The Context the view is running in, through which it can
4020     *        access the current theme, resources, etc.
4021     * @param attrs The attributes of the XML tag that is inflating the view.
4022     * @see #View(Context, AttributeSet, int)
4023     */
4024    public View(Context context, @Nullable AttributeSet attrs) {
4025        this(context, attrs, 0);
4026    }
4027
4028    /**
4029     * Perform inflation from XML and apply a class-specific base style from a
4030     * theme attribute. This constructor of View allows subclasses to use their
4031     * own base style when they are inflating. For example, a Button class's
4032     * constructor would call this version of the super class constructor and
4033     * supply <code>R.attr.buttonStyle</code> for <var>defStyleAttr</var>; this
4034     * allows the theme's button style to modify all of the base view attributes
4035     * (in particular its background) as well as the Button class's attributes.
4036     *
4037     * @param context The Context the view is running in, through which it can
4038     *        access the current theme, resources, etc.
4039     * @param attrs The attributes of the XML tag that is inflating the view.
4040     * @param defStyleAttr An attribute in the current theme that contains a
4041     *        reference to a style resource that supplies default values for
4042     *        the view. Can be 0 to not look for defaults.
4043     * @see #View(Context, AttributeSet)
4044     */
4045    public View(Context context, @Nullable AttributeSet attrs, int defStyleAttr) {
4046        this(context, attrs, defStyleAttr, 0);
4047    }
4048
4049    /**
4050     * Perform inflation from XML and apply a class-specific base style from a
4051     * theme attribute or style resource. This constructor of View allows
4052     * subclasses to use their own base style when they are inflating.
4053     * <p>
4054     * When determining the final value of a particular attribute, there are
4055     * four inputs that come into play:
4056     * <ol>
4057     * <li>Any attribute values in the given AttributeSet.
4058     * <li>The style resource specified in the AttributeSet (named "style").
4059     * <li>The default style specified by <var>defStyleAttr</var>.
4060     * <li>The default style specified by <var>defStyleRes</var>.
4061     * <li>The base values in this theme.
4062     * </ol>
4063     * <p>
4064     * Each of these inputs is considered in-order, with the first listed taking
4065     * precedence over the following ones. In other words, if in the
4066     * AttributeSet you have supplied <code>&lt;Button * textColor="#ff000000"&gt;</code>
4067     * , then the button's text will <em>always</em> be black, regardless of
4068     * what is specified in any of the styles.
4069     *
4070     * @param context The Context the view is running in, through which it can
4071     *        access the current theme, resources, etc.
4072     * @param attrs The attributes of the XML tag that is inflating the view.
4073     * @param defStyleAttr An attribute in the current theme that contains a
4074     *        reference to a style resource that supplies default values for
4075     *        the view. Can be 0 to not look for defaults.
4076     * @param defStyleRes A resource identifier of a style resource that
4077     *        supplies default values for the view, used only if
4078     *        defStyleAttr is 0 or can not be found in the theme. Can be 0
4079     *        to not look for defaults.
4080     * @see #View(Context, AttributeSet, int)
4081     */
4082    public View(Context context, @Nullable AttributeSet attrs, int defStyleAttr, int defStyleRes) {
4083        this(context);
4084
4085        final TypedArray a = context.obtainStyledAttributes(
4086                attrs, com.android.internal.R.styleable.View, defStyleAttr, defStyleRes);
4087
4088        if (mDebugViewAttributes) {
4089            saveAttributeData(attrs, a);
4090        }
4091
4092        Drawable background = null;
4093
4094        int leftPadding = -1;
4095        int topPadding = -1;
4096        int rightPadding = -1;
4097        int bottomPadding = -1;
4098        int startPadding = UNDEFINED_PADDING;
4099        int endPadding = UNDEFINED_PADDING;
4100
4101        int padding = -1;
4102
4103        int viewFlagValues = 0;
4104        int viewFlagMasks = 0;
4105
4106        boolean setScrollContainer = false;
4107
4108        int x = 0;
4109        int y = 0;
4110
4111        float tx = 0;
4112        float ty = 0;
4113        float tz = 0;
4114        float elevation = 0;
4115        float rotation = 0;
4116        float rotationX = 0;
4117        float rotationY = 0;
4118        float sx = 1f;
4119        float sy = 1f;
4120        boolean transformSet = false;
4121
4122        int scrollbarStyle = SCROLLBARS_INSIDE_OVERLAY;
4123        int overScrollMode = mOverScrollMode;
4124        boolean initializeScrollbars = false;
4125        boolean initializeScrollIndicators = false;
4126
4127        boolean startPaddingDefined = false;
4128        boolean endPaddingDefined = false;
4129        boolean leftPaddingDefined = false;
4130        boolean rightPaddingDefined = false;
4131
4132        final int targetSdkVersion = context.getApplicationInfo().targetSdkVersion;
4133
4134        final int N = a.getIndexCount();
4135        for (int i = 0; i < N; i++) {
4136            int attr = a.getIndex(i);
4137            switch (attr) {
4138                case com.android.internal.R.styleable.View_background:
4139                    background = a.getDrawable(attr);
4140                    break;
4141                case com.android.internal.R.styleable.View_padding:
4142                    padding = a.getDimensionPixelSize(attr, -1);
4143                    mUserPaddingLeftInitial = padding;
4144                    mUserPaddingRightInitial = padding;
4145                    leftPaddingDefined = true;
4146                    rightPaddingDefined = true;
4147                    break;
4148                 case com.android.internal.R.styleable.View_paddingLeft:
4149                    leftPadding = a.getDimensionPixelSize(attr, -1);
4150                    mUserPaddingLeftInitial = leftPadding;
4151                    leftPaddingDefined = true;
4152                    break;
4153                case com.android.internal.R.styleable.View_paddingTop:
4154                    topPadding = a.getDimensionPixelSize(attr, -1);
4155                    break;
4156                case com.android.internal.R.styleable.View_paddingRight:
4157                    rightPadding = a.getDimensionPixelSize(attr, -1);
4158                    mUserPaddingRightInitial = rightPadding;
4159                    rightPaddingDefined = true;
4160                    break;
4161                case com.android.internal.R.styleable.View_paddingBottom:
4162                    bottomPadding = a.getDimensionPixelSize(attr, -1);
4163                    break;
4164                case com.android.internal.R.styleable.View_paddingStart:
4165                    startPadding = a.getDimensionPixelSize(attr, UNDEFINED_PADDING);
4166                    startPaddingDefined = (startPadding != UNDEFINED_PADDING);
4167                    break;
4168                case com.android.internal.R.styleable.View_paddingEnd:
4169                    endPadding = a.getDimensionPixelSize(attr, UNDEFINED_PADDING);
4170                    endPaddingDefined = (endPadding != UNDEFINED_PADDING);
4171                    break;
4172                case com.android.internal.R.styleable.View_scrollX:
4173                    x = a.getDimensionPixelOffset(attr, 0);
4174                    break;
4175                case com.android.internal.R.styleable.View_scrollY:
4176                    y = a.getDimensionPixelOffset(attr, 0);
4177                    break;
4178                case com.android.internal.R.styleable.View_alpha:
4179                    setAlpha(a.getFloat(attr, 1f));
4180                    break;
4181                case com.android.internal.R.styleable.View_transformPivotX:
4182                    setPivotX(a.getDimensionPixelOffset(attr, 0));
4183                    break;
4184                case com.android.internal.R.styleable.View_transformPivotY:
4185                    setPivotY(a.getDimensionPixelOffset(attr, 0));
4186                    break;
4187                case com.android.internal.R.styleable.View_translationX:
4188                    tx = a.getDimensionPixelOffset(attr, 0);
4189                    transformSet = true;
4190                    break;
4191                case com.android.internal.R.styleable.View_translationY:
4192                    ty = a.getDimensionPixelOffset(attr, 0);
4193                    transformSet = true;
4194                    break;
4195                case com.android.internal.R.styleable.View_translationZ:
4196                    tz = a.getDimensionPixelOffset(attr, 0);
4197                    transformSet = true;
4198                    break;
4199                case com.android.internal.R.styleable.View_elevation:
4200                    elevation = a.getDimensionPixelOffset(attr, 0);
4201                    transformSet = true;
4202                    break;
4203                case com.android.internal.R.styleable.View_rotation:
4204                    rotation = a.getFloat(attr, 0);
4205                    transformSet = true;
4206                    break;
4207                case com.android.internal.R.styleable.View_rotationX:
4208                    rotationX = a.getFloat(attr, 0);
4209                    transformSet = true;
4210                    break;
4211                case com.android.internal.R.styleable.View_rotationY:
4212                    rotationY = a.getFloat(attr, 0);
4213                    transformSet = true;
4214                    break;
4215                case com.android.internal.R.styleable.View_scaleX:
4216                    sx = a.getFloat(attr, 1f);
4217                    transformSet = true;
4218                    break;
4219                case com.android.internal.R.styleable.View_scaleY:
4220                    sy = a.getFloat(attr, 1f);
4221                    transformSet = true;
4222                    break;
4223                case com.android.internal.R.styleable.View_id:
4224                    mID = a.getResourceId(attr, NO_ID);
4225                    break;
4226                case com.android.internal.R.styleable.View_tag:
4227                    mTag = a.getText(attr);
4228                    break;
4229                case com.android.internal.R.styleable.View_fitsSystemWindows:
4230                    if (a.getBoolean(attr, false)) {
4231                        viewFlagValues |= FITS_SYSTEM_WINDOWS;
4232                        viewFlagMasks |= FITS_SYSTEM_WINDOWS;
4233                    }
4234                    break;
4235                case com.android.internal.R.styleable.View_focusable:
4236                    if (a.getBoolean(attr, false)) {
4237                        viewFlagValues |= FOCUSABLE;
4238                        viewFlagMasks |= FOCUSABLE_MASK;
4239                    }
4240                    break;
4241                case com.android.internal.R.styleable.View_focusableInTouchMode:
4242                    if (a.getBoolean(attr, false)) {
4243                        viewFlagValues |= FOCUSABLE_IN_TOUCH_MODE | FOCUSABLE;
4244                        viewFlagMasks |= FOCUSABLE_IN_TOUCH_MODE | FOCUSABLE_MASK;
4245                    }
4246                    break;
4247                case com.android.internal.R.styleable.View_clickable:
4248                    if (a.getBoolean(attr, false)) {
4249                        viewFlagValues |= CLICKABLE;
4250                        viewFlagMasks |= CLICKABLE;
4251                    }
4252                    break;
4253                case com.android.internal.R.styleable.View_longClickable:
4254                    if (a.getBoolean(attr, false)) {
4255                        viewFlagValues |= LONG_CLICKABLE;
4256                        viewFlagMasks |= LONG_CLICKABLE;
4257                    }
4258                    break;
4259                case com.android.internal.R.styleable.View_contextClickable:
4260                    if (a.getBoolean(attr, false)) {
4261                        viewFlagValues |= CONTEXT_CLICKABLE;
4262                        viewFlagMasks |= CONTEXT_CLICKABLE;
4263                    }
4264                    break;
4265                case com.android.internal.R.styleable.View_saveEnabled:
4266                    if (!a.getBoolean(attr, true)) {
4267                        viewFlagValues |= SAVE_DISABLED;
4268                        viewFlagMasks |= SAVE_DISABLED_MASK;
4269                    }
4270                    break;
4271                case com.android.internal.R.styleable.View_duplicateParentState:
4272                    if (a.getBoolean(attr, false)) {
4273                        viewFlagValues |= DUPLICATE_PARENT_STATE;
4274                        viewFlagMasks |= DUPLICATE_PARENT_STATE;
4275                    }
4276                    break;
4277                case com.android.internal.R.styleable.View_visibility:
4278                    final int visibility = a.getInt(attr, 0);
4279                    if (visibility != 0) {
4280                        viewFlagValues |= VISIBILITY_FLAGS[visibility];
4281                        viewFlagMasks |= VISIBILITY_MASK;
4282                    }
4283                    break;
4284                case com.android.internal.R.styleable.View_layoutDirection:
4285                    // Clear any layout direction flags (included resolved bits) already set
4286                    mPrivateFlags2 &=
4287                            ~(PFLAG2_LAYOUT_DIRECTION_MASK | PFLAG2_LAYOUT_DIRECTION_RESOLVED_MASK);
4288                    // Set the layout direction flags depending on the value of the attribute
4289                    final int layoutDirection = a.getInt(attr, -1);
4290                    final int value = (layoutDirection != -1) ?
4291                            LAYOUT_DIRECTION_FLAGS[layoutDirection] : LAYOUT_DIRECTION_DEFAULT;
4292                    mPrivateFlags2 |= (value << PFLAG2_LAYOUT_DIRECTION_MASK_SHIFT);
4293                    break;
4294                case com.android.internal.R.styleable.View_drawingCacheQuality:
4295                    final int cacheQuality = a.getInt(attr, 0);
4296                    if (cacheQuality != 0) {
4297                        viewFlagValues |= DRAWING_CACHE_QUALITY_FLAGS[cacheQuality];
4298                        viewFlagMasks |= DRAWING_CACHE_QUALITY_MASK;
4299                    }
4300                    break;
4301                case com.android.internal.R.styleable.View_contentDescription:
4302                    setContentDescription(a.getString(attr));
4303                    break;
4304                case com.android.internal.R.styleable.View_accessibilityTraversalBefore:
4305                    setAccessibilityTraversalBefore(a.getResourceId(attr, NO_ID));
4306                    break;
4307                case com.android.internal.R.styleable.View_accessibilityTraversalAfter:
4308                    setAccessibilityTraversalAfter(a.getResourceId(attr, NO_ID));
4309                    break;
4310                case com.android.internal.R.styleable.View_labelFor:
4311                    setLabelFor(a.getResourceId(attr, NO_ID));
4312                    break;
4313                case com.android.internal.R.styleable.View_soundEffectsEnabled:
4314                    if (!a.getBoolean(attr, true)) {
4315                        viewFlagValues &= ~SOUND_EFFECTS_ENABLED;
4316                        viewFlagMasks |= SOUND_EFFECTS_ENABLED;
4317                    }
4318                    break;
4319                case com.android.internal.R.styleable.View_hapticFeedbackEnabled:
4320                    if (!a.getBoolean(attr, true)) {
4321                        viewFlagValues &= ~HAPTIC_FEEDBACK_ENABLED;
4322                        viewFlagMasks |= HAPTIC_FEEDBACK_ENABLED;
4323                    }
4324                    break;
4325                case R.styleable.View_scrollbars:
4326                    final int scrollbars = a.getInt(attr, SCROLLBARS_NONE);
4327                    if (scrollbars != SCROLLBARS_NONE) {
4328                        viewFlagValues |= scrollbars;
4329                        viewFlagMasks |= SCROLLBARS_MASK;
4330                        initializeScrollbars = true;
4331                    }
4332                    break;
4333                //noinspection deprecation
4334                case R.styleable.View_fadingEdge:
4335                    if (targetSdkVersion >= ICE_CREAM_SANDWICH) {
4336                        // Ignore the attribute starting with ICS
4337                        break;
4338                    }
4339                    // With builds < ICS, fall through and apply fading edges
4340                case R.styleable.View_requiresFadingEdge:
4341                    final int fadingEdge = a.getInt(attr, FADING_EDGE_NONE);
4342                    if (fadingEdge != FADING_EDGE_NONE) {
4343                        viewFlagValues |= fadingEdge;
4344                        viewFlagMasks |= FADING_EDGE_MASK;
4345                        initializeFadingEdgeInternal(a);
4346                    }
4347                    break;
4348                case R.styleable.View_scrollbarStyle:
4349                    scrollbarStyle = a.getInt(attr, SCROLLBARS_INSIDE_OVERLAY);
4350                    if (scrollbarStyle != SCROLLBARS_INSIDE_OVERLAY) {
4351                        viewFlagValues |= scrollbarStyle & SCROLLBARS_STYLE_MASK;
4352                        viewFlagMasks |= SCROLLBARS_STYLE_MASK;
4353                    }
4354                    break;
4355                case R.styleable.View_isScrollContainer:
4356                    setScrollContainer = true;
4357                    if (a.getBoolean(attr, false)) {
4358                        setScrollContainer(true);
4359                    }
4360                    break;
4361                case com.android.internal.R.styleable.View_keepScreenOn:
4362                    if (a.getBoolean(attr, false)) {
4363                        viewFlagValues |= KEEP_SCREEN_ON;
4364                        viewFlagMasks |= KEEP_SCREEN_ON;
4365                    }
4366                    break;
4367                case R.styleable.View_filterTouchesWhenObscured:
4368                    if (a.getBoolean(attr, false)) {
4369                        viewFlagValues |= FILTER_TOUCHES_WHEN_OBSCURED;
4370                        viewFlagMasks |= FILTER_TOUCHES_WHEN_OBSCURED;
4371                    }
4372                    break;
4373                case R.styleable.View_nextFocusLeft:
4374                    mNextFocusLeftId = a.getResourceId(attr, View.NO_ID);
4375                    break;
4376                case R.styleable.View_nextFocusRight:
4377                    mNextFocusRightId = a.getResourceId(attr, View.NO_ID);
4378                    break;
4379                case R.styleable.View_nextFocusUp:
4380                    mNextFocusUpId = a.getResourceId(attr, View.NO_ID);
4381                    break;
4382                case R.styleable.View_nextFocusDown:
4383                    mNextFocusDownId = a.getResourceId(attr, View.NO_ID);
4384                    break;
4385                case R.styleable.View_nextFocusForward:
4386                    mNextFocusForwardId = a.getResourceId(attr, View.NO_ID);
4387                    break;
4388                case R.styleable.View_minWidth:
4389                    mMinWidth = a.getDimensionPixelSize(attr, 0);
4390                    break;
4391                case R.styleable.View_minHeight:
4392                    mMinHeight = a.getDimensionPixelSize(attr, 0);
4393                    break;
4394                case R.styleable.View_onClick:
4395                    if (context.isRestricted()) {
4396                        throw new IllegalStateException("The android:onClick attribute cannot "
4397                                + "be used within a restricted context");
4398                    }
4399
4400                    final String handlerName = a.getString(attr);
4401                    if (handlerName != null) {
4402                        setOnClickListener(new DeclaredOnClickListener(this, handlerName));
4403                    }
4404                    break;
4405                case R.styleable.View_overScrollMode:
4406                    overScrollMode = a.getInt(attr, OVER_SCROLL_IF_CONTENT_SCROLLS);
4407                    break;
4408                case R.styleable.View_verticalScrollbarPosition:
4409                    mVerticalScrollbarPosition = a.getInt(attr, SCROLLBAR_POSITION_DEFAULT);
4410                    break;
4411                case R.styleable.View_layerType:
4412                    setLayerType(a.getInt(attr, LAYER_TYPE_NONE), null);
4413                    break;
4414                case R.styleable.View_textDirection:
4415                    // Clear any text direction flag already set
4416                    mPrivateFlags2 &= ~PFLAG2_TEXT_DIRECTION_MASK;
4417                    // Set the text direction flags depending on the value of the attribute
4418                    final int textDirection = a.getInt(attr, -1);
4419                    if (textDirection != -1) {
4420                        mPrivateFlags2 |= PFLAG2_TEXT_DIRECTION_FLAGS[textDirection];
4421                    }
4422                    break;
4423                case R.styleable.View_textAlignment:
4424                    // Clear any text alignment flag already set
4425                    mPrivateFlags2 &= ~PFLAG2_TEXT_ALIGNMENT_MASK;
4426                    // Set the text alignment flag depending on the value of the attribute
4427                    final int textAlignment = a.getInt(attr, TEXT_ALIGNMENT_DEFAULT);
4428                    mPrivateFlags2 |= PFLAG2_TEXT_ALIGNMENT_FLAGS[textAlignment];
4429                    break;
4430                case R.styleable.View_importantForAccessibility:
4431                    setImportantForAccessibility(a.getInt(attr,
4432                            IMPORTANT_FOR_ACCESSIBILITY_DEFAULT));
4433                    break;
4434                case R.styleable.View_accessibilityLiveRegion:
4435                    setAccessibilityLiveRegion(a.getInt(attr, ACCESSIBILITY_LIVE_REGION_DEFAULT));
4436                    break;
4437                case R.styleable.View_transitionName:
4438                    setTransitionName(a.getString(attr));
4439                    break;
4440                case R.styleable.View_nestedScrollingEnabled:
4441                    setNestedScrollingEnabled(a.getBoolean(attr, false));
4442                    break;
4443                case R.styleable.View_stateListAnimator:
4444                    setStateListAnimator(AnimatorInflater.loadStateListAnimator(context,
4445                            a.getResourceId(attr, 0)));
4446                    break;
4447                case R.styleable.View_backgroundTint:
4448                    // This will get applied later during setBackground().
4449                    if (mBackgroundTint == null) {
4450                        mBackgroundTint = new TintInfo();
4451                    }
4452                    mBackgroundTint.mTintList = a.getColorStateList(
4453                            R.styleable.View_backgroundTint);
4454                    mBackgroundTint.mHasTintList = true;
4455                    break;
4456                case R.styleable.View_backgroundTintMode:
4457                    // This will get applied later during setBackground().
4458                    if (mBackgroundTint == null) {
4459                        mBackgroundTint = new TintInfo();
4460                    }
4461                    mBackgroundTint.mTintMode = Drawable.parseTintMode(a.getInt(
4462                            R.styleable.View_backgroundTintMode, -1), null);
4463                    mBackgroundTint.mHasTintMode = true;
4464                    break;
4465                case R.styleable.View_outlineProvider:
4466                    setOutlineProviderFromAttribute(a.getInt(R.styleable.View_outlineProvider,
4467                            PROVIDER_BACKGROUND));
4468                    break;
4469                case R.styleable.View_foreground:
4470                    if (targetSdkVersion >= VERSION_CODES.M || this instanceof FrameLayout) {
4471                        setForeground(a.getDrawable(attr));
4472                    }
4473                    break;
4474                case R.styleable.View_foregroundGravity:
4475                    if (targetSdkVersion >= VERSION_CODES.M || this instanceof FrameLayout) {
4476                        setForegroundGravity(a.getInt(attr, Gravity.NO_GRAVITY));
4477                    }
4478                    break;
4479                case R.styleable.View_foregroundTintMode:
4480                    if (targetSdkVersion >= VERSION_CODES.M || this instanceof FrameLayout) {
4481                        setForegroundTintMode(Drawable.parseTintMode(a.getInt(attr, -1), null));
4482                    }
4483                    break;
4484                case R.styleable.View_foregroundTint:
4485                    if (targetSdkVersion >= VERSION_CODES.M || this instanceof FrameLayout) {
4486                        setForegroundTintList(a.getColorStateList(attr));
4487                    }
4488                    break;
4489                case R.styleable.View_foregroundInsidePadding:
4490                    if (targetSdkVersion >= VERSION_CODES.M || this instanceof FrameLayout) {
4491                        if (mForegroundInfo == null) {
4492                            mForegroundInfo = new ForegroundInfo();
4493                        }
4494                        mForegroundInfo.mInsidePadding = a.getBoolean(attr,
4495                                mForegroundInfo.mInsidePadding);
4496                    }
4497                    break;
4498                case R.styleable.View_scrollIndicators:
4499                    final int scrollIndicators =
4500                            (a.getInt(attr, 0) << SCROLL_INDICATORS_TO_PFLAGS3_LSHIFT)
4501                                    & SCROLL_INDICATORS_PFLAG3_MASK;
4502                    if (scrollIndicators != 0) {
4503                        mPrivateFlags3 |= scrollIndicators;
4504                        initializeScrollIndicators = true;
4505                    }
4506                    break;
4507            }
4508        }
4509
4510        setOverScrollMode(overScrollMode);
4511
4512        // Cache start/end user padding as we cannot fully resolve padding here (we dont have yet
4513        // the resolved layout direction). Those cached values will be used later during padding
4514        // resolution.
4515        mUserPaddingStart = startPadding;
4516        mUserPaddingEnd = endPadding;
4517
4518        if (background != null) {
4519            setBackground(background);
4520        }
4521
4522        // setBackground above will record that padding is currently provided by the background.
4523        // If we have padding specified via xml, record that here instead and use it.
4524        mLeftPaddingDefined = leftPaddingDefined;
4525        mRightPaddingDefined = rightPaddingDefined;
4526
4527        if (padding >= 0) {
4528            leftPadding = padding;
4529            topPadding = padding;
4530            rightPadding = padding;
4531            bottomPadding = padding;
4532            mUserPaddingLeftInitial = padding;
4533            mUserPaddingRightInitial = padding;
4534        }
4535
4536        if (isRtlCompatibilityMode()) {
4537            // RTL compatibility mode: pre Jelly Bean MR1 case OR no RTL support case.
4538            // left / right padding are used if defined (meaning here nothing to do). If they are not
4539            // defined and start / end padding are defined (e.g. in Frameworks resources), then we use
4540            // start / end and resolve them as left / right (layout direction is not taken into account).
4541            // Padding from the background drawable is stored at this point in mUserPaddingLeftInitial
4542            // and mUserPaddingRightInitial) so drawable padding will be used as ultimate default if
4543            // defined.
4544            if (!mLeftPaddingDefined && startPaddingDefined) {
4545                leftPadding = startPadding;
4546            }
4547            mUserPaddingLeftInitial = (leftPadding >= 0) ? leftPadding : mUserPaddingLeftInitial;
4548            if (!mRightPaddingDefined && endPaddingDefined) {
4549                rightPadding = endPadding;
4550            }
4551            mUserPaddingRightInitial = (rightPadding >= 0) ? rightPadding : mUserPaddingRightInitial;
4552        } else {
4553            // Jelly Bean MR1 and after case: if start/end defined, they will override any left/right
4554            // values defined. Otherwise, left /right values are used.
4555            // Padding from the background drawable is stored at this point in mUserPaddingLeftInitial
4556            // and mUserPaddingRightInitial) so drawable padding will be used as ultimate default if
4557            // defined.
4558            final boolean hasRelativePadding = startPaddingDefined || endPaddingDefined;
4559
4560            if (mLeftPaddingDefined && !hasRelativePadding) {
4561                mUserPaddingLeftInitial = leftPadding;
4562            }
4563            if (mRightPaddingDefined && !hasRelativePadding) {
4564                mUserPaddingRightInitial = rightPadding;
4565            }
4566        }
4567
4568        internalSetPadding(
4569                mUserPaddingLeftInitial,
4570                topPadding >= 0 ? topPadding : mPaddingTop,
4571                mUserPaddingRightInitial,
4572                bottomPadding >= 0 ? bottomPadding : mPaddingBottom);
4573
4574        if (viewFlagMasks != 0) {
4575            setFlags(viewFlagValues, viewFlagMasks);
4576        }
4577
4578        if (initializeScrollbars) {
4579            initializeScrollbarsInternal(a);
4580        }
4581
4582        if (initializeScrollIndicators) {
4583            initializeScrollIndicatorsInternal();
4584        }
4585
4586        a.recycle();
4587
4588        // Needs to be called after mViewFlags is set
4589        if (scrollbarStyle != SCROLLBARS_INSIDE_OVERLAY) {
4590            recomputePadding();
4591        }
4592
4593        if (x != 0 || y != 0) {
4594            scrollTo(x, y);
4595        }
4596
4597        if (transformSet) {
4598            setTranslationX(tx);
4599            setTranslationY(ty);
4600            setTranslationZ(tz);
4601            setElevation(elevation);
4602            setRotation(rotation);
4603            setRotationX(rotationX);
4604            setRotationY(rotationY);
4605            setScaleX(sx);
4606            setScaleY(sy);
4607        }
4608
4609        if (!setScrollContainer && (viewFlagValues&SCROLLBARS_VERTICAL) != 0) {
4610            setScrollContainer(true);
4611        }
4612
4613        computeOpaqueFlags();
4614    }
4615
4616    /**
4617     * An implementation of OnClickListener that attempts to lazily load a
4618     * named click handling method from a parent or ancestor context.
4619     */
4620    private static class DeclaredOnClickListener implements OnClickListener {
4621        private final View mHostView;
4622        private final String mMethodName;
4623
4624        private Method mResolvedMethod;
4625        private Context mResolvedContext;
4626
4627        public DeclaredOnClickListener(@NonNull View hostView, @NonNull String methodName) {
4628            mHostView = hostView;
4629            mMethodName = methodName;
4630        }
4631
4632        @Override
4633        public void onClick(@NonNull View v) {
4634            if (mResolvedMethod == null) {
4635                resolveMethod(mHostView.getContext(), mMethodName);
4636            }
4637
4638            try {
4639                mResolvedMethod.invoke(mResolvedContext, v);
4640            } catch (IllegalAccessException e) {
4641                throw new IllegalStateException(
4642                        "Could not execute non-public method for android:onClick", e);
4643            } catch (InvocationTargetException e) {
4644                throw new IllegalStateException(
4645                        "Could not execute method for android:onClick", e);
4646            }
4647        }
4648
4649        @NonNull
4650        private void resolveMethod(@Nullable Context context, @NonNull String name) {
4651            while (context != null) {
4652                try {
4653                    if (!context.isRestricted()) {
4654                        final Method method = context.getClass().getMethod(mMethodName, View.class);
4655                        if (method != null) {
4656                            mResolvedMethod = method;
4657                            mResolvedContext = context;
4658                            return;
4659                        }
4660                    }
4661                } catch (NoSuchMethodException e) {
4662                    // Failed to find method, keep searching up the hierarchy.
4663                }
4664
4665                if (context instanceof ContextWrapper) {
4666                    context = ((ContextWrapper) context).getBaseContext();
4667                } else {
4668                    // Can't search up the hierarchy, null out and fail.
4669                    context = null;
4670                }
4671            }
4672
4673            final int id = mHostView.getId();
4674            final String idText = id == NO_ID ? "" : " with id '"
4675                    + mHostView.getContext().getResources().getResourceEntryName(id) + "'";
4676            throw new IllegalStateException("Could not find method " + mMethodName
4677                    + "(View) in a parent or ancestor Context for android:onClick "
4678                    + "attribute defined on view " + mHostView.getClass() + idText);
4679        }
4680    }
4681
4682    /**
4683     * Non-public constructor for use in testing
4684     */
4685    View() {
4686        mResources = null;
4687        mRenderNode = RenderNode.create(getClass().getName(), this);
4688    }
4689
4690    private static SparseArray<String> getAttributeMap() {
4691        if (mAttributeMap == null) {
4692            mAttributeMap = new SparseArray<>();
4693        }
4694        return mAttributeMap;
4695    }
4696
4697    private void saveAttributeData(@Nullable AttributeSet attrs, @NonNull TypedArray t) {
4698        final int attrsCount = attrs == null ? 0 : attrs.getAttributeCount();
4699        final int indexCount = t.getIndexCount();
4700        final String[] attributes = new String[(attrsCount + indexCount) * 2];
4701
4702        int i = 0;
4703
4704        // Store raw XML attributes.
4705        for (int j = 0; j < attrsCount; ++j) {
4706            attributes[i] = attrs.getAttributeName(j);
4707            attributes[i + 1] = attrs.getAttributeValue(j);
4708            i += 2;
4709        }
4710
4711        // Store resolved styleable attributes.
4712        final Resources res = t.getResources();
4713        final SparseArray<String> attributeMap = getAttributeMap();
4714        for (int j = 0; j < indexCount; ++j) {
4715            final int index = t.getIndex(j);
4716            if (!t.hasValueOrEmpty(index)) {
4717                // Value is undefined. Skip it.
4718                continue;
4719            }
4720
4721            final int resourceId = t.getResourceId(index, 0);
4722            if (resourceId == 0) {
4723                // Value is not a reference. Skip it.
4724                continue;
4725            }
4726
4727            String resourceName = attributeMap.get(resourceId);
4728            if (resourceName == null) {
4729                try {
4730                    resourceName = res.getResourceName(resourceId);
4731                } catch (Resources.NotFoundException e) {
4732                    resourceName = "0x" + Integer.toHexString(resourceId);
4733                }
4734                attributeMap.put(resourceId, resourceName);
4735            }
4736
4737            attributes[i] = resourceName;
4738            attributes[i + 1] = t.getString(index);
4739            i += 2;
4740        }
4741
4742        // Trim to fit contents.
4743        final String[] trimmed = new String[i];
4744        System.arraycopy(attributes, 0, trimmed, 0, i);
4745        mAttributes = trimmed;
4746    }
4747
4748    public String toString() {
4749        StringBuilder out = new StringBuilder(128);
4750        out.append(getClass().getName());
4751        out.append('{');
4752        out.append(Integer.toHexString(System.identityHashCode(this)));
4753        out.append(' ');
4754        switch (mViewFlags&VISIBILITY_MASK) {
4755            case VISIBLE: out.append('V'); break;
4756            case INVISIBLE: out.append('I'); break;
4757            case GONE: out.append('G'); break;
4758            default: out.append('.'); break;
4759        }
4760        out.append((mViewFlags&FOCUSABLE_MASK) == FOCUSABLE ? 'F' : '.');
4761        out.append((mViewFlags&ENABLED_MASK) == ENABLED ? 'E' : '.');
4762        out.append((mViewFlags&DRAW_MASK) == WILL_NOT_DRAW ? '.' : 'D');
4763        out.append((mViewFlags&SCROLLBARS_HORIZONTAL) != 0 ? 'H' : '.');
4764        out.append((mViewFlags&SCROLLBARS_VERTICAL) != 0 ? 'V' : '.');
4765        out.append((mViewFlags&CLICKABLE) != 0 ? 'C' : '.');
4766        out.append((mViewFlags&LONG_CLICKABLE) != 0 ? 'L' : '.');
4767        out.append((mViewFlags&CONTEXT_CLICKABLE) != 0 ? 'X' : '.');
4768        out.append(' ');
4769        out.append((mPrivateFlags&PFLAG_IS_ROOT_NAMESPACE) != 0 ? 'R' : '.');
4770        out.append((mPrivateFlags&PFLAG_FOCUSED) != 0 ? 'F' : '.');
4771        out.append((mPrivateFlags&PFLAG_SELECTED) != 0 ? 'S' : '.');
4772        if ((mPrivateFlags&PFLAG_PREPRESSED) != 0) {
4773            out.append('p');
4774        } else {
4775            out.append((mPrivateFlags&PFLAG_PRESSED) != 0 ? 'P' : '.');
4776        }
4777        out.append((mPrivateFlags&PFLAG_HOVERED) != 0 ? 'H' : '.');
4778        out.append((mPrivateFlags&PFLAG_ACTIVATED) != 0 ? 'A' : '.');
4779        out.append((mPrivateFlags&PFLAG_INVALIDATED) != 0 ? 'I' : '.');
4780        out.append((mPrivateFlags&PFLAG_DIRTY_MASK) != 0 ? 'D' : '.');
4781        out.append(' ');
4782        out.append(mLeft);
4783        out.append(',');
4784        out.append(mTop);
4785        out.append('-');
4786        out.append(mRight);
4787        out.append(',');
4788        out.append(mBottom);
4789        final int id = getId();
4790        if (id != NO_ID) {
4791            out.append(" #");
4792            out.append(Integer.toHexString(id));
4793            final Resources r = mResources;
4794            if (id > 0 && Resources.resourceHasPackage(id) && r != null) {
4795                try {
4796                    String pkgname;
4797                    switch (id&0xff000000) {
4798                        case 0x7f000000:
4799                            pkgname="app";
4800                            break;
4801                        case 0x01000000:
4802                            pkgname="android";
4803                            break;
4804                        default:
4805                            pkgname = r.getResourcePackageName(id);
4806                            break;
4807                    }
4808                    String typename = r.getResourceTypeName(id);
4809                    String entryname = r.getResourceEntryName(id);
4810                    out.append(" ");
4811                    out.append(pkgname);
4812                    out.append(":");
4813                    out.append(typename);
4814                    out.append("/");
4815                    out.append(entryname);
4816                } catch (Resources.NotFoundException e) {
4817                }
4818            }
4819        }
4820        out.append("}");
4821        return out.toString();
4822    }
4823
4824    /**
4825     * <p>
4826     * Initializes the fading edges from a given set of styled attributes. This
4827     * method should be called by subclasses that need fading edges and when an
4828     * instance of these subclasses is created programmatically rather than
4829     * being inflated from XML. This method is automatically called when the XML
4830     * is inflated.
4831     * </p>
4832     *
4833     * @param a the styled attributes set to initialize the fading edges from
4834     *
4835     * @removed
4836     */
4837    protected void initializeFadingEdge(TypedArray a) {
4838        // This method probably shouldn't have been included in the SDK to begin with.
4839        // It relies on 'a' having been initialized using an attribute filter array that is
4840        // not publicly available to the SDK. The old method has been renamed
4841        // to initializeFadingEdgeInternal and hidden for framework use only;
4842        // this one initializes using defaults to make it safe to call for apps.
4843
4844        TypedArray arr = mContext.obtainStyledAttributes(com.android.internal.R.styleable.View);
4845
4846        initializeFadingEdgeInternal(arr);
4847
4848        arr.recycle();
4849    }
4850
4851    /**
4852     * <p>
4853     * Initializes the fading edges from a given set of styled attributes. This
4854     * method should be called by subclasses that need fading edges and when an
4855     * instance of these subclasses is created programmatically rather than
4856     * being inflated from XML. This method is automatically called when the XML
4857     * is inflated.
4858     * </p>
4859     *
4860     * @param a the styled attributes set to initialize the fading edges from
4861     * @hide This is the real method; the public one is shimmed to be safe to call from apps.
4862     */
4863    protected void initializeFadingEdgeInternal(TypedArray a) {
4864        initScrollCache();
4865
4866        mScrollCache.fadingEdgeLength = a.getDimensionPixelSize(
4867                R.styleable.View_fadingEdgeLength,
4868                ViewConfiguration.get(mContext).getScaledFadingEdgeLength());
4869    }
4870
4871    /**
4872     * Returns the size of the vertical faded edges used to indicate that more
4873     * content in this view is visible.
4874     *
4875     * @return The size in pixels of the vertical faded edge or 0 if vertical
4876     *         faded edges are not enabled for this view.
4877     * @attr ref android.R.styleable#View_fadingEdgeLength
4878     */
4879    public int getVerticalFadingEdgeLength() {
4880        if (isVerticalFadingEdgeEnabled()) {
4881            ScrollabilityCache cache = mScrollCache;
4882            if (cache != null) {
4883                return cache.fadingEdgeLength;
4884            }
4885        }
4886        return 0;
4887    }
4888
4889    /**
4890     * Set the size of the faded edge used to indicate that more content in this
4891     * view is available.  Will not change whether the fading edge is enabled; use
4892     * {@link #setVerticalFadingEdgeEnabled(boolean)} or
4893     * {@link #setHorizontalFadingEdgeEnabled(boolean)} to enable the fading edge
4894     * for the vertical or horizontal fading edges.
4895     *
4896     * @param length The size in pixels of the faded edge used to indicate that more
4897     *        content in this view is visible.
4898     */
4899    public void setFadingEdgeLength(int length) {
4900        initScrollCache();
4901        mScrollCache.fadingEdgeLength = length;
4902    }
4903
4904    /**
4905     * Returns the size of the horizontal faded edges used to indicate that more
4906     * content in this view is visible.
4907     *
4908     * @return The size in pixels of the horizontal faded edge or 0 if horizontal
4909     *         faded edges are not enabled for this view.
4910     * @attr ref android.R.styleable#View_fadingEdgeLength
4911     */
4912    public int getHorizontalFadingEdgeLength() {
4913        if (isHorizontalFadingEdgeEnabled()) {
4914            ScrollabilityCache cache = mScrollCache;
4915            if (cache != null) {
4916                return cache.fadingEdgeLength;
4917            }
4918        }
4919        return 0;
4920    }
4921
4922    /**
4923     * Returns the width of the vertical scrollbar.
4924     *
4925     * @return The width in pixels of the vertical scrollbar or 0 if there
4926     *         is no vertical scrollbar.
4927     */
4928    public int getVerticalScrollbarWidth() {
4929        ScrollabilityCache cache = mScrollCache;
4930        if (cache != null) {
4931            ScrollBarDrawable scrollBar = cache.scrollBar;
4932            if (scrollBar != null) {
4933                int size = scrollBar.getSize(true);
4934                if (size <= 0) {
4935                    size = cache.scrollBarSize;
4936                }
4937                return size;
4938            }
4939            return 0;
4940        }
4941        return 0;
4942    }
4943
4944    /**
4945     * Returns the height of the horizontal scrollbar.
4946     *
4947     * @return The height in pixels of the horizontal scrollbar or 0 if
4948     *         there is no horizontal scrollbar.
4949     */
4950    protected int getHorizontalScrollbarHeight() {
4951        ScrollabilityCache cache = mScrollCache;
4952        if (cache != null) {
4953            ScrollBarDrawable scrollBar = cache.scrollBar;
4954            if (scrollBar != null) {
4955                int size = scrollBar.getSize(false);
4956                if (size <= 0) {
4957                    size = cache.scrollBarSize;
4958                }
4959                return size;
4960            }
4961            return 0;
4962        }
4963        return 0;
4964    }
4965
4966    /**
4967     * <p>
4968     * Initializes the scrollbars from a given set of styled attributes. This
4969     * method should be called by subclasses that need scrollbars and when an
4970     * instance of these subclasses is created programmatically rather than
4971     * being inflated from XML. This method is automatically called when the XML
4972     * is inflated.
4973     * </p>
4974     *
4975     * @param a the styled attributes set to initialize the scrollbars from
4976     *
4977     * @removed
4978     */
4979    protected void initializeScrollbars(TypedArray a) {
4980        // It's not safe to use this method from apps. The parameter 'a' must have been obtained
4981        // using the View filter array which is not available to the SDK. As such, internal
4982        // framework usage now uses initializeScrollbarsInternal and we grab a default
4983        // TypedArray with the right filter instead here.
4984        TypedArray arr = mContext.obtainStyledAttributes(com.android.internal.R.styleable.View);
4985
4986        initializeScrollbarsInternal(arr);
4987
4988        // We ignored the method parameter. Recycle the one we actually did use.
4989        arr.recycle();
4990    }
4991
4992    /**
4993     * <p>
4994     * Initializes the scrollbars from a given set of styled attributes. This
4995     * method should be called by subclasses that need scrollbars and when an
4996     * instance of these subclasses is created programmatically rather than
4997     * being inflated from XML. This method is automatically called when the XML
4998     * is inflated.
4999     * </p>
5000     *
5001     * @param a the styled attributes set to initialize the scrollbars from
5002     * @hide
5003     */
5004    protected void initializeScrollbarsInternal(TypedArray a) {
5005        initScrollCache();
5006
5007        final ScrollabilityCache scrollabilityCache = mScrollCache;
5008
5009        if (scrollabilityCache.scrollBar == null) {
5010            scrollabilityCache.scrollBar = new ScrollBarDrawable();
5011            scrollabilityCache.scrollBar.setCallback(this);
5012            scrollabilityCache.scrollBar.setState(getDrawableState());
5013        }
5014
5015        final boolean fadeScrollbars = a.getBoolean(R.styleable.View_fadeScrollbars, true);
5016
5017        if (!fadeScrollbars) {
5018            scrollabilityCache.state = ScrollabilityCache.ON;
5019        }
5020        scrollabilityCache.fadeScrollBars = fadeScrollbars;
5021
5022
5023        scrollabilityCache.scrollBarFadeDuration = a.getInt(
5024                R.styleable.View_scrollbarFadeDuration, ViewConfiguration
5025                        .getScrollBarFadeDuration());
5026        scrollabilityCache.scrollBarDefaultDelayBeforeFade = a.getInt(
5027                R.styleable.View_scrollbarDefaultDelayBeforeFade,
5028                ViewConfiguration.getScrollDefaultDelay());
5029
5030
5031        scrollabilityCache.scrollBarSize = a.getDimensionPixelSize(
5032                com.android.internal.R.styleable.View_scrollbarSize,
5033                ViewConfiguration.get(mContext).getScaledScrollBarSize());
5034
5035        Drawable track = a.getDrawable(R.styleable.View_scrollbarTrackHorizontal);
5036        scrollabilityCache.scrollBar.setHorizontalTrackDrawable(track);
5037
5038        Drawable thumb = a.getDrawable(R.styleable.View_scrollbarThumbHorizontal);
5039        if (thumb != null) {
5040            scrollabilityCache.scrollBar.setHorizontalThumbDrawable(thumb);
5041        }
5042
5043        boolean alwaysDraw = a.getBoolean(R.styleable.View_scrollbarAlwaysDrawHorizontalTrack,
5044                false);
5045        if (alwaysDraw) {
5046            scrollabilityCache.scrollBar.setAlwaysDrawHorizontalTrack(true);
5047        }
5048
5049        track = a.getDrawable(R.styleable.View_scrollbarTrackVertical);
5050        scrollabilityCache.scrollBar.setVerticalTrackDrawable(track);
5051
5052        thumb = a.getDrawable(R.styleable.View_scrollbarThumbVertical);
5053        if (thumb != null) {
5054            scrollabilityCache.scrollBar.setVerticalThumbDrawable(thumb);
5055        }
5056
5057        alwaysDraw = a.getBoolean(R.styleable.View_scrollbarAlwaysDrawVerticalTrack,
5058                false);
5059        if (alwaysDraw) {
5060            scrollabilityCache.scrollBar.setAlwaysDrawVerticalTrack(true);
5061        }
5062
5063        // Apply layout direction to the new Drawables if needed
5064        final int layoutDirection = getLayoutDirection();
5065        if (track != null) {
5066            track.setLayoutDirection(layoutDirection);
5067        }
5068        if (thumb != null) {
5069            thumb.setLayoutDirection(layoutDirection);
5070        }
5071
5072        // Re-apply user/background padding so that scrollbar(s) get added
5073        resolvePadding();
5074    }
5075
5076    private void initializeScrollIndicatorsInternal() {
5077        // Some day maybe we'll break this into top/left/start/etc. and let the
5078        // client control it. Until then, you can have any scroll indicator you
5079        // want as long as it's a 1dp foreground-colored rectangle.
5080        if (mScrollIndicatorDrawable == null) {
5081            mScrollIndicatorDrawable = mContext.getDrawable(R.drawable.scroll_indicator_material);
5082        }
5083    }
5084
5085    /**
5086     * <p>
5087     * Initalizes the scrollability cache if necessary.
5088     * </p>
5089     */
5090    private void initScrollCache() {
5091        if (mScrollCache == null) {
5092            mScrollCache = new ScrollabilityCache(ViewConfiguration.get(mContext), this);
5093        }
5094    }
5095
5096    private ScrollabilityCache getScrollCache() {
5097        initScrollCache();
5098        return mScrollCache;
5099    }
5100
5101    /**
5102     * Set the position of the vertical scroll bar. Should be one of
5103     * {@link #SCROLLBAR_POSITION_DEFAULT}, {@link #SCROLLBAR_POSITION_LEFT} or
5104     * {@link #SCROLLBAR_POSITION_RIGHT}.
5105     *
5106     * @param position Where the vertical scroll bar should be positioned.
5107     */
5108    public void setVerticalScrollbarPosition(int position) {
5109        if (mVerticalScrollbarPosition != position) {
5110            mVerticalScrollbarPosition = position;
5111            computeOpaqueFlags();
5112            resolvePadding();
5113        }
5114    }
5115
5116    /**
5117     * @return The position where the vertical scroll bar will show, if applicable.
5118     * @see #setVerticalScrollbarPosition(int)
5119     */
5120    public int getVerticalScrollbarPosition() {
5121        return mVerticalScrollbarPosition;
5122    }
5123
5124    /**
5125     * Sets the state of all scroll indicators.
5126     * <p>
5127     * See {@link #setScrollIndicators(int, int)} for usage information.
5128     *
5129     * @param indicators a bitmask of indicators that should be enabled, or
5130     *                   {@code 0} to disable all indicators
5131     * @see #setScrollIndicators(int, int)
5132     * @see #getScrollIndicators()
5133     * @attr ref android.R.styleable#View_scrollIndicators
5134     */
5135    public void setScrollIndicators(@ScrollIndicators int indicators) {
5136        setScrollIndicators(indicators,
5137                SCROLL_INDICATORS_PFLAG3_MASK >>> SCROLL_INDICATORS_TO_PFLAGS3_LSHIFT);
5138    }
5139
5140    /**
5141     * Sets the state of the scroll indicators specified by the mask. To change
5142     * all scroll indicators at once, see {@link #setScrollIndicators(int)}.
5143     * <p>
5144     * When a scroll indicator is enabled, it will be displayed if the view
5145     * can scroll in the direction of the indicator.
5146     * <p>
5147     * Multiple indicator types may be enabled or disabled by passing the
5148     * logical OR of the desired types. If multiple types are specified, they
5149     * will all be set to the same enabled state.
5150     * <p>
5151     * For example, to enable the top scroll indicatorExample: {@code setScrollIndicators
5152     *
5153     * @param indicators the indicator direction, or the logical OR of multiple
5154     *             indicator directions. One or more of:
5155     *             <ul>
5156     *               <li>{@link #SCROLL_INDICATOR_TOP}</li>
5157     *               <li>{@link #SCROLL_INDICATOR_BOTTOM}</li>
5158     *               <li>{@link #SCROLL_INDICATOR_LEFT}</li>
5159     *               <li>{@link #SCROLL_INDICATOR_RIGHT}</li>
5160     *               <li>{@link #SCROLL_INDICATOR_START}</li>
5161     *               <li>{@link #SCROLL_INDICATOR_END}</li>
5162     *             </ul>
5163     * @see #setScrollIndicators(int)
5164     * @see #getScrollIndicators()
5165     * @attr ref android.R.styleable#View_scrollIndicators
5166     */
5167    public void setScrollIndicators(@ScrollIndicators int indicators, @ScrollIndicators int mask) {
5168        // Shift and sanitize mask.
5169        mask <<= SCROLL_INDICATORS_TO_PFLAGS3_LSHIFT;
5170        mask &= SCROLL_INDICATORS_PFLAG3_MASK;
5171
5172        // Shift and mask indicators.
5173        indicators <<= SCROLL_INDICATORS_TO_PFLAGS3_LSHIFT;
5174        indicators &= mask;
5175
5176        // Merge with non-masked flags.
5177        final int updatedFlags = indicators | (mPrivateFlags3 & ~mask);
5178
5179        if (mPrivateFlags3 != updatedFlags) {
5180            mPrivateFlags3 = updatedFlags;
5181
5182            if (indicators != 0) {
5183                initializeScrollIndicatorsInternal();
5184            }
5185            invalidate();
5186        }
5187    }
5188
5189    /**
5190     * Returns a bitmask representing the enabled scroll indicators.
5191     * <p>
5192     * For example, if the top and left scroll indicators are enabled and all
5193     * other indicators are disabled, the return value will be
5194     * {@code View.SCROLL_INDICATOR_TOP | View.SCROLL_INDICATOR_LEFT}.
5195     * <p>
5196     * To check whether the bottom scroll indicator is enabled, use the value
5197     * of {@code (getScrollIndicators() & View.SCROLL_INDICATOR_BOTTOM) != 0}.
5198     *
5199     * @return a bitmask representing the enabled scroll indicators
5200     */
5201    @ScrollIndicators
5202    public int getScrollIndicators() {
5203        return (mPrivateFlags3 & SCROLL_INDICATORS_PFLAG3_MASK)
5204                >>> SCROLL_INDICATORS_TO_PFLAGS3_LSHIFT;
5205    }
5206
5207    ListenerInfo getListenerInfo() {
5208        if (mListenerInfo != null) {
5209            return mListenerInfo;
5210        }
5211        mListenerInfo = new ListenerInfo();
5212        return mListenerInfo;
5213    }
5214
5215    /**
5216     * Register a callback to be invoked when the scroll X or Y positions of
5217     * this view change.
5218     * <p>
5219     * <b>Note:</b> Some views handle scrolling independently from View and may
5220     * have their own separate listeners for scroll-type events. For example,
5221     * {@link android.widget.ListView ListView} allows clients to register an
5222     * {@link android.widget.ListView#setOnScrollListener(android.widget.AbsListView.OnScrollListener) AbsListView.OnScrollListener}
5223     * to listen for changes in list scroll position.
5224     *
5225     * @param l The listener to notify when the scroll X or Y position changes.
5226     * @see android.view.View#getScrollX()
5227     * @see android.view.View#getScrollY()
5228     */
5229    public void setOnScrollChangeListener(OnScrollChangeListener l) {
5230        getListenerInfo().mOnScrollChangeListener = l;
5231    }
5232
5233    /**
5234     * Register a callback to be invoked when focus of this view changed.
5235     *
5236     * @param l The callback that will run.
5237     */
5238    public void setOnFocusChangeListener(OnFocusChangeListener l) {
5239        getListenerInfo().mOnFocusChangeListener = l;
5240    }
5241
5242    /**
5243     * Add a listener that will be called when the bounds of the view change due to
5244     * layout processing.
5245     *
5246     * @param listener The listener that will be called when layout bounds change.
5247     */
5248    public void addOnLayoutChangeListener(OnLayoutChangeListener listener) {
5249        ListenerInfo li = getListenerInfo();
5250        if (li.mOnLayoutChangeListeners == null) {
5251            li.mOnLayoutChangeListeners = new ArrayList<OnLayoutChangeListener>();
5252        }
5253        if (!li.mOnLayoutChangeListeners.contains(listener)) {
5254            li.mOnLayoutChangeListeners.add(listener);
5255        }
5256    }
5257
5258    /**
5259     * Remove a listener for layout changes.
5260     *
5261     * @param listener The listener for layout bounds change.
5262     */
5263    public void removeOnLayoutChangeListener(OnLayoutChangeListener listener) {
5264        ListenerInfo li = mListenerInfo;
5265        if (li == null || li.mOnLayoutChangeListeners == null) {
5266            return;
5267        }
5268        li.mOnLayoutChangeListeners.remove(listener);
5269    }
5270
5271    /**
5272     * Add a listener for attach state changes.
5273     *
5274     * This listener will be called whenever this view is attached or detached
5275     * from a window. Remove the listener using
5276     * {@link #removeOnAttachStateChangeListener(OnAttachStateChangeListener)}.
5277     *
5278     * @param listener Listener to attach
5279     * @see #removeOnAttachStateChangeListener(OnAttachStateChangeListener)
5280     */
5281    public void addOnAttachStateChangeListener(OnAttachStateChangeListener listener) {
5282        ListenerInfo li = getListenerInfo();
5283        if (li.mOnAttachStateChangeListeners == null) {
5284            li.mOnAttachStateChangeListeners
5285                    = new CopyOnWriteArrayList<OnAttachStateChangeListener>();
5286        }
5287        li.mOnAttachStateChangeListeners.add(listener);
5288    }
5289
5290    /**
5291     * Remove a listener for attach state changes. The listener will receive no further
5292     * notification of window attach/detach events.
5293     *
5294     * @param listener Listener to remove
5295     * @see #addOnAttachStateChangeListener(OnAttachStateChangeListener)
5296     */
5297    public void removeOnAttachStateChangeListener(OnAttachStateChangeListener listener) {
5298        ListenerInfo li = mListenerInfo;
5299        if (li == null || li.mOnAttachStateChangeListeners == null) {
5300            return;
5301        }
5302        li.mOnAttachStateChangeListeners.remove(listener);
5303    }
5304
5305    /**
5306     * Returns the focus-change callback registered for this view.
5307     *
5308     * @return The callback, or null if one is not registered.
5309     */
5310    public OnFocusChangeListener getOnFocusChangeListener() {
5311        ListenerInfo li = mListenerInfo;
5312        return li != null ? li.mOnFocusChangeListener : null;
5313    }
5314
5315    /**
5316     * Register a callback to be invoked when this view is clicked. If this view is not
5317     * clickable, it becomes clickable.
5318     *
5319     * @param l The callback that will run
5320     *
5321     * @see #setClickable(boolean)
5322     */
5323    public void setOnClickListener(@Nullable OnClickListener l) {
5324        if (!isClickable()) {
5325            setClickable(true);
5326        }
5327        getListenerInfo().mOnClickListener = l;
5328    }
5329
5330    /**
5331     * Return whether this view has an attached OnClickListener.  Returns
5332     * true if there is a listener, false if there is none.
5333     */
5334    public boolean hasOnClickListeners() {
5335        ListenerInfo li = mListenerInfo;
5336        return (li != null && li.mOnClickListener != null);
5337    }
5338
5339    /**
5340     * Register a callback to be invoked when this view is clicked and held. If this view is not
5341     * long clickable, it becomes long clickable.
5342     *
5343     * @param l The callback that will run
5344     *
5345     * @see #setLongClickable(boolean)
5346     */
5347    public void setOnLongClickListener(@Nullable OnLongClickListener l) {
5348        if (!isLongClickable()) {
5349            setLongClickable(true);
5350        }
5351        getListenerInfo().mOnLongClickListener = l;
5352    }
5353
5354    /**
5355     * Register a callback to be invoked when this view is context clicked. If the view is not
5356     * context clickable, it becomes context clickable.
5357     *
5358     * @param l The callback that will run
5359     * @see #setContextClickable(boolean)
5360     */
5361    public void setOnContextClickListener(@Nullable OnContextClickListener l) {
5362        if (!isContextClickable()) {
5363            setContextClickable(true);
5364        }
5365        getListenerInfo().mOnContextClickListener = l;
5366    }
5367
5368    /**
5369     * Register a callback to be invoked when the context menu for this view is
5370     * being built. If this view is not long clickable, it becomes long clickable.
5371     *
5372     * @param l The callback that will run
5373     *
5374     */
5375    public void setOnCreateContextMenuListener(OnCreateContextMenuListener l) {
5376        if (!isLongClickable()) {
5377            setLongClickable(true);
5378        }
5379        getListenerInfo().mOnCreateContextMenuListener = l;
5380    }
5381
5382    /**
5383     * Call this view's OnClickListener, if it is defined.  Performs all normal
5384     * actions associated with clicking: reporting accessibility event, playing
5385     * a sound, etc.
5386     *
5387     * @return True there was an assigned OnClickListener that was called, false
5388     *         otherwise is returned.
5389     */
5390    public boolean performClick() {
5391        final boolean result;
5392        final ListenerInfo li = mListenerInfo;
5393        if (li != null && li.mOnClickListener != null) {
5394            playSoundEffect(SoundEffectConstants.CLICK);
5395            li.mOnClickListener.onClick(this);
5396            result = true;
5397        } else {
5398            result = false;
5399        }
5400
5401        sendAccessibilityEvent(AccessibilityEvent.TYPE_VIEW_CLICKED);
5402        return result;
5403    }
5404
5405    /**
5406     * Directly call any attached OnClickListener.  Unlike {@link #performClick()},
5407     * this only calls the listener, and does not do any associated clicking
5408     * actions like reporting an accessibility event.
5409     *
5410     * @return True there was an assigned OnClickListener that was called, false
5411     *         otherwise is returned.
5412     */
5413    public boolean callOnClick() {
5414        ListenerInfo li = mListenerInfo;
5415        if (li != null && li.mOnClickListener != null) {
5416            li.mOnClickListener.onClick(this);
5417            return true;
5418        }
5419        return false;
5420    }
5421
5422    /**
5423     * Calls this view's OnLongClickListener, if it is defined. Invokes the
5424     * context menu if the OnLongClickListener did not consume the event.
5425     *
5426     * @return {@code true} if one of the above receivers consumed the event,
5427     *         {@code false} otherwise
5428     */
5429    public boolean performLongClick() {
5430        return performLongClickInternal(mLongClickX, mLongClickY);
5431    }
5432
5433    /**
5434     * Calls this view's OnLongClickListener, if it is defined. Invokes the
5435     * context menu if the OnLongClickListener did not consume the event,
5436     * anchoring it to an (x,y) coordinate.
5437     *
5438     * @param x x coordinate of the anchoring touch event, or {@link Float#NaN}
5439     *          to disable anchoring
5440     * @param y y coordinate of the anchoring touch event, or {@link Float#NaN}
5441     *          to disable anchoring
5442     * @return {@code true} if one of the above receivers consumed the event,
5443     *         {@code false} otherwise
5444     */
5445    public boolean performLongClick(float x, float y) {
5446        mLongClickX = x;
5447        mLongClickY = y;
5448        final boolean handled = performLongClick();
5449        mLongClickX = Float.NaN;
5450        mLongClickY = Float.NaN;
5451        return handled;
5452    }
5453
5454    /**
5455     * Calls this view's OnLongClickListener, if it is defined. Invokes the
5456     * context menu if the OnLongClickListener did not consume the event,
5457     * optionally anchoring it to an (x,y) coordinate.
5458     *
5459     * @param x x coordinate of the anchoring touch event, or {@link Float#NaN}
5460     *          to disable anchoring
5461     * @param y y coordinate of the anchoring touch event, or {@link Float#NaN}
5462     *          to disable anchoring
5463     * @return {@code true} if one of the above receivers consumed the event,
5464     *         {@code false} otherwise
5465     */
5466    private boolean performLongClickInternal(float x, float y) {
5467        sendAccessibilityEvent(AccessibilityEvent.TYPE_VIEW_LONG_CLICKED);
5468
5469        boolean handled = false;
5470        final ListenerInfo li = mListenerInfo;
5471        if (li != null && li.mOnLongClickListener != null) {
5472            handled = li.mOnLongClickListener.onLongClick(View.this);
5473        }
5474        if (!handled) {
5475            final boolean isAnchored = !Float.isNaN(x) && !Float.isNaN(y);
5476            handled = isAnchored ? showContextMenu(x, y) : showContextMenu();
5477        }
5478        if (handled) {
5479            performHapticFeedback(HapticFeedbackConstants.LONG_PRESS);
5480        }
5481        return handled;
5482    }
5483
5484    /**
5485     * Call this view's OnContextClickListener, if it is defined.
5486     *
5487     * @return True if there was an assigned OnContextClickListener that consumed the event, false
5488     *         otherwise.
5489     */
5490    public boolean performContextClick() {
5491        sendAccessibilityEvent(AccessibilityEvent.TYPE_VIEW_CONTEXT_CLICKED);
5492
5493        boolean handled = false;
5494        ListenerInfo li = mListenerInfo;
5495        if (li != null && li.mOnContextClickListener != null) {
5496            handled = li.mOnContextClickListener.onContextClick(View.this);
5497        }
5498        if (handled) {
5499            performHapticFeedback(HapticFeedbackConstants.CONTEXT_CLICK);
5500        }
5501        return handled;
5502    }
5503
5504    /**
5505     * Performs button-related actions during a touch down event.
5506     *
5507     * @param event The event.
5508     * @return True if the down was consumed.
5509     *
5510     * @hide
5511     */
5512    protected boolean performButtonActionOnTouchDown(MotionEvent event) {
5513        if (event.isFromSource(InputDevice.SOURCE_MOUSE) &&
5514            (event.getButtonState() & MotionEvent.BUTTON_SECONDARY) != 0) {
5515            showContextMenu(event.getX(), event.getY());
5516            mPrivateFlags |= PFLAG_CANCEL_NEXT_UP_EVENT;
5517            return true;
5518        }
5519        return false;
5520    }
5521
5522    /**
5523     * Shows the context menu for this view.
5524     *
5525     * @return {@code true} if the context menu was shown, {@code false}
5526     *         otherwise
5527     * @see #showContextMenu(float, float)
5528     */
5529    public boolean showContextMenu() {
5530        return getParent().showContextMenuForChild(this);
5531    }
5532
5533    /**
5534     * Shows the context menu for this view anchored to the specified
5535     * view-relative coordinate.
5536     *
5537     * @param x the X coordinate in pixels relative to the view to which the
5538     *          menu should be anchored
5539     * @param y the Y coordinate in pixels relative to the view to which the
5540     *          menu should be anchored
5541     * @return {@code true} if the context menu was shown, {@code false}
5542     *         otherwise
5543     */
5544    public boolean showContextMenu(float x, float y) {
5545        return getParent().showContextMenuForChild(this, x, y);
5546    }
5547
5548    /**
5549     * Start an action mode with the default type {@link ActionMode#TYPE_PRIMARY}.
5550     *
5551     * @param callback Callback that will control the lifecycle of the action mode
5552     * @return The new action mode if it is started, null otherwise
5553     *
5554     * @see ActionMode
5555     * @see #startActionMode(android.view.ActionMode.Callback, int)
5556     */
5557    public ActionMode startActionMode(ActionMode.Callback callback) {
5558        return startActionMode(callback, ActionMode.TYPE_PRIMARY);
5559    }
5560
5561    /**
5562     * Start an action mode with the given type.
5563     *
5564     * @param callback Callback that will control the lifecycle of the action mode
5565     * @param type One of {@link ActionMode#TYPE_PRIMARY} or {@link ActionMode#TYPE_FLOATING}.
5566     * @return The new action mode if it is started, null otherwise
5567     *
5568     * @see ActionMode
5569     */
5570    public ActionMode startActionMode(ActionMode.Callback callback, int type) {
5571        ViewParent parent = getParent();
5572        if (parent == null) return null;
5573        try {
5574            return parent.startActionModeForChild(this, callback, type);
5575        } catch (AbstractMethodError ame) {
5576            // Older implementations of custom views might not implement this.
5577            return parent.startActionModeForChild(this, callback);
5578        }
5579    }
5580
5581    /**
5582     * Call {@link Context#startActivityForResult(String, Intent, int, Bundle)} for the View's
5583     * Context, creating a unique View identifier to retrieve the result.
5584     *
5585     * @param intent The Intent to be started.
5586     * @param requestCode The request code to use.
5587     * @hide
5588     */
5589    public void startActivityForResult(Intent intent, int requestCode) {
5590        mStartActivityRequestWho = "@android:view:" + System.identityHashCode(this);
5591        getContext().startActivityForResult(mStartActivityRequestWho, intent, requestCode, null);
5592    }
5593
5594    /**
5595     * If this View corresponds to the calling who, dispatches the activity result.
5596     * @param who The identifier for the targeted View to receive the result.
5597     * @param requestCode The integer request code originally supplied to
5598     *                    startActivityForResult(), allowing you to identify who this
5599     *                    result came from.
5600     * @param resultCode The integer result code returned by the child activity
5601     *                   through its setResult().
5602     * @param data An Intent, which can return result data to the caller
5603     *               (various data can be attached to Intent "extras").
5604     * @return {@code true} if the activity result was dispatched.
5605     * @hide
5606     */
5607    public boolean dispatchActivityResult(
5608            String who, int requestCode, int resultCode, Intent data) {
5609        if (mStartActivityRequestWho != null && mStartActivityRequestWho.equals(who)) {
5610            onActivityResult(requestCode, resultCode, data);
5611            mStartActivityRequestWho = null;
5612            return true;
5613        }
5614        return false;
5615    }
5616
5617    /**
5618     * Receive the result from a previous call to {@link #startActivityForResult(Intent, int)}.
5619     *
5620     * @param requestCode The integer request code originally supplied to
5621     *                    startActivityForResult(), allowing you to identify who this
5622     *                    result came from.
5623     * @param resultCode The integer result code returned by the child activity
5624     *                   through its setResult().
5625     * @param data An Intent, which can return result data to the caller
5626     *               (various data can be attached to Intent "extras").
5627     * @hide
5628     */
5629    public void onActivityResult(int requestCode, int resultCode, Intent data) {
5630        // Do nothing.
5631    }
5632
5633    /**
5634     * Register a callback to be invoked when a hardware key is pressed in this view.
5635     * Key presses in software input methods will generally not trigger the methods of
5636     * this listener.
5637     * @param l the key listener to attach to this view
5638     */
5639    public void setOnKeyListener(OnKeyListener l) {
5640        getListenerInfo().mOnKeyListener = l;
5641    }
5642
5643    /**
5644     * Register a callback to be invoked when a touch event is sent to this view.
5645     * @param l the touch listener to attach to this view
5646     */
5647    public void setOnTouchListener(OnTouchListener l) {
5648        getListenerInfo().mOnTouchListener = l;
5649    }
5650
5651    /**
5652     * Register a callback to be invoked when a generic motion event is sent to this view.
5653     * @param l the generic motion listener to attach to this view
5654     */
5655    public void setOnGenericMotionListener(OnGenericMotionListener l) {
5656        getListenerInfo().mOnGenericMotionListener = l;
5657    }
5658
5659    /**
5660     * Register a callback to be invoked when a hover event is sent to this view.
5661     * @param l the hover listener to attach to this view
5662     */
5663    public void setOnHoverListener(OnHoverListener l) {
5664        getListenerInfo().mOnHoverListener = l;
5665    }
5666
5667    /**
5668     * Register a drag event listener callback object for this View. The parameter is
5669     * an implementation of {@link android.view.View.OnDragListener}. To send a drag event to a
5670     * View, the system calls the
5671     * {@link android.view.View.OnDragListener#onDrag(View,DragEvent)} method.
5672     * @param l An implementation of {@link android.view.View.OnDragListener}.
5673     */
5674    public void setOnDragListener(OnDragListener l) {
5675        getListenerInfo().mOnDragListener = l;
5676    }
5677
5678    /**
5679     * Give this view focus. This will cause
5680     * {@link #onFocusChanged(boolean, int, android.graphics.Rect)} to be called.
5681     *
5682     * Note: this does not check whether this {@link View} should get focus, it just
5683     * gives it focus no matter what.  It should only be called internally by framework
5684     * code that knows what it is doing, namely {@link #requestFocus(int, Rect)}.
5685     *
5686     * @param direction values are {@link View#FOCUS_UP}, {@link View#FOCUS_DOWN},
5687     *        {@link View#FOCUS_LEFT} or {@link View#FOCUS_RIGHT}. This is the direction which
5688     *        focus moved when requestFocus() is called. It may not always
5689     *        apply, in which case use the default View.FOCUS_DOWN.
5690     * @param previouslyFocusedRect The rectangle of the view that had focus
5691     *        prior in this View's coordinate system.
5692     */
5693    void handleFocusGainInternal(@FocusRealDirection int direction, Rect previouslyFocusedRect) {
5694        if (DBG) {
5695            System.out.println(this + " requestFocus()");
5696        }
5697
5698        if ((mPrivateFlags & PFLAG_FOCUSED) == 0) {
5699            mPrivateFlags |= PFLAG_FOCUSED;
5700
5701            View oldFocus = (mAttachInfo != null) ? getRootView().findFocus() : null;
5702
5703            if (mParent != null) {
5704                mParent.requestChildFocus(this, this);
5705            }
5706
5707            if (mAttachInfo != null) {
5708                mAttachInfo.mTreeObserver.dispatchOnGlobalFocusChange(oldFocus, this);
5709            }
5710
5711            onFocusChanged(true, direction, previouslyFocusedRect);
5712            refreshDrawableState();
5713        }
5714    }
5715
5716    /**
5717     * Populates <code>outRect</code> with the hotspot bounds. By default,
5718     * the hotspot bounds are identical to the screen bounds.
5719     *
5720     * @param outRect rect to populate with hotspot bounds
5721     * @hide Only for internal use by views and widgets.
5722     */
5723    public void getHotspotBounds(Rect outRect) {
5724        final Drawable background = getBackground();
5725        if (background != null) {
5726            background.getHotspotBounds(outRect);
5727        } else {
5728            getBoundsOnScreen(outRect);
5729        }
5730    }
5731
5732    /**
5733     * Request that a rectangle of this view be visible on the screen,
5734     * scrolling if necessary just enough.
5735     *
5736     * <p>A View should call this if it maintains some notion of which part
5737     * of its content is interesting.  For example, a text editing view
5738     * should call this when its cursor moves.
5739     *
5740     * @param rectangle The rectangle.
5741     * @return Whether any parent scrolled.
5742     */
5743    public boolean requestRectangleOnScreen(Rect rectangle) {
5744        return requestRectangleOnScreen(rectangle, false);
5745    }
5746
5747    /**
5748     * Request that a rectangle of this view be visible on the screen,
5749     * scrolling if necessary just enough.
5750     *
5751     * <p>A View should call this if it maintains some notion of which part
5752     * of its content is interesting.  For example, a text editing view
5753     * should call this when its cursor moves.
5754     *
5755     * <p>When <code>immediate</code> is set to true, scrolling will not be
5756     * animated.
5757     *
5758     * @param rectangle The rectangle.
5759     * @param immediate True to forbid animated scrolling, false otherwise
5760     * @return Whether any parent scrolled.
5761     */
5762    public boolean requestRectangleOnScreen(Rect rectangle, boolean immediate) {
5763        if (mParent == null) {
5764            return false;
5765        }
5766
5767        View child = this;
5768
5769        RectF position = (mAttachInfo != null) ? mAttachInfo.mTmpTransformRect : new RectF();
5770        position.set(rectangle);
5771
5772        ViewParent parent = mParent;
5773        boolean scrolled = false;
5774        while (parent != null) {
5775            rectangle.set((int) position.left, (int) position.top,
5776                    (int) position.right, (int) position.bottom);
5777
5778            scrolled |= parent.requestChildRectangleOnScreen(child,
5779                    rectangle, immediate);
5780
5781            if (!child.hasIdentityMatrix()) {
5782                child.getMatrix().mapRect(position);
5783            }
5784
5785            position.offset(child.mLeft, child.mTop);
5786
5787            if (!(parent instanceof View)) {
5788                break;
5789            }
5790
5791            View parentView = (View) parent;
5792
5793            position.offset(-parentView.getScrollX(), -parentView.getScrollY());
5794
5795            child = parentView;
5796            parent = child.getParent();
5797        }
5798
5799        return scrolled;
5800    }
5801
5802    /**
5803     * Called when this view wants to give up focus. If focus is cleared
5804     * {@link #onFocusChanged(boolean, int, android.graphics.Rect)} is called.
5805     * <p>
5806     * <strong>Note:</strong> When a View clears focus the framework is trying
5807     * to give focus to the first focusable View from the top. Hence, if this
5808     * View is the first from the top that can take focus, then all callbacks
5809     * related to clearing focus will be invoked after which the framework will
5810     * give focus to this view.
5811     * </p>
5812     */
5813    public void clearFocus() {
5814        if (DBG) {
5815            System.out.println(this + " clearFocus()");
5816        }
5817
5818        clearFocusInternal(null, true, true);
5819    }
5820
5821    /**
5822     * Clears focus from the view, optionally propagating the change up through
5823     * the parent hierarchy and requesting that the root view place new focus.
5824     *
5825     * @param propagate whether to propagate the change up through the parent
5826     *            hierarchy
5827     * @param refocus when propagate is true, specifies whether to request the
5828     *            root view place new focus
5829     */
5830    void clearFocusInternal(View focused, boolean propagate, boolean refocus) {
5831        if ((mPrivateFlags & PFLAG_FOCUSED) != 0) {
5832            mPrivateFlags &= ~PFLAG_FOCUSED;
5833
5834            if (propagate && mParent != null) {
5835                mParent.clearChildFocus(this);
5836            }
5837
5838            onFocusChanged(false, 0, null);
5839            refreshDrawableState();
5840
5841            if (propagate && (!refocus || !rootViewRequestFocus())) {
5842                notifyGlobalFocusCleared(this);
5843            }
5844        }
5845    }
5846
5847    void notifyGlobalFocusCleared(View oldFocus) {
5848        if (oldFocus != null && mAttachInfo != null) {
5849            mAttachInfo.mTreeObserver.dispatchOnGlobalFocusChange(oldFocus, null);
5850        }
5851    }
5852
5853    boolean rootViewRequestFocus() {
5854        final View root = getRootView();
5855        return root != null && root.requestFocus();
5856    }
5857
5858    /**
5859     * Called internally by the view system when a new view is getting focus.
5860     * This is what clears the old focus.
5861     * <p>
5862     * <b>NOTE:</b> The parent view's focused child must be updated manually
5863     * after calling this method. Otherwise, the view hierarchy may be left in
5864     * an inconstent state.
5865     */
5866    void unFocus(View focused) {
5867        if (DBG) {
5868            System.out.println(this + " unFocus()");
5869        }
5870
5871        clearFocusInternal(focused, false, false);
5872    }
5873
5874    /**
5875     * Returns true if this view has focus itself, or is the ancestor of the
5876     * view that has focus.
5877     *
5878     * @return True if this view has or contains focus, false otherwise.
5879     */
5880    @ViewDebug.ExportedProperty(category = "focus")
5881    public boolean hasFocus() {
5882        return (mPrivateFlags & PFLAG_FOCUSED) != 0;
5883    }
5884
5885    /**
5886     * Returns true if this view is focusable or if it contains a reachable View
5887     * for which {@link #hasFocusable()} returns true. A "reachable hasFocusable()"
5888     * is a View whose parents do not block descendants focus.
5889     *
5890     * Only {@link #VISIBLE} views are considered focusable.
5891     *
5892     * @return True if the view is focusable or if the view contains a focusable
5893     *         View, false otherwise.
5894     *
5895     * @see ViewGroup#FOCUS_BLOCK_DESCENDANTS
5896     * @see ViewGroup#getTouchscreenBlocksFocus()
5897     */
5898    public boolean hasFocusable() {
5899        if (!isFocusableInTouchMode()) {
5900            for (ViewParent p = mParent; p instanceof ViewGroup; p = p.getParent()) {
5901                final ViewGroup g = (ViewGroup) p;
5902                if (g.shouldBlockFocusForTouchscreen()) {
5903                    return false;
5904                }
5905            }
5906        }
5907        return (mViewFlags & VISIBILITY_MASK) == VISIBLE && isFocusable();
5908    }
5909
5910    /**
5911     * Called by the view system when the focus state of this view changes.
5912     * When the focus change event is caused by directional navigation, direction
5913     * and previouslyFocusedRect provide insight into where the focus is coming from.
5914     * When overriding, be sure to call up through to the super class so that
5915     * the standard focus handling will occur.
5916     *
5917     * @param gainFocus True if the View has focus; false otherwise.
5918     * @param direction The direction focus has moved when requestFocus()
5919     *                  is called to give this view focus. Values are
5920     *                  {@link #FOCUS_UP}, {@link #FOCUS_DOWN}, {@link #FOCUS_LEFT},
5921     *                  {@link #FOCUS_RIGHT}, {@link #FOCUS_FORWARD}, or {@link #FOCUS_BACKWARD}.
5922     *                  It may not always apply, in which case use the default.
5923     * @param previouslyFocusedRect The rectangle, in this view's coordinate
5924     *        system, of the previously focused view.  If applicable, this will be
5925     *        passed in as finer grained information about where the focus is coming
5926     *        from (in addition to direction).  Will be <code>null</code> otherwise.
5927     */
5928    @CallSuper
5929    protected void onFocusChanged(boolean gainFocus, @FocusDirection int direction,
5930            @Nullable Rect previouslyFocusedRect) {
5931        if (gainFocus) {
5932            sendAccessibilityEvent(AccessibilityEvent.TYPE_VIEW_FOCUSED);
5933        } else {
5934            notifyViewAccessibilityStateChangedIfNeeded(
5935                    AccessibilityEvent.CONTENT_CHANGE_TYPE_UNDEFINED);
5936        }
5937
5938        InputMethodManager imm = InputMethodManager.peekInstance();
5939        if (!gainFocus) {
5940            if (isPressed()) {
5941                setPressed(false);
5942            }
5943            if (imm != null && mAttachInfo != null
5944                    && mAttachInfo.mHasWindowFocus) {
5945                imm.focusOut(this);
5946            }
5947            onFocusLost();
5948        } else if (imm != null && mAttachInfo != null
5949                && mAttachInfo.mHasWindowFocus) {
5950            imm.focusIn(this);
5951        }
5952
5953        invalidate(true);
5954        ListenerInfo li = mListenerInfo;
5955        if (li != null && li.mOnFocusChangeListener != null) {
5956            li.mOnFocusChangeListener.onFocusChange(this, gainFocus);
5957        }
5958
5959        if (mAttachInfo != null) {
5960            mAttachInfo.mKeyDispatchState.reset(this);
5961        }
5962    }
5963
5964    /**
5965     * Sends an accessibility event of the given type. If accessibility is
5966     * not enabled this method has no effect. The default implementation calls
5967     * {@link #onInitializeAccessibilityEvent(AccessibilityEvent)} first
5968     * to populate information about the event source (this View), then calls
5969     * {@link #dispatchPopulateAccessibilityEvent(AccessibilityEvent)} to
5970     * populate the text content of the event source including its descendants,
5971     * and last calls
5972     * {@link ViewParent#requestSendAccessibilityEvent(View, AccessibilityEvent)}
5973     * on its parent to request sending of the event to interested parties.
5974     * <p>
5975     * If an {@link AccessibilityDelegate} has been specified via calling
5976     * {@link #setAccessibilityDelegate(AccessibilityDelegate)} its
5977     * {@link AccessibilityDelegate#sendAccessibilityEvent(View, int)} is
5978     * responsible for handling this call.
5979     * </p>
5980     *
5981     * @param eventType The type of the event to send, as defined by several types from
5982     * {@link android.view.accessibility.AccessibilityEvent}, such as
5983     * {@link android.view.accessibility.AccessibilityEvent#TYPE_VIEW_CLICKED} or
5984     * {@link android.view.accessibility.AccessibilityEvent#TYPE_VIEW_HOVER_ENTER}.
5985     *
5986     * @see #onInitializeAccessibilityEvent(AccessibilityEvent)
5987     * @see #dispatchPopulateAccessibilityEvent(AccessibilityEvent)
5988     * @see ViewParent#requestSendAccessibilityEvent(View, AccessibilityEvent)
5989     * @see AccessibilityDelegate
5990     */
5991    public void sendAccessibilityEvent(int eventType) {
5992        if (mAccessibilityDelegate != null) {
5993            mAccessibilityDelegate.sendAccessibilityEvent(this, eventType);
5994        } else {
5995            sendAccessibilityEventInternal(eventType);
5996        }
5997    }
5998
5999    /**
6000     * Convenience method for sending a {@link AccessibilityEvent#TYPE_ANNOUNCEMENT}
6001     * {@link AccessibilityEvent} to make an announcement which is related to some
6002     * sort of a context change for which none of the events representing UI transitions
6003     * is a good fit. For example, announcing a new page in a book. If accessibility
6004     * is not enabled this method does nothing.
6005     *
6006     * @param text The announcement text.
6007     */
6008    public void announceForAccessibility(CharSequence text) {
6009        if (AccessibilityManager.getInstance(mContext).isEnabled() && mParent != null) {
6010            AccessibilityEvent event = AccessibilityEvent.obtain(
6011                    AccessibilityEvent.TYPE_ANNOUNCEMENT);
6012            onInitializeAccessibilityEvent(event);
6013            event.getText().add(text);
6014            event.setContentDescription(null);
6015            mParent.requestSendAccessibilityEvent(this, event);
6016        }
6017    }
6018
6019    /**
6020     * @see #sendAccessibilityEvent(int)
6021     *
6022     * Note: Called from the default {@link AccessibilityDelegate}.
6023     *
6024     * @hide
6025     */
6026    public void sendAccessibilityEventInternal(int eventType) {
6027        if (AccessibilityManager.getInstance(mContext).isEnabled()) {
6028            sendAccessibilityEventUnchecked(AccessibilityEvent.obtain(eventType));
6029        }
6030    }
6031
6032    /**
6033     * This method behaves exactly as {@link #sendAccessibilityEvent(int)} but
6034     * takes as an argument an empty {@link AccessibilityEvent} and does not
6035     * perform a check whether accessibility is enabled.
6036     * <p>
6037     * If an {@link AccessibilityDelegate} has been specified via calling
6038     * {@link #setAccessibilityDelegate(AccessibilityDelegate)} its
6039     * {@link AccessibilityDelegate#sendAccessibilityEventUnchecked(View, AccessibilityEvent)}
6040     * is responsible for handling this call.
6041     * </p>
6042     *
6043     * @param event The event to send.
6044     *
6045     * @see #sendAccessibilityEvent(int)
6046     */
6047    public void sendAccessibilityEventUnchecked(AccessibilityEvent event) {
6048        if (mAccessibilityDelegate != null) {
6049            mAccessibilityDelegate.sendAccessibilityEventUnchecked(this, event);
6050        } else {
6051            sendAccessibilityEventUncheckedInternal(event);
6052        }
6053    }
6054
6055    /**
6056     * @see #sendAccessibilityEventUnchecked(AccessibilityEvent)
6057     *
6058     * Note: Called from the default {@link AccessibilityDelegate}.
6059     *
6060     * @hide
6061     */
6062    public void sendAccessibilityEventUncheckedInternal(AccessibilityEvent event) {
6063        if (!isShown()) {
6064            return;
6065        }
6066        onInitializeAccessibilityEvent(event);
6067        // Only a subset of accessibility events populates text content.
6068        if ((event.getEventType() & POPULATING_ACCESSIBILITY_EVENT_TYPES) != 0) {
6069            dispatchPopulateAccessibilityEvent(event);
6070        }
6071        // In the beginning we called #isShown(), so we know that getParent() is not null.
6072        getParent().requestSendAccessibilityEvent(this, event);
6073    }
6074
6075    /**
6076     * Dispatches an {@link AccessibilityEvent} to the {@link View} first and then
6077     * to its children for adding their text content to the event. Note that the
6078     * event text is populated in a separate dispatch path since we add to the
6079     * event not only the text of the source but also the text of all its descendants.
6080     * A typical implementation will call
6081     * {@link #onPopulateAccessibilityEvent(AccessibilityEvent)} on the this view
6082     * and then call the {@link #dispatchPopulateAccessibilityEvent(AccessibilityEvent)}
6083     * on each child. Override this method if custom population of the event text
6084     * content is required.
6085     * <p>
6086     * If an {@link AccessibilityDelegate} has been specified via calling
6087     * {@link #setAccessibilityDelegate(AccessibilityDelegate)} its
6088     * {@link AccessibilityDelegate#dispatchPopulateAccessibilityEvent(View, AccessibilityEvent)}
6089     * is responsible for handling this call.
6090     * </p>
6091     * <p>
6092     * <em>Note:</em> Accessibility events of certain types are not dispatched for
6093     * populating the event text via this method. For details refer to {@link AccessibilityEvent}.
6094     * </p>
6095     *
6096     * @param event The event.
6097     *
6098     * @return True if the event population was completed.
6099     */
6100    public boolean dispatchPopulateAccessibilityEvent(AccessibilityEvent event) {
6101        if (mAccessibilityDelegate != null) {
6102            return mAccessibilityDelegate.dispatchPopulateAccessibilityEvent(this, event);
6103        } else {
6104            return dispatchPopulateAccessibilityEventInternal(event);
6105        }
6106    }
6107
6108    /**
6109     * @see #dispatchPopulateAccessibilityEvent(AccessibilityEvent)
6110     *
6111     * Note: Called from the default {@link AccessibilityDelegate}.
6112     *
6113     * @hide
6114     */
6115    public boolean dispatchPopulateAccessibilityEventInternal(AccessibilityEvent event) {
6116        onPopulateAccessibilityEvent(event);
6117        return false;
6118    }
6119
6120    /**
6121     * Called from {@link #dispatchPopulateAccessibilityEvent(AccessibilityEvent)}
6122     * giving a chance to this View to populate the accessibility event with its
6123     * text content. While this method is free to modify event
6124     * attributes other than text content, doing so should normally be performed in
6125     * {@link #onInitializeAccessibilityEvent(AccessibilityEvent)}.
6126     * <p>
6127     * Example: Adding formatted date string to an accessibility event in addition
6128     *          to the text added by the super implementation:
6129     * <pre> public void onPopulateAccessibilityEvent(AccessibilityEvent event) {
6130     *     super.onPopulateAccessibilityEvent(event);
6131     *     final int flags = DateUtils.FORMAT_SHOW_DATE | DateUtils.FORMAT_SHOW_WEEKDAY;
6132     *     String selectedDateUtterance = DateUtils.formatDateTime(mContext,
6133     *         mCurrentDate.getTimeInMillis(), flags);
6134     *     event.getText().add(selectedDateUtterance);
6135     * }</pre>
6136     * <p>
6137     * If an {@link AccessibilityDelegate} has been specified via calling
6138     * {@link #setAccessibilityDelegate(AccessibilityDelegate)} its
6139     * {@link AccessibilityDelegate#onPopulateAccessibilityEvent(View, AccessibilityEvent)}
6140     * is responsible for handling this call.
6141     * </p>
6142     * <p class="note"><strong>Note:</strong> Always call the super implementation before adding
6143     * information to the event, in case the default implementation has basic information to add.
6144     * </p>
6145     *
6146     * @param event The accessibility event which to populate.
6147     *
6148     * @see #sendAccessibilityEvent(int)
6149     * @see #dispatchPopulateAccessibilityEvent(AccessibilityEvent)
6150     */
6151    @CallSuper
6152    public void onPopulateAccessibilityEvent(AccessibilityEvent event) {
6153        if (mAccessibilityDelegate != null) {
6154            mAccessibilityDelegate.onPopulateAccessibilityEvent(this, event);
6155        } else {
6156            onPopulateAccessibilityEventInternal(event);
6157        }
6158    }
6159
6160    /**
6161     * @see #onPopulateAccessibilityEvent(AccessibilityEvent)
6162     *
6163     * Note: Called from the default {@link AccessibilityDelegate}.
6164     *
6165     * @hide
6166     */
6167    public void onPopulateAccessibilityEventInternal(AccessibilityEvent event) {
6168    }
6169
6170    /**
6171     * Initializes an {@link AccessibilityEvent} with information about
6172     * this View which is the event source. In other words, the source of
6173     * an accessibility event is the view whose state change triggered firing
6174     * the event.
6175     * <p>
6176     * Example: Setting the password property of an event in addition
6177     *          to properties set by the super implementation:
6178     * <pre> public void onInitializeAccessibilityEvent(AccessibilityEvent event) {
6179     *     super.onInitializeAccessibilityEvent(event);
6180     *     event.setPassword(true);
6181     * }</pre>
6182     * <p>
6183     * If an {@link AccessibilityDelegate} has been specified via calling
6184     * {@link #setAccessibilityDelegate(AccessibilityDelegate)} its
6185     * {@link AccessibilityDelegate#onInitializeAccessibilityEvent(View, AccessibilityEvent)}
6186     * is responsible for handling this call.
6187     * </p>
6188     * <p class="note"><strong>Note:</strong> Always call the super implementation before adding
6189     * information to the event, in case the default implementation has basic information to add.
6190     * </p>
6191     * @param event The event to initialize.
6192     *
6193     * @see #sendAccessibilityEvent(int)
6194     * @see #dispatchPopulateAccessibilityEvent(AccessibilityEvent)
6195     */
6196    @CallSuper
6197    public void onInitializeAccessibilityEvent(AccessibilityEvent event) {
6198        if (mAccessibilityDelegate != null) {
6199            mAccessibilityDelegate.onInitializeAccessibilityEvent(this, event);
6200        } else {
6201            onInitializeAccessibilityEventInternal(event);
6202        }
6203    }
6204
6205    /**
6206     * @see #onInitializeAccessibilityEvent(AccessibilityEvent)
6207     *
6208     * Note: Called from the default {@link AccessibilityDelegate}.
6209     *
6210     * @hide
6211     */
6212    public void onInitializeAccessibilityEventInternal(AccessibilityEvent event) {
6213        event.setSource(this);
6214        event.setClassName(getAccessibilityClassName());
6215        event.setPackageName(getContext().getPackageName());
6216        event.setEnabled(isEnabled());
6217        event.setContentDescription(mContentDescription);
6218
6219        switch (event.getEventType()) {
6220            case AccessibilityEvent.TYPE_VIEW_FOCUSED: {
6221                ArrayList<View> focusablesTempList = (mAttachInfo != null)
6222                        ? mAttachInfo.mTempArrayList : new ArrayList<View>();
6223                getRootView().addFocusables(focusablesTempList, View.FOCUS_FORWARD, FOCUSABLES_ALL);
6224                event.setItemCount(focusablesTempList.size());
6225                event.setCurrentItemIndex(focusablesTempList.indexOf(this));
6226                if (mAttachInfo != null) {
6227                    focusablesTempList.clear();
6228                }
6229            } break;
6230            case AccessibilityEvent.TYPE_VIEW_TEXT_SELECTION_CHANGED: {
6231                CharSequence text = getIterableTextForAccessibility();
6232                if (text != null && text.length() > 0) {
6233                    event.setFromIndex(getAccessibilitySelectionStart());
6234                    event.setToIndex(getAccessibilitySelectionEnd());
6235                    event.setItemCount(text.length());
6236                }
6237            } break;
6238        }
6239    }
6240
6241    /**
6242     * Returns an {@link AccessibilityNodeInfo} representing this view from the
6243     * point of view of an {@link android.accessibilityservice.AccessibilityService}.
6244     * This method is responsible for obtaining an accessibility node info from a
6245     * pool of reusable instances and calling
6246     * {@link #onInitializeAccessibilityNodeInfo(AccessibilityNodeInfo)} on this view to
6247     * initialize the former.
6248     * <p>
6249     * Note: The client is responsible for recycling the obtained instance by calling
6250     *       {@link AccessibilityNodeInfo#recycle()} to minimize object creation.
6251     * </p>
6252     *
6253     * @return A populated {@link AccessibilityNodeInfo}.
6254     *
6255     * @see AccessibilityNodeInfo
6256     */
6257    public AccessibilityNodeInfo createAccessibilityNodeInfo() {
6258        if (mAccessibilityDelegate != null) {
6259            return mAccessibilityDelegate.createAccessibilityNodeInfo(this);
6260        } else {
6261            return createAccessibilityNodeInfoInternal();
6262        }
6263    }
6264
6265    /**
6266     * @see #createAccessibilityNodeInfo()
6267     *
6268     * @hide
6269     */
6270    public AccessibilityNodeInfo createAccessibilityNodeInfoInternal() {
6271        AccessibilityNodeProvider provider = getAccessibilityNodeProvider();
6272        if (provider != null) {
6273            return provider.createAccessibilityNodeInfo(AccessibilityNodeProvider.HOST_VIEW_ID);
6274        } else {
6275            AccessibilityNodeInfo info = AccessibilityNodeInfo.obtain(this);
6276            onInitializeAccessibilityNodeInfo(info);
6277            return info;
6278        }
6279    }
6280
6281    /**
6282     * Initializes an {@link AccessibilityNodeInfo} with information about this view.
6283     * The base implementation sets:
6284     * <ul>
6285     *   <li>{@link AccessibilityNodeInfo#setParent(View)},</li>
6286     *   <li>{@link AccessibilityNodeInfo#setBoundsInParent(Rect)},</li>
6287     *   <li>{@link AccessibilityNodeInfo#setBoundsInScreen(Rect)},</li>
6288     *   <li>{@link AccessibilityNodeInfo#setPackageName(CharSequence)},</li>
6289     *   <li>{@link AccessibilityNodeInfo#setClassName(CharSequence)},</li>
6290     *   <li>{@link AccessibilityNodeInfo#setContentDescription(CharSequence)},</li>
6291     *   <li>{@link AccessibilityNodeInfo#setEnabled(boolean)},</li>
6292     *   <li>{@link AccessibilityNodeInfo#setClickable(boolean)},</li>
6293     *   <li>{@link AccessibilityNodeInfo#setFocusable(boolean)},</li>
6294     *   <li>{@link AccessibilityNodeInfo#setFocused(boolean)},</li>
6295     *   <li>{@link AccessibilityNodeInfo#setLongClickable(boolean)},</li>
6296     *   <li>{@link AccessibilityNodeInfo#setSelected(boolean)},</li>
6297     *   <li>{@link AccessibilityNodeInfo#setContextClickable(boolean)}</li>
6298     * </ul>
6299     * <p>
6300     * Subclasses should override this method, call the super implementation,
6301     * and set additional attributes.
6302     * </p>
6303     * <p>
6304     * If an {@link AccessibilityDelegate} has been specified via calling
6305     * {@link #setAccessibilityDelegate(AccessibilityDelegate)} its
6306     * {@link AccessibilityDelegate#onInitializeAccessibilityNodeInfo(View, AccessibilityNodeInfo)}
6307     * is responsible for handling this call.
6308     * </p>
6309     *
6310     * @param info The instance to initialize.
6311     */
6312    @CallSuper
6313    public void onInitializeAccessibilityNodeInfo(AccessibilityNodeInfo info) {
6314        if (mAccessibilityDelegate != null) {
6315            mAccessibilityDelegate.onInitializeAccessibilityNodeInfo(this, info);
6316        } else {
6317            onInitializeAccessibilityNodeInfoInternal(info);
6318        }
6319    }
6320
6321    /**
6322     * Gets the location of this view in screen coordinates.
6323     *
6324     * @param outRect The output location
6325     * @hide
6326     */
6327    public void getBoundsOnScreen(Rect outRect) {
6328        getBoundsOnScreen(outRect, false);
6329    }
6330
6331    /**
6332     * Gets the location of this view in screen coordinates.
6333     *
6334     * @param outRect The output location
6335     * @param clipToParent Whether to clip child bounds to the parent ones.
6336     * @hide
6337     */
6338    public void getBoundsOnScreen(Rect outRect, boolean clipToParent) {
6339        if (mAttachInfo == null) {
6340            return;
6341        }
6342
6343        RectF position = mAttachInfo.mTmpTransformRect;
6344        position.set(0, 0, mRight - mLeft, mBottom - mTop);
6345
6346        if (!hasIdentityMatrix()) {
6347            getMatrix().mapRect(position);
6348        }
6349
6350        position.offset(mLeft, mTop);
6351
6352        ViewParent parent = mParent;
6353        while (parent instanceof View) {
6354            View parentView = (View) parent;
6355
6356            position.offset(-parentView.mScrollX, -parentView.mScrollY);
6357
6358            if (clipToParent) {
6359                position.left = Math.max(position.left, 0);
6360                position.top = Math.max(position.top, 0);
6361                position.right = Math.min(position.right, parentView.getWidth());
6362                position.bottom = Math.min(position.bottom, parentView.getHeight());
6363            }
6364
6365            if (!parentView.hasIdentityMatrix()) {
6366                parentView.getMatrix().mapRect(position);
6367            }
6368
6369            position.offset(parentView.mLeft, parentView.mTop);
6370
6371            parent = parentView.mParent;
6372        }
6373
6374        if (parent instanceof ViewRootImpl) {
6375            ViewRootImpl viewRootImpl = (ViewRootImpl) parent;
6376            position.offset(0, -viewRootImpl.mCurScrollY);
6377        }
6378
6379        position.offset(mAttachInfo.mWindowLeft, mAttachInfo.mWindowTop);
6380
6381        outRect.set(Math.round(position.left), Math.round(position.top),
6382                Math.round(position.right), Math.round(position.bottom));
6383    }
6384
6385    /**
6386     * Return the class name of this object to be used for accessibility purposes.
6387     * Subclasses should only override this if they are implementing something that
6388     * should be seen as a completely new class of view when used by accessibility,
6389     * unrelated to the class it is deriving from.  This is used to fill in
6390     * {@link AccessibilityNodeInfo#setClassName AccessibilityNodeInfo.setClassName}.
6391     */
6392    public CharSequence getAccessibilityClassName() {
6393        return View.class.getName();
6394    }
6395
6396    /**
6397     * Called when assist structure is being retrieved from a view as part of
6398     * {@link android.app.Activity#onProvideAssistData Activity.onProvideAssistData}.
6399     * @param structure Fill in with structured view data.  The default implementation
6400     * fills in all data that can be inferred from the view itself.
6401     */
6402    public void onProvideStructure(ViewStructure structure) {
6403        final int id = mID;
6404        if (id > 0 && (id&0xff000000) != 0 && (id&0x00ff0000) != 0
6405                && (id&0x0000ffff) != 0) {
6406            String pkg, type, entry;
6407            try {
6408                final Resources res = getResources();
6409                entry = res.getResourceEntryName(id);
6410                type = res.getResourceTypeName(id);
6411                pkg = res.getResourcePackageName(id);
6412            } catch (Resources.NotFoundException e) {
6413                entry = type = pkg = null;
6414            }
6415            structure.setId(id, pkg, type, entry);
6416        } else {
6417            structure.setId(id, null, null, null);
6418        }
6419        structure.setDimens(mLeft, mTop, mScrollX, mScrollY, mRight - mLeft, mBottom - mTop);
6420        if (!hasIdentityMatrix()) {
6421            structure.setTransformation(getMatrix());
6422        }
6423        structure.setElevation(getZ());
6424        structure.setVisibility(getVisibility());
6425        structure.setEnabled(isEnabled());
6426        if (isClickable()) {
6427            structure.setClickable(true);
6428        }
6429        if (isFocusable()) {
6430            structure.setFocusable(true);
6431        }
6432        if (isFocused()) {
6433            structure.setFocused(true);
6434        }
6435        if (isAccessibilityFocused()) {
6436            structure.setAccessibilityFocused(true);
6437        }
6438        if (isSelected()) {
6439            structure.setSelected(true);
6440        }
6441        if (isActivated()) {
6442            structure.setActivated(true);
6443        }
6444        if (isLongClickable()) {
6445            structure.setLongClickable(true);
6446        }
6447        if (this instanceof Checkable) {
6448            structure.setCheckable(true);
6449            if (((Checkable)this).isChecked()) {
6450                structure.setChecked(true);
6451            }
6452        }
6453        if (isContextClickable()) {
6454            structure.setContextClickable(true);
6455        }
6456        structure.setClassName(getAccessibilityClassName().toString());
6457        structure.setContentDescription(getContentDescription());
6458    }
6459
6460    /**
6461     * Called when assist structure is being retrieved from a view as part of
6462     * {@link android.app.Activity#onProvideAssistData Activity.onProvideAssistData} to
6463     * generate additional virtual structure under this view.  The defaullt implementation
6464     * uses {@link #getAccessibilityNodeProvider()} to try to generate this from the
6465     * view's virtual accessibility nodes, if any.  You can override this for a more
6466     * optimal implementation providing this data.
6467     */
6468    public void onProvideVirtualStructure(ViewStructure structure) {
6469        AccessibilityNodeProvider provider = getAccessibilityNodeProvider();
6470        if (provider != null) {
6471            AccessibilityNodeInfo info = createAccessibilityNodeInfo();
6472            structure.setChildCount(1);
6473            ViewStructure root = structure.newChild(0);
6474            populateVirtualStructure(root, provider, info);
6475            info.recycle();
6476        }
6477    }
6478
6479    private void populateVirtualStructure(ViewStructure structure,
6480            AccessibilityNodeProvider provider, AccessibilityNodeInfo info) {
6481        structure.setId(AccessibilityNodeInfo.getVirtualDescendantId(info.getSourceNodeId()),
6482                null, null, null);
6483        Rect rect = structure.getTempRect();
6484        info.getBoundsInParent(rect);
6485        structure.setDimens(rect.left, rect.top, 0, 0, rect.width(), rect.height());
6486        structure.setVisibility(VISIBLE);
6487        structure.setEnabled(info.isEnabled());
6488        if (info.isClickable()) {
6489            structure.setClickable(true);
6490        }
6491        if (info.isFocusable()) {
6492            structure.setFocusable(true);
6493        }
6494        if (info.isFocused()) {
6495            structure.setFocused(true);
6496        }
6497        if (info.isAccessibilityFocused()) {
6498            structure.setAccessibilityFocused(true);
6499        }
6500        if (info.isSelected()) {
6501            structure.setSelected(true);
6502        }
6503        if (info.isLongClickable()) {
6504            structure.setLongClickable(true);
6505        }
6506        if (info.isCheckable()) {
6507            structure.setCheckable(true);
6508            if (info.isChecked()) {
6509                structure.setChecked(true);
6510            }
6511        }
6512        if (info.isContextClickable()) {
6513            structure.setContextClickable(true);
6514        }
6515        CharSequence cname = info.getClassName();
6516        structure.setClassName(cname != null ? cname.toString() : null);
6517        structure.setContentDescription(info.getContentDescription());
6518        if (info.getText() != null || info.getError() != null) {
6519            structure.setText(info.getText(), info.getTextSelectionStart(),
6520                    info.getTextSelectionEnd());
6521        }
6522        final int NCHILDREN = info.getChildCount();
6523        if (NCHILDREN > 0) {
6524            structure.setChildCount(NCHILDREN);
6525            for (int i=0; i<NCHILDREN; i++) {
6526                AccessibilityNodeInfo cinfo = provider.createAccessibilityNodeInfo(
6527                        AccessibilityNodeInfo.getVirtualDescendantId(info.getChildId(i)));
6528                ViewStructure child = structure.newChild(i);
6529                populateVirtualStructure(child, provider, cinfo);
6530                cinfo.recycle();
6531            }
6532        }
6533    }
6534
6535    /**
6536     * Dispatch creation of {@link ViewStructure} down the hierarchy.  The default
6537     * implementation calls {@link #onProvideStructure} and
6538     * {@link #onProvideVirtualStructure}.
6539     */
6540    public void dispatchProvideStructure(ViewStructure structure) {
6541        if (!isAssistBlocked()) {
6542            onProvideStructure(structure);
6543            onProvideVirtualStructure(structure);
6544        } else {
6545            structure.setClassName(getAccessibilityClassName().toString());
6546            structure.setAssistBlocked(true);
6547        }
6548    }
6549
6550    /**
6551     * @see #onInitializeAccessibilityNodeInfo(AccessibilityNodeInfo)
6552     *
6553     * Note: Called from the default {@link AccessibilityDelegate}.
6554     *
6555     * @hide
6556     */
6557    public void onInitializeAccessibilityNodeInfoInternal(AccessibilityNodeInfo info) {
6558        if (mAttachInfo == null) {
6559            return;
6560        }
6561
6562        Rect bounds = mAttachInfo.mTmpInvalRect;
6563
6564        getDrawingRect(bounds);
6565        info.setBoundsInParent(bounds);
6566
6567        getBoundsOnScreen(bounds, true);
6568        info.setBoundsInScreen(bounds);
6569
6570        ViewParent parent = getParentForAccessibility();
6571        if (parent instanceof View) {
6572            info.setParent((View) parent);
6573        }
6574
6575        if (mID != View.NO_ID) {
6576            View rootView = getRootView();
6577            if (rootView == null) {
6578                rootView = this;
6579            }
6580
6581            View label = rootView.findLabelForView(this, mID);
6582            if (label != null) {
6583                info.setLabeledBy(label);
6584            }
6585
6586            if ((mAttachInfo.mAccessibilityFetchFlags
6587                    & AccessibilityNodeInfo.FLAG_REPORT_VIEW_IDS) != 0
6588                    && Resources.resourceHasPackage(mID)) {
6589                try {
6590                    String viewId = getResources().getResourceName(mID);
6591                    info.setViewIdResourceName(viewId);
6592                } catch (Resources.NotFoundException nfe) {
6593                    /* ignore */
6594                }
6595            }
6596        }
6597
6598        if (mLabelForId != View.NO_ID) {
6599            View rootView = getRootView();
6600            if (rootView == null) {
6601                rootView = this;
6602            }
6603            View labeled = rootView.findViewInsideOutShouldExist(this, mLabelForId);
6604            if (labeled != null) {
6605                info.setLabelFor(labeled);
6606            }
6607        }
6608
6609        if (mAccessibilityTraversalBeforeId != View.NO_ID) {
6610            View rootView = getRootView();
6611            if (rootView == null) {
6612                rootView = this;
6613            }
6614            View next = rootView.findViewInsideOutShouldExist(this,
6615                    mAccessibilityTraversalBeforeId);
6616            if (next != null && next.includeForAccessibility()) {
6617                info.setTraversalBefore(next);
6618            }
6619        }
6620
6621        if (mAccessibilityTraversalAfterId != View.NO_ID) {
6622            View rootView = getRootView();
6623            if (rootView == null) {
6624                rootView = this;
6625            }
6626            View next = rootView.findViewInsideOutShouldExist(this,
6627                    mAccessibilityTraversalAfterId);
6628            if (next != null && next.includeForAccessibility()) {
6629                info.setTraversalAfter(next);
6630            }
6631        }
6632
6633        info.setVisibleToUser(isVisibleToUser());
6634
6635        info.setPackageName(mContext.getPackageName());
6636        info.setClassName(getAccessibilityClassName());
6637        info.setContentDescription(getContentDescription());
6638
6639        info.setEnabled(isEnabled());
6640        info.setClickable(isClickable());
6641        info.setFocusable(isFocusable());
6642        info.setFocused(isFocused());
6643        info.setAccessibilityFocused(isAccessibilityFocused());
6644        info.setSelected(isSelected());
6645        info.setLongClickable(isLongClickable());
6646        info.setContextClickable(isContextClickable());
6647        info.setLiveRegion(getAccessibilityLiveRegion());
6648
6649        // TODO: These make sense only if we are in an AdapterView but all
6650        // views can be selected. Maybe from accessibility perspective
6651        // we should report as selectable view in an AdapterView.
6652        info.addAction(AccessibilityNodeInfo.ACTION_SELECT);
6653        info.addAction(AccessibilityNodeInfo.ACTION_CLEAR_SELECTION);
6654
6655        if (isFocusable()) {
6656            if (isFocused()) {
6657                info.addAction(AccessibilityNodeInfo.ACTION_CLEAR_FOCUS);
6658            } else {
6659                info.addAction(AccessibilityNodeInfo.ACTION_FOCUS);
6660            }
6661        }
6662
6663        if (!isAccessibilityFocused()) {
6664            info.addAction(AccessibilityNodeInfo.ACTION_ACCESSIBILITY_FOCUS);
6665        } else {
6666            info.addAction(AccessibilityNodeInfo.ACTION_CLEAR_ACCESSIBILITY_FOCUS);
6667        }
6668
6669        if (isClickable() && isEnabled()) {
6670            info.addAction(AccessibilityNodeInfo.ACTION_CLICK);
6671        }
6672
6673        if (isLongClickable() && isEnabled()) {
6674            info.addAction(AccessibilityNodeInfo.ACTION_LONG_CLICK);
6675        }
6676
6677        if (isContextClickable() && isEnabled()) {
6678            info.addAction(AccessibilityAction.ACTION_CONTEXT_CLICK);
6679        }
6680
6681        CharSequence text = getIterableTextForAccessibility();
6682        if (text != null && text.length() > 0) {
6683            info.setTextSelection(getAccessibilitySelectionStart(), getAccessibilitySelectionEnd());
6684
6685            info.addAction(AccessibilityNodeInfo.ACTION_SET_SELECTION);
6686            info.addAction(AccessibilityNodeInfo.ACTION_NEXT_AT_MOVEMENT_GRANULARITY);
6687            info.addAction(AccessibilityNodeInfo.ACTION_PREVIOUS_AT_MOVEMENT_GRANULARITY);
6688            info.setMovementGranularities(AccessibilityNodeInfo.MOVEMENT_GRANULARITY_CHARACTER
6689                    | AccessibilityNodeInfo.MOVEMENT_GRANULARITY_WORD
6690                    | AccessibilityNodeInfo.MOVEMENT_GRANULARITY_PARAGRAPH);
6691        }
6692
6693        info.addAction(AccessibilityAction.ACTION_SHOW_ON_SCREEN);
6694    }
6695
6696    private View findLabelForView(View view, int labeledId) {
6697        if (mMatchLabelForPredicate == null) {
6698            mMatchLabelForPredicate = new MatchLabelForPredicate();
6699        }
6700        mMatchLabelForPredicate.mLabeledId = labeledId;
6701        return findViewByPredicateInsideOut(view, mMatchLabelForPredicate);
6702    }
6703
6704    /**
6705     * Computes whether this view is visible to the user. Such a view is
6706     * attached, visible, all its predecessors are visible, it is not clipped
6707     * entirely by its predecessors, and has an alpha greater than zero.
6708     *
6709     * @return Whether the view is visible on the screen.
6710     *
6711     * @hide
6712     */
6713    protected boolean isVisibleToUser() {
6714        return isVisibleToUser(null);
6715    }
6716
6717    /**
6718     * Computes whether the given portion of this view is visible to the user.
6719     * Such a view is attached, visible, all its predecessors are visible,
6720     * has an alpha greater than zero, and the specified portion is not
6721     * clipped entirely by its predecessors.
6722     *
6723     * @param boundInView the portion of the view to test; coordinates should be relative; may be
6724     *                    <code>null</code>, and the entire view will be tested in this case.
6725     *                    When <code>true</code> is returned by the function, the actual visible
6726     *                    region will be stored in this parameter; that is, if boundInView is fully
6727     *                    contained within the view, no modification will be made, otherwise regions
6728     *                    outside of the visible area of the view will be clipped.
6729     *
6730     * @return Whether the specified portion of the view is visible on the screen.
6731     *
6732     * @hide
6733     */
6734    protected boolean isVisibleToUser(Rect boundInView) {
6735        if (mAttachInfo != null) {
6736            // Attached to invisible window means this view is not visible.
6737            if (mAttachInfo.mWindowVisibility != View.VISIBLE) {
6738                return false;
6739            }
6740            // An invisible predecessor or one with alpha zero means
6741            // that this view is not visible to the user.
6742            Object current = this;
6743            while (current instanceof View) {
6744                View view = (View) current;
6745                // We have attach info so this view is attached and there is no
6746                // need to check whether we reach to ViewRootImpl on the way up.
6747                if (view.getAlpha() <= 0 || view.getTransitionAlpha() <= 0 ||
6748                        view.getVisibility() != VISIBLE) {
6749                    return false;
6750                }
6751                current = view.mParent;
6752            }
6753            // Check if the view is entirely covered by its predecessors.
6754            Rect visibleRect = mAttachInfo.mTmpInvalRect;
6755            Point offset = mAttachInfo.mPoint;
6756            if (!getGlobalVisibleRect(visibleRect, offset)) {
6757                return false;
6758            }
6759            // Check if the visible portion intersects the rectangle of interest.
6760            if (boundInView != null) {
6761                visibleRect.offset(-offset.x, -offset.y);
6762                return boundInView.intersect(visibleRect);
6763            }
6764            return true;
6765        }
6766        return false;
6767    }
6768
6769    /**
6770     * Returns the delegate for implementing accessibility support via
6771     * composition. For more details see {@link AccessibilityDelegate}.
6772     *
6773     * @return The delegate, or null if none set.
6774     *
6775     * @hide
6776     */
6777    public AccessibilityDelegate getAccessibilityDelegate() {
6778        return mAccessibilityDelegate;
6779    }
6780
6781    /**
6782     * Sets a delegate for implementing accessibility support via composition
6783     * (as opposed to inheritance). For more details, see
6784     * {@link AccessibilityDelegate}.
6785     * <p>
6786     * <strong>Note:</strong> On platform versions prior to
6787     * {@link android.os.Build.VERSION_CODES#M API 23}, delegate methods on
6788     * views in the {@code android.widget.*} package are called <i>before</i>
6789     * host methods. This prevents certain properties such as class name from
6790     * being modified by overriding
6791     * {@link AccessibilityDelegate#onInitializeAccessibilityNodeInfo(View, AccessibilityNodeInfo)},
6792     * as any changes will be overwritten by the host class.
6793     * <p>
6794     * Starting in {@link android.os.Build.VERSION_CODES#M API 23}, delegate
6795     * methods are called <i>after</i> host methods, which all properties to be
6796     * modified without being overwritten by the host class.
6797     *
6798     * @param delegate the object to which accessibility method calls should be
6799     *                 delegated
6800     * @see AccessibilityDelegate
6801     */
6802    public void setAccessibilityDelegate(@Nullable AccessibilityDelegate delegate) {
6803        mAccessibilityDelegate = delegate;
6804    }
6805
6806    /**
6807     * Gets the provider for managing a virtual view hierarchy rooted at this View
6808     * and reported to {@link android.accessibilityservice.AccessibilityService}s
6809     * that explore the window content.
6810     * <p>
6811     * If this method returns an instance, this instance is responsible for managing
6812     * {@link AccessibilityNodeInfo}s describing the virtual sub-tree rooted at this
6813     * View including the one representing the View itself. Similarly the returned
6814     * instance is responsible for performing accessibility actions on any virtual
6815     * view or the root view itself.
6816     * </p>
6817     * <p>
6818     * If an {@link AccessibilityDelegate} has been specified via calling
6819     * {@link #setAccessibilityDelegate(AccessibilityDelegate)} its
6820     * {@link AccessibilityDelegate#getAccessibilityNodeProvider(View)}
6821     * is responsible for handling this call.
6822     * </p>
6823     *
6824     * @return The provider.
6825     *
6826     * @see AccessibilityNodeProvider
6827     */
6828    public AccessibilityNodeProvider getAccessibilityNodeProvider() {
6829        if (mAccessibilityDelegate != null) {
6830            return mAccessibilityDelegate.getAccessibilityNodeProvider(this);
6831        } else {
6832            return null;
6833        }
6834    }
6835
6836    /**
6837     * Gets the unique identifier of this view on the screen for accessibility purposes.
6838     * If this {@link View} is not attached to any window, {@value #NO_ID} is returned.
6839     *
6840     * @return The view accessibility id.
6841     *
6842     * @hide
6843     */
6844    public int getAccessibilityViewId() {
6845        if (mAccessibilityViewId == NO_ID) {
6846            mAccessibilityViewId = sNextAccessibilityViewId++;
6847        }
6848        return mAccessibilityViewId;
6849    }
6850
6851    /**
6852     * Gets the unique identifier of the window in which this View reseides.
6853     *
6854     * @return The window accessibility id.
6855     *
6856     * @hide
6857     */
6858    public int getAccessibilityWindowId() {
6859        return mAttachInfo != null ? mAttachInfo.mAccessibilityWindowId
6860                : AccessibilityNodeInfo.UNDEFINED_ITEM_ID;
6861    }
6862
6863    /**
6864     * Returns the {@link View}'s content description.
6865     * <p>
6866     * <strong>Note:</strong> Do not override this method, as it will have no
6867     * effect on the content description presented to accessibility services.
6868     * You must call {@link #setContentDescription(CharSequence)} to modify the
6869     * content description.
6870     *
6871     * @return the content description
6872     * @see #setContentDescription(CharSequence)
6873     * @attr ref android.R.styleable#View_contentDescription
6874     */
6875    @ViewDebug.ExportedProperty(category = "accessibility")
6876    public CharSequence getContentDescription() {
6877        return mContentDescription;
6878    }
6879
6880    /**
6881     * Sets the {@link View}'s content description.
6882     * <p>
6883     * A content description briefly describes the view and is primarily used
6884     * for accessibility support to determine how a view should be presented to
6885     * the user. In the case of a view with no textual representation, such as
6886     * {@link android.widget.ImageButton}, a useful content description
6887     * explains what the view does. For example, an image button with a phone
6888     * icon that is used to place a call may use "Call" as its content
6889     * description. An image of a floppy disk that is used to save a file may
6890     * use "Save".
6891     *
6892     * @param contentDescription The content description.
6893     * @see #getContentDescription()
6894     * @attr ref android.R.styleable#View_contentDescription
6895     */
6896    @RemotableViewMethod
6897    public void setContentDescription(CharSequence contentDescription) {
6898        if (mContentDescription == null) {
6899            if (contentDescription == null) {
6900                return;
6901            }
6902        } else if (mContentDescription.equals(contentDescription)) {
6903            return;
6904        }
6905        mContentDescription = contentDescription;
6906        final boolean nonEmptyDesc = contentDescription != null && contentDescription.length() > 0;
6907        if (nonEmptyDesc && getImportantForAccessibility() == IMPORTANT_FOR_ACCESSIBILITY_AUTO) {
6908            setImportantForAccessibility(IMPORTANT_FOR_ACCESSIBILITY_YES);
6909            notifySubtreeAccessibilityStateChangedIfNeeded();
6910        } else {
6911            notifyViewAccessibilityStateChangedIfNeeded(
6912                    AccessibilityEvent.CONTENT_CHANGE_TYPE_CONTENT_DESCRIPTION);
6913        }
6914    }
6915
6916    /**
6917     * Sets the id of a view before which this one is visited in accessibility traversal.
6918     * A screen-reader must visit the content of this view before the content of the one
6919     * it precedes. For example, if view B is set to be before view A, then a screen-reader
6920     * will traverse the entire content of B before traversing the entire content of A,
6921     * regardles of what traversal strategy it is using.
6922     * <p>
6923     * Views that do not have specified before/after relationships are traversed in order
6924     * determined by the screen-reader.
6925     * </p>
6926     * <p>
6927     * Setting that this view is before a view that is not important for accessibility
6928     * or if this view is not important for accessibility will have no effect as the
6929     * screen-reader is not aware of unimportant views.
6930     * </p>
6931     *
6932     * @param beforeId The id of a view this one precedes in accessibility traversal.
6933     *
6934     * @attr ref android.R.styleable#View_accessibilityTraversalBefore
6935     *
6936     * @see #setImportantForAccessibility(int)
6937     */
6938    @RemotableViewMethod
6939    public void setAccessibilityTraversalBefore(int beforeId) {
6940        if (mAccessibilityTraversalBeforeId == beforeId) {
6941            return;
6942        }
6943        mAccessibilityTraversalBeforeId = beforeId;
6944        notifyViewAccessibilityStateChangedIfNeeded(
6945                AccessibilityEvent.CONTENT_CHANGE_TYPE_UNDEFINED);
6946    }
6947
6948    /**
6949     * Gets the id of a view before which this one is visited in accessibility traversal.
6950     *
6951     * @return The id of a view this one precedes in accessibility traversal if
6952     *         specified, otherwise {@link #NO_ID}.
6953     *
6954     * @see #setAccessibilityTraversalBefore(int)
6955     */
6956    public int getAccessibilityTraversalBefore() {
6957        return mAccessibilityTraversalBeforeId;
6958    }
6959
6960    /**
6961     * Sets the id of a view after which this one is visited in accessibility traversal.
6962     * A screen-reader must visit the content of the other view before the content of this
6963     * one. For example, if view B is set to be after view A, then a screen-reader
6964     * will traverse the entire content of A before traversing the entire content of B,
6965     * regardles of what traversal strategy it is using.
6966     * <p>
6967     * Views that do not have specified before/after relationships are traversed in order
6968     * determined by the screen-reader.
6969     * </p>
6970     * <p>
6971     * Setting that this view is after a view that is not important for accessibility
6972     * or if this view is not important for accessibility will have no effect as the
6973     * screen-reader is not aware of unimportant views.
6974     * </p>
6975     *
6976     * @param afterId The id of a view this one succedees in accessibility traversal.
6977     *
6978     * @attr ref android.R.styleable#View_accessibilityTraversalAfter
6979     *
6980     * @see #setImportantForAccessibility(int)
6981     */
6982    @RemotableViewMethod
6983    public void setAccessibilityTraversalAfter(int afterId) {
6984        if (mAccessibilityTraversalAfterId == afterId) {
6985            return;
6986        }
6987        mAccessibilityTraversalAfterId = afterId;
6988        notifyViewAccessibilityStateChangedIfNeeded(
6989                AccessibilityEvent.CONTENT_CHANGE_TYPE_UNDEFINED);
6990    }
6991
6992    /**
6993     * Gets the id of a view after which this one is visited in accessibility traversal.
6994     *
6995     * @return The id of a view this one succeedes in accessibility traversal if
6996     *         specified, otherwise {@link #NO_ID}.
6997     *
6998     * @see #setAccessibilityTraversalAfter(int)
6999     */
7000    public int getAccessibilityTraversalAfter() {
7001        return mAccessibilityTraversalAfterId;
7002    }
7003
7004    /**
7005     * Gets the id of a view for which this view serves as a label for
7006     * accessibility purposes.
7007     *
7008     * @return The labeled view id.
7009     */
7010    @ViewDebug.ExportedProperty(category = "accessibility")
7011    public int getLabelFor() {
7012        return mLabelForId;
7013    }
7014
7015    /**
7016     * Sets the id of a view for which this view serves as a label for
7017     * accessibility purposes.
7018     *
7019     * @param id The labeled view id.
7020     */
7021    @RemotableViewMethod
7022    public void setLabelFor(@IdRes int id) {
7023        if (mLabelForId == id) {
7024            return;
7025        }
7026        mLabelForId = id;
7027        if (mLabelForId != View.NO_ID
7028                && mID == View.NO_ID) {
7029            mID = generateViewId();
7030        }
7031        notifyViewAccessibilityStateChangedIfNeeded(
7032                AccessibilityEvent.CONTENT_CHANGE_TYPE_UNDEFINED);
7033    }
7034
7035    /**
7036     * Invoked whenever this view loses focus, either by losing window focus or by losing
7037     * focus within its window. This method can be used to clear any state tied to the
7038     * focus. For instance, if a button is held pressed with the trackball and the window
7039     * loses focus, this method can be used to cancel the press.
7040     *
7041     * Subclasses of View overriding this method should always call super.onFocusLost().
7042     *
7043     * @see #onFocusChanged(boolean, int, android.graphics.Rect)
7044     * @see #onWindowFocusChanged(boolean)
7045     *
7046     * @hide pending API council approval
7047     */
7048    @CallSuper
7049    protected void onFocusLost() {
7050        resetPressedState();
7051    }
7052
7053    private void resetPressedState() {
7054        if ((mViewFlags & ENABLED_MASK) == DISABLED) {
7055            return;
7056        }
7057
7058        if (isPressed()) {
7059            setPressed(false);
7060
7061            if (!mHasPerformedLongPress) {
7062                removeLongPressCallback();
7063            }
7064        }
7065    }
7066
7067    /**
7068     * Returns true if this view has focus
7069     *
7070     * @return True if this view has focus, false otherwise.
7071     */
7072    @ViewDebug.ExportedProperty(category = "focus")
7073    public boolean isFocused() {
7074        return (mPrivateFlags & PFLAG_FOCUSED) != 0;
7075    }
7076
7077    /**
7078     * Find the view in the hierarchy rooted at this view that currently has
7079     * focus.
7080     *
7081     * @return The view that currently has focus, or null if no focused view can
7082     *         be found.
7083     */
7084    public View findFocus() {
7085        return (mPrivateFlags & PFLAG_FOCUSED) != 0 ? this : null;
7086    }
7087
7088    /**
7089     * Indicates whether this view is one of the set of scrollable containers in
7090     * its window.
7091     *
7092     * @return whether this view is one of the set of scrollable containers in
7093     * its window
7094     *
7095     * @attr ref android.R.styleable#View_isScrollContainer
7096     */
7097    public boolean isScrollContainer() {
7098        return (mPrivateFlags & PFLAG_SCROLL_CONTAINER_ADDED) != 0;
7099    }
7100
7101    /**
7102     * Change whether this view is one of the set of scrollable containers in
7103     * its window.  This will be used to determine whether the window can
7104     * resize or must pan when a soft input area is open -- scrollable
7105     * containers allow the window to use resize mode since the container
7106     * will appropriately shrink.
7107     *
7108     * @attr ref android.R.styleable#View_isScrollContainer
7109     */
7110    public void setScrollContainer(boolean isScrollContainer) {
7111        if (isScrollContainer) {
7112            if (mAttachInfo != null && (mPrivateFlags&PFLAG_SCROLL_CONTAINER_ADDED) == 0) {
7113                mAttachInfo.mScrollContainers.add(this);
7114                mPrivateFlags |= PFLAG_SCROLL_CONTAINER_ADDED;
7115            }
7116            mPrivateFlags |= PFLAG_SCROLL_CONTAINER;
7117        } else {
7118            if ((mPrivateFlags&PFLAG_SCROLL_CONTAINER_ADDED) != 0) {
7119                mAttachInfo.mScrollContainers.remove(this);
7120            }
7121            mPrivateFlags &= ~(PFLAG_SCROLL_CONTAINER|PFLAG_SCROLL_CONTAINER_ADDED);
7122        }
7123    }
7124
7125    /**
7126     * Returns the quality of the drawing cache.
7127     *
7128     * @return One of {@link #DRAWING_CACHE_QUALITY_AUTO},
7129     *         {@link #DRAWING_CACHE_QUALITY_LOW}, or {@link #DRAWING_CACHE_QUALITY_HIGH}
7130     *
7131     * @see #setDrawingCacheQuality(int)
7132     * @see #setDrawingCacheEnabled(boolean)
7133     * @see #isDrawingCacheEnabled()
7134     *
7135     * @attr ref android.R.styleable#View_drawingCacheQuality
7136     */
7137    @DrawingCacheQuality
7138    public int getDrawingCacheQuality() {
7139        return mViewFlags & DRAWING_CACHE_QUALITY_MASK;
7140    }
7141
7142    /**
7143     * Set the drawing cache quality of this view. This value is used only when the
7144     * drawing cache is enabled
7145     *
7146     * @param quality One of {@link #DRAWING_CACHE_QUALITY_AUTO},
7147     *        {@link #DRAWING_CACHE_QUALITY_LOW}, or {@link #DRAWING_CACHE_QUALITY_HIGH}
7148     *
7149     * @see #getDrawingCacheQuality()
7150     * @see #setDrawingCacheEnabled(boolean)
7151     * @see #isDrawingCacheEnabled()
7152     *
7153     * @attr ref android.R.styleable#View_drawingCacheQuality
7154     */
7155    public void setDrawingCacheQuality(@DrawingCacheQuality int quality) {
7156        setFlags(quality, DRAWING_CACHE_QUALITY_MASK);
7157    }
7158
7159    /**
7160     * Returns whether the screen should remain on, corresponding to the current
7161     * value of {@link #KEEP_SCREEN_ON}.
7162     *
7163     * @return Returns true if {@link #KEEP_SCREEN_ON} is set.
7164     *
7165     * @see #setKeepScreenOn(boolean)
7166     *
7167     * @attr ref android.R.styleable#View_keepScreenOn
7168     */
7169    public boolean getKeepScreenOn() {
7170        return (mViewFlags & KEEP_SCREEN_ON) != 0;
7171    }
7172
7173    /**
7174     * Controls whether the screen should remain on, modifying the
7175     * value of {@link #KEEP_SCREEN_ON}.
7176     *
7177     * @param keepScreenOn Supply true to set {@link #KEEP_SCREEN_ON}.
7178     *
7179     * @see #getKeepScreenOn()
7180     *
7181     * @attr ref android.R.styleable#View_keepScreenOn
7182     */
7183    public void setKeepScreenOn(boolean keepScreenOn) {
7184        setFlags(keepScreenOn ? KEEP_SCREEN_ON : 0, KEEP_SCREEN_ON);
7185    }
7186
7187    /**
7188     * Gets the id of the view to use when the next focus is {@link #FOCUS_LEFT}.
7189     * @return The next focus ID, or {@link #NO_ID} if the framework should decide automatically.
7190     *
7191     * @attr ref android.R.styleable#View_nextFocusLeft
7192     */
7193    public int getNextFocusLeftId() {
7194        return mNextFocusLeftId;
7195    }
7196
7197    /**
7198     * Sets the id of the view to use when the next focus is {@link #FOCUS_LEFT}.
7199     * @param nextFocusLeftId The next focus ID, or {@link #NO_ID} if the framework should
7200     * decide automatically.
7201     *
7202     * @attr ref android.R.styleable#View_nextFocusLeft
7203     */
7204    public void setNextFocusLeftId(int nextFocusLeftId) {
7205        mNextFocusLeftId = nextFocusLeftId;
7206    }
7207
7208    /**
7209     * Gets the id of the view to use when the next focus is {@link #FOCUS_RIGHT}.
7210     * @return The next focus ID, or {@link #NO_ID} if the framework should decide automatically.
7211     *
7212     * @attr ref android.R.styleable#View_nextFocusRight
7213     */
7214    public int getNextFocusRightId() {
7215        return mNextFocusRightId;
7216    }
7217
7218    /**
7219     * Sets the id of the view to use when the next focus is {@link #FOCUS_RIGHT}.
7220     * @param nextFocusRightId The next focus ID, or {@link #NO_ID} if the framework should
7221     * decide automatically.
7222     *
7223     * @attr ref android.R.styleable#View_nextFocusRight
7224     */
7225    public void setNextFocusRightId(int nextFocusRightId) {
7226        mNextFocusRightId = nextFocusRightId;
7227    }
7228
7229    /**
7230     * Gets the id of the view to use when the next focus is {@link #FOCUS_UP}.
7231     * @return The next focus ID, or {@link #NO_ID} if the framework should decide automatically.
7232     *
7233     * @attr ref android.R.styleable#View_nextFocusUp
7234     */
7235    public int getNextFocusUpId() {
7236        return mNextFocusUpId;
7237    }
7238
7239    /**
7240     * Sets the id of the view to use when the next focus is {@link #FOCUS_UP}.
7241     * @param nextFocusUpId The next focus ID, or {@link #NO_ID} if the framework should
7242     * decide automatically.
7243     *
7244     * @attr ref android.R.styleable#View_nextFocusUp
7245     */
7246    public void setNextFocusUpId(int nextFocusUpId) {
7247        mNextFocusUpId = nextFocusUpId;
7248    }
7249
7250    /**
7251     * Gets the id of the view to use when the next focus is {@link #FOCUS_DOWN}.
7252     * @return The next focus ID, or {@link #NO_ID} if the framework should decide automatically.
7253     *
7254     * @attr ref android.R.styleable#View_nextFocusDown
7255     */
7256    public int getNextFocusDownId() {
7257        return mNextFocusDownId;
7258    }
7259
7260    /**
7261     * Sets the id of the view to use when the next focus is {@link #FOCUS_DOWN}.
7262     * @param nextFocusDownId The next focus ID, or {@link #NO_ID} if the framework should
7263     * decide automatically.
7264     *
7265     * @attr ref android.R.styleable#View_nextFocusDown
7266     */
7267    public void setNextFocusDownId(int nextFocusDownId) {
7268        mNextFocusDownId = nextFocusDownId;
7269    }
7270
7271    /**
7272     * Gets the id of the view to use when the next focus is {@link #FOCUS_FORWARD}.
7273     * @return The next focus ID, or {@link #NO_ID} if the framework should decide automatically.
7274     *
7275     * @attr ref android.R.styleable#View_nextFocusForward
7276     */
7277    public int getNextFocusForwardId() {
7278        return mNextFocusForwardId;
7279    }
7280
7281    /**
7282     * Sets the id of the view to use when the next focus is {@link #FOCUS_FORWARD}.
7283     * @param nextFocusForwardId The next focus ID, or {@link #NO_ID} if the framework should
7284     * decide automatically.
7285     *
7286     * @attr ref android.R.styleable#View_nextFocusForward
7287     */
7288    public void setNextFocusForwardId(int nextFocusForwardId) {
7289        mNextFocusForwardId = nextFocusForwardId;
7290    }
7291
7292    /**
7293     * Returns the visibility of this view and all of its ancestors
7294     *
7295     * @return True if this view and all of its ancestors are {@link #VISIBLE}
7296     */
7297    public boolean isShown() {
7298        View current = this;
7299        //noinspection ConstantConditions
7300        do {
7301            if ((current.mViewFlags & VISIBILITY_MASK) != VISIBLE) {
7302                return false;
7303            }
7304            ViewParent parent = current.mParent;
7305            if (parent == null) {
7306                return false; // We are not attached to the view root
7307            }
7308            if (!(parent instanceof View)) {
7309                return true;
7310            }
7311            current = (View) parent;
7312        } while (current != null);
7313
7314        return false;
7315    }
7316
7317    /**
7318     * Called by the view hierarchy when the content insets for a window have
7319     * changed, to allow it to adjust its content to fit within those windows.
7320     * The content insets tell you the space that the status bar, input method,
7321     * and other system windows infringe on the application's window.
7322     *
7323     * <p>You do not normally need to deal with this function, since the default
7324     * window decoration given to applications takes care of applying it to the
7325     * content of the window.  If you use {@link #SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN}
7326     * or {@link #SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION} this will not be the case,
7327     * and your content can be placed under those system elements.  You can then
7328     * use this method within your view hierarchy if you have parts of your UI
7329     * which you would like to ensure are not being covered.
7330     *
7331     * <p>The default implementation of this method simply applies the content
7332     * insets to the view's padding, consuming that content (modifying the
7333     * insets to be 0), and returning true.  This behavior is off by default, but can
7334     * be enabled through {@link #setFitsSystemWindows(boolean)}.
7335     *
7336     * <p>This function's traversal down the hierarchy is depth-first.  The same content
7337     * insets object is propagated down the hierarchy, so any changes made to it will
7338     * be seen by all following views (including potentially ones above in
7339     * the hierarchy since this is a depth-first traversal).  The first view
7340     * that returns true will abort the entire traversal.
7341     *
7342     * <p>The default implementation works well for a situation where it is
7343     * used with a container that covers the entire window, allowing it to
7344     * apply the appropriate insets to its content on all edges.  If you need
7345     * a more complicated layout (such as two different views fitting system
7346     * windows, one on the top of the window, and one on the bottom),
7347     * you can override the method and handle the insets however you would like.
7348     * Note that the insets provided by the framework are always relative to the
7349     * far edges of the window, not accounting for the location of the called view
7350     * within that window.  (In fact when this method is called you do not yet know
7351     * where the layout will place the view, as it is done before layout happens.)
7352     *
7353     * <p>Note: unlike many View methods, there is no dispatch phase to this
7354     * call.  If you are overriding it in a ViewGroup and want to allow the
7355     * call to continue to your children, you must be sure to call the super
7356     * implementation.
7357     *
7358     * <p>Here is a sample layout that makes use of fitting system windows
7359     * to have controls for a video view placed inside of the window decorations
7360     * that it hides and shows.  This can be used with code like the second
7361     * sample (video player) shown in {@link #setSystemUiVisibility(int)}.
7362     *
7363     * {@sample development/samples/ApiDemos/res/layout/video_player.xml complete}
7364     *
7365     * @param insets Current content insets of the window.  Prior to
7366     * {@link android.os.Build.VERSION_CODES#JELLY_BEAN} you must not modify
7367     * the insets or else you and Android will be unhappy.
7368     *
7369     * @return {@code true} if this view applied the insets and it should not
7370     * continue propagating further down the hierarchy, {@code false} otherwise.
7371     * @see #getFitsSystemWindows()
7372     * @see #setFitsSystemWindows(boolean)
7373     * @see #setSystemUiVisibility(int)
7374     *
7375     * @deprecated As of API 20 use {@link #dispatchApplyWindowInsets(WindowInsets)} to apply
7376     * insets to views. Views should override {@link #onApplyWindowInsets(WindowInsets)} or use
7377     * {@link #setOnApplyWindowInsetsListener(android.view.View.OnApplyWindowInsetsListener)}
7378     * to implement handling their own insets.
7379     */
7380    protected boolean fitSystemWindows(Rect insets) {
7381        if ((mPrivateFlags3 & PFLAG3_APPLYING_INSETS) == 0) {
7382            if (insets == null) {
7383                // Null insets by definition have already been consumed.
7384                // This call cannot apply insets since there are none to apply,
7385                // so return false.
7386                return false;
7387            }
7388            // If we're not in the process of dispatching the newer apply insets call,
7389            // that means we're not in the compatibility path. Dispatch into the newer
7390            // apply insets path and take things from there.
7391            try {
7392                mPrivateFlags3 |= PFLAG3_FITTING_SYSTEM_WINDOWS;
7393                return dispatchApplyWindowInsets(new WindowInsets(insets)).isConsumed();
7394            } finally {
7395                mPrivateFlags3 &= ~PFLAG3_FITTING_SYSTEM_WINDOWS;
7396            }
7397        } else {
7398            // We're being called from the newer apply insets path.
7399            // Perform the standard fallback behavior.
7400            return fitSystemWindowsInt(insets);
7401        }
7402    }
7403
7404    private boolean fitSystemWindowsInt(Rect insets) {
7405        if ((mViewFlags & FITS_SYSTEM_WINDOWS) == FITS_SYSTEM_WINDOWS) {
7406            mUserPaddingStart = UNDEFINED_PADDING;
7407            mUserPaddingEnd = UNDEFINED_PADDING;
7408            Rect localInsets = sThreadLocal.get();
7409            if (localInsets == null) {
7410                localInsets = new Rect();
7411                sThreadLocal.set(localInsets);
7412            }
7413            boolean res = computeFitSystemWindows(insets, localInsets);
7414            mUserPaddingLeftInitial = localInsets.left;
7415            mUserPaddingRightInitial = localInsets.right;
7416            internalSetPadding(localInsets.left, localInsets.top,
7417                    localInsets.right, localInsets.bottom);
7418            return res;
7419        }
7420        return false;
7421    }
7422
7423    /**
7424     * Called when the view should apply {@link WindowInsets} according to its internal policy.
7425     *
7426     * <p>This method should be overridden by views that wish to apply a policy different from or
7427     * in addition to the default behavior. Clients that wish to force a view subtree
7428     * to apply insets should call {@link #dispatchApplyWindowInsets(WindowInsets)}.</p>
7429     *
7430     * <p>Clients may supply an {@link OnApplyWindowInsetsListener} to a view. If one is set
7431     * it will be called during dispatch instead of this method. The listener may optionally
7432     * call this method from its own implementation if it wishes to apply the view's default
7433     * insets policy in addition to its own.</p>
7434     *
7435     * <p>Implementations of this method should either return the insets parameter unchanged
7436     * or a new {@link WindowInsets} cloned from the supplied insets with any insets consumed
7437     * that this view applied itself. This allows new inset types added in future platform
7438     * versions to pass through existing implementations unchanged without being erroneously
7439     * consumed.</p>
7440     *
7441     * <p>By default if a view's {@link #setFitsSystemWindows(boolean) fitsSystemWindows}
7442     * property is set then the view will consume the system window insets and apply them
7443     * as padding for the view.</p>
7444     *
7445     * @param insets Insets to apply
7446     * @return The supplied insets with any applied insets consumed
7447     */
7448    public WindowInsets onApplyWindowInsets(WindowInsets insets) {
7449        if ((mPrivateFlags3 & PFLAG3_FITTING_SYSTEM_WINDOWS) == 0) {
7450            // We weren't called from within a direct call to fitSystemWindows,
7451            // call into it as a fallback in case we're in a class that overrides it
7452            // and has logic to perform.
7453            if (fitSystemWindows(insets.getSystemWindowInsets())) {
7454                return insets.consumeSystemWindowInsets();
7455            }
7456        } else {
7457            // We were called from within a direct call to fitSystemWindows.
7458            if (fitSystemWindowsInt(insets.getSystemWindowInsets())) {
7459                return insets.consumeSystemWindowInsets();
7460            }
7461        }
7462        return insets;
7463    }
7464
7465    /**
7466     * Set an {@link OnApplyWindowInsetsListener} to take over the policy for applying
7467     * window insets to this view. The listener's
7468     * {@link OnApplyWindowInsetsListener#onApplyWindowInsets(View, WindowInsets) onApplyWindowInsets}
7469     * method will be called instead of the view's
7470     * {@link #onApplyWindowInsets(WindowInsets) onApplyWindowInsets} method.
7471     *
7472     * @param listener Listener to set
7473     *
7474     * @see #onApplyWindowInsets(WindowInsets)
7475     */
7476    public void setOnApplyWindowInsetsListener(OnApplyWindowInsetsListener listener) {
7477        getListenerInfo().mOnApplyWindowInsetsListener = listener;
7478    }
7479
7480    /**
7481     * Request to apply the given window insets to this view or another view in its subtree.
7482     *
7483     * <p>This method should be called by clients wishing to apply insets corresponding to areas
7484     * obscured by window decorations or overlays. This can include the status and navigation bars,
7485     * action bars, input methods and more. New inset categories may be added in the future.
7486     * The method returns the insets provided minus any that were applied by this view or its
7487     * children.</p>
7488     *
7489     * <p>Clients wishing to provide custom behavior should override the
7490     * {@link #onApplyWindowInsets(WindowInsets)} method or alternatively provide a
7491     * {@link OnApplyWindowInsetsListener} via the
7492     * {@link #setOnApplyWindowInsetsListener(View.OnApplyWindowInsetsListener) setOnApplyWindowInsetsListener}
7493     * method.</p>
7494     *
7495     * <p>This method replaces the older {@link #fitSystemWindows(Rect) fitSystemWindows} method.
7496     * </p>
7497     *
7498     * @param insets Insets to apply
7499     * @return The provided insets minus the insets that were consumed
7500     */
7501    public WindowInsets dispatchApplyWindowInsets(WindowInsets insets) {
7502        try {
7503            mPrivateFlags3 |= PFLAG3_APPLYING_INSETS;
7504            if (mListenerInfo != null && mListenerInfo.mOnApplyWindowInsetsListener != null) {
7505                return mListenerInfo.mOnApplyWindowInsetsListener.onApplyWindowInsets(this, insets);
7506            } else {
7507                return onApplyWindowInsets(insets);
7508            }
7509        } finally {
7510            mPrivateFlags3 &= ~PFLAG3_APPLYING_INSETS;
7511        }
7512    }
7513
7514    /**
7515     * Compute the view's coordinate within the surface.
7516     *
7517     * <p>Computes the coordinates of this view in its surface. The argument
7518     * must be an array of two integers. After the method returns, the array
7519     * contains the x and y location in that order.</p>
7520     * @hide
7521     * @param location an array of two integers in which to hold the coordinates
7522     */
7523    public void getLocationInSurface(@Size(2) int[] location) {
7524        getLocationInWindow(location);
7525        if (mAttachInfo != null && mAttachInfo.mViewRootImpl != null) {
7526            location[0] += mAttachInfo.mViewRootImpl.mWindowAttributes.surfaceInsets.left;
7527            location[1] += mAttachInfo.mViewRootImpl.mWindowAttributes.surfaceInsets.top;
7528        }
7529    }
7530
7531    /**
7532     * Provide original WindowInsets that are dispatched to the view hierarchy. The insets are
7533     * only available if the view is attached.
7534     *
7535     * @return WindowInsets from the top of the view hierarchy or null if View is detached
7536     */
7537    public WindowInsets getRootWindowInsets() {
7538        if (mAttachInfo != null) {
7539            return mAttachInfo.mViewRootImpl.getWindowInsets(false /* forceConstruct */);
7540        }
7541        return null;
7542    }
7543
7544    /**
7545     * @hide Compute the insets that should be consumed by this view and the ones
7546     * that should propagate to those under it.
7547     */
7548    protected boolean computeFitSystemWindows(Rect inoutInsets, Rect outLocalInsets) {
7549        if ((mViewFlags & OPTIONAL_FITS_SYSTEM_WINDOWS) == 0
7550                || mAttachInfo == null
7551                || ((mAttachInfo.mSystemUiVisibility & SYSTEM_UI_LAYOUT_FLAGS) == 0
7552                        && !mAttachInfo.mOverscanRequested)) {
7553            outLocalInsets.set(inoutInsets);
7554            inoutInsets.set(0, 0, 0, 0);
7555            return true;
7556        } else {
7557            // The application wants to take care of fitting system window for
7558            // the content...  however we still need to take care of any overscan here.
7559            final Rect overscan = mAttachInfo.mOverscanInsets;
7560            outLocalInsets.set(overscan);
7561            inoutInsets.left -= overscan.left;
7562            inoutInsets.top -= overscan.top;
7563            inoutInsets.right -= overscan.right;
7564            inoutInsets.bottom -= overscan.bottom;
7565            return false;
7566        }
7567    }
7568
7569    /**
7570     * Compute insets that should be consumed by this view and the ones that should propagate
7571     * to those under it.
7572     *
7573     * @param in Insets currently being processed by this View, likely received as a parameter
7574     *           to {@link #onApplyWindowInsets(WindowInsets)}.
7575     * @param outLocalInsets A Rect that will receive the insets that should be consumed
7576     *                       by this view
7577     * @return Insets that should be passed along to views under this one
7578     */
7579    public WindowInsets computeSystemWindowInsets(WindowInsets in, Rect outLocalInsets) {
7580        if ((mViewFlags & OPTIONAL_FITS_SYSTEM_WINDOWS) == 0
7581                || mAttachInfo == null
7582                || (mAttachInfo.mSystemUiVisibility & SYSTEM_UI_LAYOUT_FLAGS) == 0) {
7583            outLocalInsets.set(in.getSystemWindowInsets());
7584            return in.consumeSystemWindowInsets();
7585        } else {
7586            outLocalInsets.set(0, 0, 0, 0);
7587            return in;
7588        }
7589    }
7590
7591    /**
7592     * Sets whether or not this view should account for system screen decorations
7593     * such as the status bar and inset its content; that is, controlling whether
7594     * the default implementation of {@link #fitSystemWindows(Rect)} will be
7595     * executed.  See that method for more details.
7596     *
7597     * <p>Note that if you are providing your own implementation of
7598     * {@link #fitSystemWindows(Rect)}, then there is no need to set this
7599     * flag to true -- your implementation will be overriding the default
7600     * implementation that checks this flag.
7601     *
7602     * @param fitSystemWindows If true, then the default implementation of
7603     * {@link #fitSystemWindows(Rect)} will be executed.
7604     *
7605     * @attr ref android.R.styleable#View_fitsSystemWindows
7606     * @see #getFitsSystemWindows()
7607     * @see #fitSystemWindows(Rect)
7608     * @see #setSystemUiVisibility(int)
7609     */
7610    public void setFitsSystemWindows(boolean fitSystemWindows) {
7611        setFlags(fitSystemWindows ? FITS_SYSTEM_WINDOWS : 0, FITS_SYSTEM_WINDOWS);
7612    }
7613
7614    /**
7615     * Check for state of {@link #setFitsSystemWindows(boolean)}. If this method
7616     * returns {@code true}, the default implementation of {@link #fitSystemWindows(Rect)}
7617     * will be executed.
7618     *
7619     * @return {@code true} if the default implementation of
7620     * {@link #fitSystemWindows(Rect)} will be executed.
7621     *
7622     * @attr ref android.R.styleable#View_fitsSystemWindows
7623     * @see #setFitsSystemWindows(boolean)
7624     * @see #fitSystemWindows(Rect)
7625     * @see #setSystemUiVisibility(int)
7626     */
7627    @ViewDebug.ExportedProperty
7628    public boolean getFitsSystemWindows() {
7629        return (mViewFlags & FITS_SYSTEM_WINDOWS) == FITS_SYSTEM_WINDOWS;
7630    }
7631
7632    /** @hide */
7633    public boolean fitsSystemWindows() {
7634        return getFitsSystemWindows();
7635    }
7636
7637    /**
7638     * Ask that a new dispatch of {@link #fitSystemWindows(Rect)} be performed.
7639     * @deprecated Use {@link #requestApplyInsets()} for newer platform versions.
7640     */
7641    public void requestFitSystemWindows() {
7642        if (mParent != null) {
7643            mParent.requestFitSystemWindows();
7644        }
7645    }
7646
7647    /**
7648     * Ask that a new dispatch of {@link #onApplyWindowInsets(WindowInsets)} be performed.
7649     */
7650    public void requestApplyInsets() {
7651        requestFitSystemWindows();
7652    }
7653
7654    /**
7655     * For use by PhoneWindow to make its own system window fitting optional.
7656     * @hide
7657     */
7658    public void makeOptionalFitsSystemWindows() {
7659        setFlags(OPTIONAL_FITS_SYSTEM_WINDOWS, OPTIONAL_FITS_SYSTEM_WINDOWS);
7660    }
7661
7662    /**
7663     * Returns the outsets, which areas of the device that aren't a surface, but we would like to
7664     * treat them as such.
7665     * @hide
7666     */
7667    public void getOutsets(Rect outOutsetRect) {
7668        if (mAttachInfo != null) {
7669            outOutsetRect.set(mAttachInfo.mOutsets);
7670        } else {
7671            outOutsetRect.setEmpty();
7672        }
7673    }
7674
7675    /**
7676     * Returns the visibility status for this view.
7677     *
7678     * @return One of {@link #VISIBLE}, {@link #INVISIBLE}, or {@link #GONE}.
7679     * @attr ref android.R.styleable#View_visibility
7680     */
7681    @ViewDebug.ExportedProperty(mapping = {
7682        @ViewDebug.IntToString(from = VISIBLE,   to = "VISIBLE"),
7683        @ViewDebug.IntToString(from = INVISIBLE, to = "INVISIBLE"),
7684        @ViewDebug.IntToString(from = GONE,      to = "GONE")
7685    })
7686    @Visibility
7687    public int getVisibility() {
7688        return mViewFlags & VISIBILITY_MASK;
7689    }
7690
7691    /**
7692     * Set the enabled state of this view.
7693     *
7694     * @param visibility One of {@link #VISIBLE}, {@link #INVISIBLE}, or {@link #GONE}.
7695     * @attr ref android.R.styleable#View_visibility
7696     */
7697    @RemotableViewMethod
7698    public void setVisibility(@Visibility int visibility) {
7699        setFlags(visibility, VISIBILITY_MASK);
7700    }
7701
7702    /**
7703     * Returns the enabled status for this view. The interpretation of the
7704     * enabled state varies by subclass.
7705     *
7706     * @return True if this view is enabled, false otherwise.
7707     */
7708    @ViewDebug.ExportedProperty
7709    public boolean isEnabled() {
7710        return (mViewFlags & ENABLED_MASK) == ENABLED;
7711    }
7712
7713    /**
7714     * Set the enabled state of this view. The interpretation of the enabled
7715     * state varies by subclass.
7716     *
7717     * @param enabled True if this view is enabled, false otherwise.
7718     */
7719    @RemotableViewMethod
7720    public void setEnabled(boolean enabled) {
7721        if (enabled == isEnabled()) return;
7722
7723        setFlags(enabled ? ENABLED : DISABLED, ENABLED_MASK);
7724
7725        /*
7726         * The View most likely has to change its appearance, so refresh
7727         * the drawable state.
7728         */
7729        refreshDrawableState();
7730
7731        // Invalidate too, since the default behavior for views is to be
7732        // be drawn at 50% alpha rather than to change the drawable.
7733        invalidate(true);
7734
7735        if (!enabled) {
7736            cancelPendingInputEvents();
7737        }
7738    }
7739
7740    /**
7741     * Set whether this view can receive the focus.
7742     *
7743     * Setting this to false will also ensure that this view is not focusable
7744     * in touch mode.
7745     *
7746     * @param focusable If true, this view can receive the focus.
7747     *
7748     * @see #setFocusableInTouchMode(boolean)
7749     * @attr ref android.R.styleable#View_focusable
7750     */
7751    public void setFocusable(boolean focusable) {
7752        if (!focusable) {
7753            setFlags(0, FOCUSABLE_IN_TOUCH_MODE);
7754        }
7755        setFlags(focusable ? FOCUSABLE : NOT_FOCUSABLE, FOCUSABLE_MASK);
7756    }
7757
7758    /**
7759     * Set whether this view can receive focus while in touch mode.
7760     *
7761     * Setting this to true will also ensure that this view is focusable.
7762     *
7763     * @param focusableInTouchMode If true, this view can receive the focus while
7764     *   in touch mode.
7765     *
7766     * @see #setFocusable(boolean)
7767     * @attr ref android.R.styleable#View_focusableInTouchMode
7768     */
7769    public void setFocusableInTouchMode(boolean focusableInTouchMode) {
7770        // Focusable in touch mode should always be set before the focusable flag
7771        // otherwise, setting the focusable flag will trigger a focusableViewAvailable()
7772        // which, in touch mode, will not successfully request focus on this view
7773        // because the focusable in touch mode flag is not set
7774        setFlags(focusableInTouchMode ? FOCUSABLE_IN_TOUCH_MODE : 0, FOCUSABLE_IN_TOUCH_MODE);
7775        if (focusableInTouchMode) {
7776            setFlags(FOCUSABLE, FOCUSABLE_MASK);
7777        }
7778    }
7779
7780    /**
7781     * Set whether this view should have sound effects enabled for events such as
7782     * clicking and touching.
7783     *
7784     * <p>You may wish to disable sound effects for a view if you already play sounds,
7785     * for instance, a dial key that plays dtmf tones.
7786     *
7787     * @param soundEffectsEnabled whether sound effects are enabled for this view.
7788     * @see #isSoundEffectsEnabled()
7789     * @see #playSoundEffect(int)
7790     * @attr ref android.R.styleable#View_soundEffectsEnabled
7791     */
7792    public void setSoundEffectsEnabled(boolean soundEffectsEnabled) {
7793        setFlags(soundEffectsEnabled ? SOUND_EFFECTS_ENABLED: 0, SOUND_EFFECTS_ENABLED);
7794    }
7795
7796    /**
7797     * @return whether this view should have sound effects enabled for events such as
7798     *     clicking and touching.
7799     *
7800     * @see #setSoundEffectsEnabled(boolean)
7801     * @see #playSoundEffect(int)
7802     * @attr ref android.R.styleable#View_soundEffectsEnabled
7803     */
7804    @ViewDebug.ExportedProperty
7805    public boolean isSoundEffectsEnabled() {
7806        return SOUND_EFFECTS_ENABLED == (mViewFlags & SOUND_EFFECTS_ENABLED);
7807    }
7808
7809    /**
7810     * Set whether this view should have haptic feedback for events such as
7811     * long presses.
7812     *
7813     * <p>You may wish to disable haptic feedback if your view already controls
7814     * its own haptic feedback.
7815     *
7816     * @param hapticFeedbackEnabled whether haptic feedback enabled for this view.
7817     * @see #isHapticFeedbackEnabled()
7818     * @see #performHapticFeedback(int)
7819     * @attr ref android.R.styleable#View_hapticFeedbackEnabled
7820     */
7821    public void setHapticFeedbackEnabled(boolean hapticFeedbackEnabled) {
7822        setFlags(hapticFeedbackEnabled ? HAPTIC_FEEDBACK_ENABLED: 0, HAPTIC_FEEDBACK_ENABLED);
7823    }
7824
7825    /**
7826     * @return whether this view should have haptic feedback enabled for events
7827     * long presses.
7828     *
7829     * @see #setHapticFeedbackEnabled(boolean)
7830     * @see #performHapticFeedback(int)
7831     * @attr ref android.R.styleable#View_hapticFeedbackEnabled
7832     */
7833    @ViewDebug.ExportedProperty
7834    public boolean isHapticFeedbackEnabled() {
7835        return HAPTIC_FEEDBACK_ENABLED == (mViewFlags & HAPTIC_FEEDBACK_ENABLED);
7836    }
7837
7838    /**
7839     * Returns the layout direction for this view.
7840     *
7841     * @return One of {@link #LAYOUT_DIRECTION_LTR},
7842     *   {@link #LAYOUT_DIRECTION_RTL},
7843     *   {@link #LAYOUT_DIRECTION_INHERIT} or
7844     *   {@link #LAYOUT_DIRECTION_LOCALE}.
7845     *
7846     * @attr ref android.R.styleable#View_layoutDirection
7847     *
7848     * @hide
7849     */
7850    @ViewDebug.ExportedProperty(category = "layout", mapping = {
7851        @ViewDebug.IntToString(from = LAYOUT_DIRECTION_LTR,     to = "LTR"),
7852        @ViewDebug.IntToString(from = LAYOUT_DIRECTION_RTL,     to = "RTL"),
7853        @ViewDebug.IntToString(from = LAYOUT_DIRECTION_INHERIT, to = "INHERIT"),
7854        @ViewDebug.IntToString(from = LAYOUT_DIRECTION_LOCALE,  to = "LOCALE")
7855    })
7856    @LayoutDir
7857    public int getRawLayoutDirection() {
7858        return (mPrivateFlags2 & PFLAG2_LAYOUT_DIRECTION_MASK) >> PFLAG2_LAYOUT_DIRECTION_MASK_SHIFT;
7859    }
7860
7861    /**
7862     * Set the layout direction for this view. This will propagate a reset of layout direction
7863     * resolution to the view's children and resolve layout direction for this view.
7864     *
7865     * @param layoutDirection the layout direction to set. Should be one of:
7866     *
7867     * {@link #LAYOUT_DIRECTION_LTR},
7868     * {@link #LAYOUT_DIRECTION_RTL},
7869     * {@link #LAYOUT_DIRECTION_INHERIT},
7870     * {@link #LAYOUT_DIRECTION_LOCALE}.
7871     *
7872     * Resolution will be done if the value is set to LAYOUT_DIRECTION_INHERIT. The resolution
7873     * proceeds up the parent chain of the view to get the value. If there is no parent, then it
7874     * will return the default {@link #LAYOUT_DIRECTION_LTR}.
7875     *
7876     * @attr ref android.R.styleable#View_layoutDirection
7877     */
7878    @RemotableViewMethod
7879    public void setLayoutDirection(@LayoutDir int layoutDirection) {
7880        if (getRawLayoutDirection() != layoutDirection) {
7881            // Reset the current layout direction and the resolved one
7882            mPrivateFlags2 &= ~PFLAG2_LAYOUT_DIRECTION_MASK;
7883            resetRtlProperties();
7884            // Set the new layout direction (filtered)
7885            mPrivateFlags2 |=
7886                    ((layoutDirection << PFLAG2_LAYOUT_DIRECTION_MASK_SHIFT) & PFLAG2_LAYOUT_DIRECTION_MASK);
7887            // We need to resolve all RTL properties as they all depend on layout direction
7888            resolveRtlPropertiesIfNeeded();
7889            requestLayout();
7890            invalidate(true);
7891        }
7892    }
7893
7894    /**
7895     * Returns the resolved layout direction for this view.
7896     *
7897     * @return {@link #LAYOUT_DIRECTION_RTL} if the layout direction is RTL or returns
7898     * {@link #LAYOUT_DIRECTION_LTR} if the layout direction is not RTL.
7899     *
7900     * For compatibility, this will return {@link #LAYOUT_DIRECTION_LTR} if API version
7901     * is lower than {@link android.os.Build.VERSION_CODES#JELLY_BEAN_MR1}.
7902     *
7903     * @attr ref android.R.styleable#View_layoutDirection
7904     */
7905    @ViewDebug.ExportedProperty(category = "layout", mapping = {
7906        @ViewDebug.IntToString(from = LAYOUT_DIRECTION_LTR, to = "RESOLVED_DIRECTION_LTR"),
7907        @ViewDebug.IntToString(from = LAYOUT_DIRECTION_RTL, to = "RESOLVED_DIRECTION_RTL")
7908    })
7909    @ResolvedLayoutDir
7910    public int getLayoutDirection() {
7911        final int targetSdkVersion = getContext().getApplicationInfo().targetSdkVersion;
7912        if (targetSdkVersion < JELLY_BEAN_MR1) {
7913            mPrivateFlags2 |= PFLAG2_LAYOUT_DIRECTION_RESOLVED;
7914            return LAYOUT_DIRECTION_RESOLVED_DEFAULT;
7915        }
7916        return ((mPrivateFlags2 & PFLAG2_LAYOUT_DIRECTION_RESOLVED_RTL) ==
7917                PFLAG2_LAYOUT_DIRECTION_RESOLVED_RTL) ? LAYOUT_DIRECTION_RTL : LAYOUT_DIRECTION_LTR;
7918    }
7919
7920    /**
7921     * Indicates whether or not this view's layout is right-to-left. This is resolved from
7922     * layout attribute and/or the inherited value from the parent
7923     *
7924     * @return true if the layout is right-to-left.
7925     *
7926     * @hide
7927     */
7928    @ViewDebug.ExportedProperty(category = "layout")
7929    public boolean isLayoutRtl() {
7930        return (getLayoutDirection() == LAYOUT_DIRECTION_RTL);
7931    }
7932
7933    /**
7934     * Indicates whether the view is currently tracking transient state that the
7935     * app should not need to concern itself with saving and restoring, but that
7936     * the framework should take special note to preserve when possible.
7937     *
7938     * <p>A view with transient state cannot be trivially rebound from an external
7939     * data source, such as an adapter binding item views in a list. This may be
7940     * because the view is performing an animation, tracking user selection
7941     * of content, or similar.</p>
7942     *
7943     * @return true if the view has transient state
7944     */
7945    @ViewDebug.ExportedProperty(category = "layout")
7946    public boolean hasTransientState() {
7947        return (mPrivateFlags2 & PFLAG2_HAS_TRANSIENT_STATE) == PFLAG2_HAS_TRANSIENT_STATE;
7948    }
7949
7950    /**
7951     * Set whether this view is currently tracking transient state that the
7952     * framework should attempt to preserve when possible. This flag is reference counted,
7953     * so every call to setHasTransientState(true) should be paired with a later call
7954     * to setHasTransientState(false).
7955     *
7956     * <p>A view with transient state cannot be trivially rebound from an external
7957     * data source, such as an adapter binding item views in a list. This may be
7958     * because the view is performing an animation, tracking user selection
7959     * of content, or similar.</p>
7960     *
7961     * @param hasTransientState true if this view has transient state
7962     */
7963    public void setHasTransientState(boolean hasTransientState) {
7964        mTransientStateCount = hasTransientState ? mTransientStateCount + 1 :
7965                mTransientStateCount - 1;
7966        if (mTransientStateCount < 0) {
7967            mTransientStateCount = 0;
7968            Log.e(VIEW_LOG_TAG, "hasTransientState decremented below 0: " +
7969                    "unmatched pair of setHasTransientState calls");
7970        } else if ((hasTransientState && mTransientStateCount == 1) ||
7971                (!hasTransientState && mTransientStateCount == 0)) {
7972            // update flag if we've just incremented up from 0 or decremented down to 0
7973            mPrivateFlags2 = (mPrivateFlags2 & ~PFLAG2_HAS_TRANSIENT_STATE) |
7974                    (hasTransientState ? PFLAG2_HAS_TRANSIENT_STATE : 0);
7975            if (mParent != null) {
7976                try {
7977                    mParent.childHasTransientStateChanged(this, hasTransientState);
7978                } catch (AbstractMethodError e) {
7979                    Log.e(VIEW_LOG_TAG, mParent.getClass().getSimpleName() +
7980                            " does not fully implement ViewParent", e);
7981                }
7982            }
7983        }
7984    }
7985
7986    /**
7987     * Returns true if this view is currently attached to a window.
7988     */
7989    public boolean isAttachedToWindow() {
7990        return mAttachInfo != null;
7991    }
7992
7993    /**
7994     * Returns true if this view has been through at least one layout since it
7995     * was last attached to or detached from a window.
7996     */
7997    public boolean isLaidOut() {
7998        return (mPrivateFlags3 & PFLAG3_IS_LAID_OUT) == PFLAG3_IS_LAID_OUT;
7999    }
8000
8001    /**
8002     * If this view doesn't do any drawing on its own, set this flag to
8003     * allow further optimizations. By default, this flag is not set on
8004     * View, but could be set on some View subclasses such as ViewGroup.
8005     *
8006     * Typically, if you override {@link #onDraw(android.graphics.Canvas)}
8007     * you should clear this flag.
8008     *
8009     * @param willNotDraw whether or not this View draw on its own
8010     */
8011    public void setWillNotDraw(boolean willNotDraw) {
8012        setFlags(willNotDraw ? WILL_NOT_DRAW : 0, DRAW_MASK);
8013    }
8014
8015    /**
8016     * Returns whether or not this View draws on its own.
8017     *
8018     * @return true if this view has nothing to draw, false otherwise
8019     */
8020    @ViewDebug.ExportedProperty(category = "drawing")
8021    public boolean willNotDraw() {
8022        return (mViewFlags & DRAW_MASK) == WILL_NOT_DRAW;
8023    }
8024
8025    /**
8026     * When a View's drawing cache is enabled, drawing is redirected to an
8027     * offscreen bitmap. Some views, like an ImageView, must be able to
8028     * bypass this mechanism if they already draw a single bitmap, to avoid
8029     * unnecessary usage of the memory.
8030     *
8031     * @param willNotCacheDrawing true if this view does not cache its
8032     *        drawing, false otherwise
8033     */
8034    public void setWillNotCacheDrawing(boolean willNotCacheDrawing) {
8035        setFlags(willNotCacheDrawing ? WILL_NOT_CACHE_DRAWING : 0, WILL_NOT_CACHE_DRAWING);
8036    }
8037
8038    /**
8039     * Returns whether or not this View can cache its drawing or not.
8040     *
8041     * @return true if this view does not cache its drawing, false otherwise
8042     */
8043    @ViewDebug.ExportedProperty(category = "drawing")
8044    public boolean willNotCacheDrawing() {
8045        return (mViewFlags & WILL_NOT_CACHE_DRAWING) == WILL_NOT_CACHE_DRAWING;
8046    }
8047
8048    /**
8049     * Indicates whether this view reacts to click events or not.
8050     *
8051     * @return true if the view is clickable, false otherwise
8052     *
8053     * @see #setClickable(boolean)
8054     * @attr ref android.R.styleable#View_clickable
8055     */
8056    @ViewDebug.ExportedProperty
8057    public boolean isClickable() {
8058        return (mViewFlags & CLICKABLE) == CLICKABLE;
8059    }
8060
8061    /**
8062     * Enables or disables click events for this view. When a view
8063     * is clickable it will change its state to "pressed" on every click.
8064     * Subclasses should set the view clickable to visually react to
8065     * user's clicks.
8066     *
8067     * @param clickable true to make the view clickable, false otherwise
8068     *
8069     * @see #isClickable()
8070     * @attr ref android.R.styleable#View_clickable
8071     */
8072    public void setClickable(boolean clickable) {
8073        setFlags(clickable ? CLICKABLE : 0, CLICKABLE);
8074    }
8075
8076    /**
8077     * Indicates whether this view reacts to long click events or not.
8078     *
8079     * @return true if the view is long clickable, false otherwise
8080     *
8081     * @see #setLongClickable(boolean)
8082     * @attr ref android.R.styleable#View_longClickable
8083     */
8084    public boolean isLongClickable() {
8085        return (mViewFlags & LONG_CLICKABLE) == LONG_CLICKABLE;
8086    }
8087
8088    /**
8089     * Enables or disables long click events for this view. When a view is long
8090     * clickable it reacts to the user holding down the button for a longer
8091     * duration than a tap. This event can either launch the listener or a
8092     * context menu.
8093     *
8094     * @param longClickable true to make the view long clickable, false otherwise
8095     * @see #isLongClickable()
8096     * @attr ref android.R.styleable#View_longClickable
8097     */
8098    public void setLongClickable(boolean longClickable) {
8099        setFlags(longClickable ? LONG_CLICKABLE : 0, LONG_CLICKABLE);
8100    }
8101
8102    /**
8103     * Indicates whether this view reacts to context clicks or not.
8104     *
8105     * @return true if the view is context clickable, false otherwise
8106     * @see #setContextClickable(boolean)
8107     * @attr ref android.R.styleable#View_contextClickable
8108     */
8109    public boolean isContextClickable() {
8110        return (mViewFlags & CONTEXT_CLICKABLE) == CONTEXT_CLICKABLE;
8111    }
8112
8113    /**
8114     * Enables or disables context clicking for this view. This event can launch the listener.
8115     *
8116     * @param contextClickable true to make the view react to a context click, false otherwise
8117     * @see #isContextClickable()
8118     * @attr ref android.R.styleable#View_contextClickable
8119     */
8120    public void setContextClickable(boolean contextClickable) {
8121        setFlags(contextClickable ? CONTEXT_CLICKABLE : 0, CONTEXT_CLICKABLE);
8122    }
8123
8124    /**
8125     * Sets the pressed state for this view and provides a touch coordinate for
8126     * animation hinting.
8127     *
8128     * @param pressed Pass true to set the View's internal state to "pressed",
8129     *            or false to reverts the View's internal state from a
8130     *            previously set "pressed" state.
8131     * @param x The x coordinate of the touch that caused the press
8132     * @param y The y coordinate of the touch that caused the press
8133     */
8134    private void setPressed(boolean pressed, float x, float y) {
8135        if (pressed) {
8136            drawableHotspotChanged(x, y);
8137        }
8138
8139        setPressed(pressed);
8140    }
8141
8142    /**
8143     * Sets the pressed state for this view.
8144     *
8145     * @see #isClickable()
8146     * @see #setClickable(boolean)
8147     *
8148     * @param pressed Pass true to set the View's internal state to "pressed", or false to reverts
8149     *        the View's internal state from a previously set "pressed" state.
8150     */
8151    public void setPressed(boolean pressed) {
8152        final boolean needsRefresh = pressed != ((mPrivateFlags & PFLAG_PRESSED) == PFLAG_PRESSED);
8153
8154        if (pressed) {
8155            mPrivateFlags |= PFLAG_PRESSED;
8156        } else {
8157            mPrivateFlags &= ~PFLAG_PRESSED;
8158        }
8159
8160        if (needsRefresh) {
8161            refreshDrawableState();
8162        }
8163        dispatchSetPressed(pressed);
8164    }
8165
8166    /**
8167     * Dispatch setPressed to all of this View's children.
8168     *
8169     * @see #setPressed(boolean)
8170     *
8171     * @param pressed The new pressed state
8172     */
8173    protected void dispatchSetPressed(boolean pressed) {
8174    }
8175
8176    /**
8177     * Indicates whether the view is currently in pressed state. Unless
8178     * {@link #setPressed(boolean)} is explicitly called, only clickable views can enter
8179     * the pressed state.
8180     *
8181     * @see #setPressed(boolean)
8182     * @see #isClickable()
8183     * @see #setClickable(boolean)
8184     *
8185     * @return true if the view is currently pressed, false otherwise
8186     */
8187    @ViewDebug.ExportedProperty
8188    public boolean isPressed() {
8189        return (mPrivateFlags & PFLAG_PRESSED) == PFLAG_PRESSED;
8190    }
8191
8192    /**
8193     * @hide
8194     * Indicates whether this view will participate in data collection through
8195     * {@link ViewStructure}.  If true, it will not provide any data
8196     * for itself or its children.  If false, the normal data collection will be allowed.
8197     *
8198     * @return Returns false if assist data collection is not blocked, else true.
8199     *
8200     * @see #setAssistBlocked(boolean)
8201     * @attr ref android.R.styleable#View_assistBlocked
8202     */
8203    public boolean isAssistBlocked() {
8204        return (mPrivateFlags3 & PFLAG3_ASSIST_BLOCKED) != 0;
8205    }
8206
8207    /**
8208     * @hide
8209     * Controls whether assist data collection from this view and its children is enabled
8210     * (that is, whether {@link #onProvideStructure} and
8211     * {@link #onProvideVirtualStructure} will be called).  The default value is false,
8212     * allowing normal assist collection.  Setting this to false will disable assist collection.
8213     *
8214     * @param enabled Set to true to <em>disable</em> assist data collection, or false
8215     * (the default) to allow it.
8216     *
8217     * @see #isAssistBlocked()
8218     * @see #onProvideStructure
8219     * @see #onProvideVirtualStructure
8220     * @attr ref android.R.styleable#View_assistBlocked
8221     */
8222    public void setAssistBlocked(boolean enabled) {
8223        if (enabled) {
8224            mPrivateFlags3 |= PFLAG3_ASSIST_BLOCKED;
8225        } else {
8226            mPrivateFlags3 &= ~PFLAG3_ASSIST_BLOCKED;
8227        }
8228    }
8229
8230    /**
8231     * Indicates whether this view will save its state (that is,
8232     * whether its {@link #onSaveInstanceState} method will be called).
8233     *
8234     * @return Returns true if the view state saving is enabled, else false.
8235     *
8236     * @see #setSaveEnabled(boolean)
8237     * @attr ref android.R.styleable#View_saveEnabled
8238     */
8239    public boolean isSaveEnabled() {
8240        return (mViewFlags & SAVE_DISABLED_MASK) != SAVE_DISABLED;
8241    }
8242
8243    /**
8244     * Controls whether the saving of this view's state is
8245     * enabled (that is, whether its {@link #onSaveInstanceState} method
8246     * will be called).  Note that even if freezing is enabled, the
8247     * view still must have an id assigned to it (via {@link #setId(int)})
8248     * for its state to be saved.  This flag can only disable the
8249     * saving of this view; any child views may still have their state saved.
8250     *
8251     * @param enabled Set to false to <em>disable</em> state saving, or true
8252     * (the default) to allow it.
8253     *
8254     * @see #isSaveEnabled()
8255     * @see #setId(int)
8256     * @see #onSaveInstanceState()
8257     * @attr ref android.R.styleable#View_saveEnabled
8258     */
8259    public void setSaveEnabled(boolean enabled) {
8260        setFlags(enabled ? 0 : SAVE_DISABLED, SAVE_DISABLED_MASK);
8261    }
8262
8263    /**
8264     * Gets whether the framework should discard touches when the view's
8265     * window is obscured by another visible window.
8266     * Refer to the {@link View} security documentation for more details.
8267     *
8268     * @return True if touch filtering is enabled.
8269     *
8270     * @see #setFilterTouchesWhenObscured(boolean)
8271     * @attr ref android.R.styleable#View_filterTouchesWhenObscured
8272     */
8273    @ViewDebug.ExportedProperty
8274    public boolean getFilterTouchesWhenObscured() {
8275        return (mViewFlags & FILTER_TOUCHES_WHEN_OBSCURED) != 0;
8276    }
8277
8278    /**
8279     * Sets whether the framework should discard touches when the view's
8280     * window is obscured by another visible window.
8281     * Refer to the {@link View} security documentation for more details.
8282     *
8283     * @param enabled True if touch filtering should be enabled.
8284     *
8285     * @see #getFilterTouchesWhenObscured
8286     * @attr ref android.R.styleable#View_filterTouchesWhenObscured
8287     */
8288    public void setFilterTouchesWhenObscured(boolean enabled) {
8289        setFlags(enabled ? FILTER_TOUCHES_WHEN_OBSCURED : 0,
8290                FILTER_TOUCHES_WHEN_OBSCURED);
8291    }
8292
8293    /**
8294     * Indicates whether the entire hierarchy under this view will save its
8295     * state when a state saving traversal occurs from its parent.  The default
8296     * is true; if false, these views will not be saved unless
8297     * {@link #saveHierarchyState(SparseArray)} is called directly on this view.
8298     *
8299     * @return Returns true if the view state saving from parent is enabled, else false.
8300     *
8301     * @see #setSaveFromParentEnabled(boolean)
8302     */
8303    public boolean isSaveFromParentEnabled() {
8304        return (mViewFlags & PARENT_SAVE_DISABLED_MASK) != PARENT_SAVE_DISABLED;
8305    }
8306
8307    /**
8308     * Controls whether the entire hierarchy under this view will save its
8309     * state when a state saving traversal occurs from its parent.  The default
8310     * is true; if false, these views will not be saved unless
8311     * {@link #saveHierarchyState(SparseArray)} is called directly on this view.
8312     *
8313     * @param enabled Set to false to <em>disable</em> state saving, or true
8314     * (the default) to allow it.
8315     *
8316     * @see #isSaveFromParentEnabled()
8317     * @see #setId(int)
8318     * @see #onSaveInstanceState()
8319     */
8320    public void setSaveFromParentEnabled(boolean enabled) {
8321        setFlags(enabled ? 0 : PARENT_SAVE_DISABLED, PARENT_SAVE_DISABLED_MASK);
8322    }
8323
8324
8325    /**
8326     * Returns whether this View is able to take focus.
8327     *
8328     * @return True if this view can take focus, or false otherwise.
8329     * @attr ref android.R.styleable#View_focusable
8330     */
8331    @ViewDebug.ExportedProperty(category = "focus")
8332    public final boolean isFocusable() {
8333        return FOCUSABLE == (mViewFlags & FOCUSABLE_MASK);
8334    }
8335
8336    /**
8337     * When a view is focusable, it may not want to take focus when in touch mode.
8338     * For example, a button would like focus when the user is navigating via a D-pad
8339     * so that the user can click on it, but once the user starts touching the screen,
8340     * the button shouldn't take focus
8341     * @return Whether the view is focusable in touch mode.
8342     * @attr ref android.R.styleable#View_focusableInTouchMode
8343     */
8344    @ViewDebug.ExportedProperty
8345    public final boolean isFocusableInTouchMode() {
8346        return FOCUSABLE_IN_TOUCH_MODE == (mViewFlags & FOCUSABLE_IN_TOUCH_MODE);
8347    }
8348
8349    /**
8350     * Find the nearest view in the specified direction that can take focus.
8351     * This does not actually give focus to that view.
8352     *
8353     * @param direction One of FOCUS_UP, FOCUS_DOWN, FOCUS_LEFT, and FOCUS_RIGHT
8354     *
8355     * @return The nearest focusable in the specified direction, or null if none
8356     *         can be found.
8357     */
8358    public View focusSearch(@FocusRealDirection int direction) {
8359        if (mParent != null) {
8360            return mParent.focusSearch(this, direction);
8361        } else {
8362            return null;
8363        }
8364    }
8365
8366    /**
8367     * This method is the last chance for the focused view and its ancestors to
8368     * respond to an arrow key. This is called when the focused view did not
8369     * consume the key internally, nor could the view system find a new view in
8370     * the requested direction to give focus to.
8371     *
8372     * @param focused The currently focused view.
8373     * @param direction The direction focus wants to move. One of FOCUS_UP,
8374     *        FOCUS_DOWN, FOCUS_LEFT, and FOCUS_RIGHT.
8375     * @return True if the this view consumed this unhandled move.
8376     */
8377    public boolean dispatchUnhandledMove(View focused, @FocusRealDirection int direction) {
8378        return false;
8379    }
8380
8381    /**
8382     * If a user manually specified the next view id for a particular direction,
8383     * use the root to look up the view.
8384     * @param root The root view of the hierarchy containing this view.
8385     * @param direction One of FOCUS_UP, FOCUS_DOWN, FOCUS_LEFT, FOCUS_RIGHT, FOCUS_FORWARD,
8386     * or FOCUS_BACKWARD.
8387     * @return The user specified next view, or null if there is none.
8388     */
8389    View findUserSetNextFocus(View root, @FocusDirection int direction) {
8390        switch (direction) {
8391            case FOCUS_LEFT:
8392                if (mNextFocusLeftId == View.NO_ID) return null;
8393                return findViewInsideOutShouldExist(root, mNextFocusLeftId);
8394            case FOCUS_RIGHT:
8395                if (mNextFocusRightId == View.NO_ID) return null;
8396                return findViewInsideOutShouldExist(root, mNextFocusRightId);
8397            case FOCUS_UP:
8398                if (mNextFocusUpId == View.NO_ID) return null;
8399                return findViewInsideOutShouldExist(root, mNextFocusUpId);
8400            case FOCUS_DOWN:
8401                if (mNextFocusDownId == View.NO_ID) return null;
8402                return findViewInsideOutShouldExist(root, mNextFocusDownId);
8403            case FOCUS_FORWARD:
8404                if (mNextFocusForwardId == View.NO_ID) return null;
8405                return findViewInsideOutShouldExist(root, mNextFocusForwardId);
8406            case FOCUS_BACKWARD: {
8407                if (mID == View.NO_ID) return null;
8408                final int id = mID;
8409                return root.findViewByPredicateInsideOut(this, new Predicate<View>() {
8410                    @Override
8411                    public boolean apply(View t) {
8412                        return t.mNextFocusForwardId == id;
8413                    }
8414                });
8415            }
8416        }
8417        return null;
8418    }
8419
8420    private View findViewInsideOutShouldExist(View root, int id) {
8421        if (mMatchIdPredicate == null) {
8422            mMatchIdPredicate = new MatchIdPredicate();
8423        }
8424        mMatchIdPredicate.mId = id;
8425        View result = root.findViewByPredicateInsideOut(this, mMatchIdPredicate);
8426        if (result == null) {
8427            Log.w(VIEW_LOG_TAG, "couldn't find view with id " + id);
8428        }
8429        return result;
8430    }
8431
8432    /**
8433     * Find and return all focusable views that are descendants of this view,
8434     * possibly including this view if it is focusable itself.
8435     *
8436     * @param direction The direction of the focus
8437     * @return A list of focusable views
8438     */
8439    public ArrayList<View> getFocusables(@FocusDirection int direction) {
8440        ArrayList<View> result = new ArrayList<View>(24);
8441        addFocusables(result, direction);
8442        return result;
8443    }
8444
8445    /**
8446     * Add any focusable views that are descendants of this view (possibly
8447     * including this view if it is focusable itself) to views.  If we are in touch mode,
8448     * only add views that are also focusable in touch mode.
8449     *
8450     * @param views Focusable views found so far
8451     * @param direction The direction of the focus
8452     */
8453    public void addFocusables(ArrayList<View> views, @FocusDirection int direction) {
8454        addFocusables(views, direction, FOCUSABLES_TOUCH_MODE);
8455    }
8456
8457    /**
8458     * Adds any focusable views that are descendants of this view (possibly
8459     * including this view if it is focusable itself) to views. This method
8460     * adds all focusable views regardless if we are in touch mode or
8461     * only views focusable in touch mode if we are in touch mode or
8462     * only views that can take accessibility focus if accessibility is enabled
8463     * depending on the focusable mode parameter.
8464     *
8465     * @param views Focusable views found so far or null if all we are interested is
8466     *        the number of focusables.
8467     * @param direction The direction of the focus.
8468     * @param focusableMode The type of focusables to be added.
8469     *
8470     * @see #FOCUSABLES_ALL
8471     * @see #FOCUSABLES_TOUCH_MODE
8472     */
8473    public void addFocusables(ArrayList<View> views, @FocusDirection int direction,
8474            @FocusableMode int focusableMode) {
8475        if (views == null) {
8476            return;
8477        }
8478        if (!isFocusable()) {
8479            return;
8480        }
8481        if ((focusableMode & FOCUSABLES_TOUCH_MODE) == FOCUSABLES_TOUCH_MODE
8482                && isInTouchMode() && !isFocusableInTouchMode()) {
8483            return;
8484        }
8485        views.add(this);
8486    }
8487
8488    /**
8489     * Finds the Views that contain given text. The containment is case insensitive.
8490     * The search is performed by either the text that the View renders or the content
8491     * description that describes the view for accessibility purposes and the view does
8492     * not render or both. Clients can specify how the search is to be performed via
8493     * passing the {@link #FIND_VIEWS_WITH_TEXT} and
8494     * {@link #FIND_VIEWS_WITH_CONTENT_DESCRIPTION} flags.
8495     *
8496     * @param outViews The output list of matching Views.
8497     * @param searched The text to match against.
8498     *
8499     * @see #FIND_VIEWS_WITH_TEXT
8500     * @see #FIND_VIEWS_WITH_CONTENT_DESCRIPTION
8501     * @see #setContentDescription(CharSequence)
8502     */
8503    public void findViewsWithText(ArrayList<View> outViews, CharSequence searched,
8504            @FindViewFlags int flags) {
8505        if (getAccessibilityNodeProvider() != null) {
8506            if ((flags & FIND_VIEWS_WITH_ACCESSIBILITY_NODE_PROVIDERS) != 0) {
8507                outViews.add(this);
8508            }
8509        } else if ((flags & FIND_VIEWS_WITH_CONTENT_DESCRIPTION) != 0
8510                && (searched != null && searched.length() > 0)
8511                && (mContentDescription != null && mContentDescription.length() > 0)) {
8512            String searchedLowerCase = searched.toString().toLowerCase();
8513            String contentDescriptionLowerCase = mContentDescription.toString().toLowerCase();
8514            if (contentDescriptionLowerCase.contains(searchedLowerCase)) {
8515                outViews.add(this);
8516            }
8517        }
8518    }
8519
8520    /**
8521     * Find and return all touchable views that are descendants of this view,
8522     * possibly including this view if it is touchable itself.
8523     *
8524     * @return A list of touchable views
8525     */
8526    public ArrayList<View> getTouchables() {
8527        ArrayList<View> result = new ArrayList<View>();
8528        addTouchables(result);
8529        return result;
8530    }
8531
8532    /**
8533     * Add any touchable views that are descendants of this view (possibly
8534     * including this view if it is touchable itself) to views.
8535     *
8536     * @param views Touchable views found so far
8537     */
8538    public void addTouchables(ArrayList<View> views) {
8539        final int viewFlags = mViewFlags;
8540
8541        if (((viewFlags & CLICKABLE) == CLICKABLE || (viewFlags & LONG_CLICKABLE) == LONG_CLICKABLE
8542                || (viewFlags & CONTEXT_CLICKABLE) == CONTEXT_CLICKABLE)
8543                && (viewFlags & ENABLED_MASK) == ENABLED) {
8544            views.add(this);
8545        }
8546    }
8547
8548    /**
8549     * Returns whether this View is accessibility focused.
8550     *
8551     * @return True if this View is accessibility focused.
8552     */
8553    public boolean isAccessibilityFocused() {
8554        return (mPrivateFlags2 & PFLAG2_ACCESSIBILITY_FOCUSED) != 0;
8555    }
8556
8557    /**
8558     * Call this to try to give accessibility focus to this view.
8559     *
8560     * A view will not actually take focus if {@link AccessibilityManager#isEnabled()}
8561     * returns false or the view is no visible or the view already has accessibility
8562     * focus.
8563     *
8564     * See also {@link #focusSearch(int)}, which is what you call to say that you
8565     * have focus, and you want your parent to look for the next one.
8566     *
8567     * @return Whether this view actually took accessibility focus.
8568     *
8569     * @hide
8570     */
8571    public boolean requestAccessibilityFocus() {
8572        AccessibilityManager manager = AccessibilityManager.getInstance(mContext);
8573        if (!manager.isEnabled() || !manager.isTouchExplorationEnabled()) {
8574            return false;
8575        }
8576        if ((mViewFlags & VISIBILITY_MASK) != VISIBLE) {
8577            return false;
8578        }
8579        if ((mPrivateFlags2 & PFLAG2_ACCESSIBILITY_FOCUSED) == 0) {
8580            mPrivateFlags2 |= PFLAG2_ACCESSIBILITY_FOCUSED;
8581            ViewRootImpl viewRootImpl = getViewRootImpl();
8582            if (viewRootImpl != null) {
8583                viewRootImpl.setAccessibilityFocus(this, null);
8584            }
8585            invalidate();
8586            sendAccessibilityEvent(AccessibilityEvent.TYPE_VIEW_ACCESSIBILITY_FOCUSED);
8587            return true;
8588        }
8589        return false;
8590    }
8591
8592    /**
8593     * Call this to try to clear accessibility focus of this view.
8594     *
8595     * See also {@link #focusSearch(int)}, which is what you call to say that you
8596     * have focus, and you want your parent to look for the next one.
8597     *
8598     * @hide
8599     */
8600    public void clearAccessibilityFocus() {
8601        clearAccessibilityFocusNoCallbacks();
8602
8603        // Clear the global reference of accessibility focus if this view or
8604        // any of its descendants had accessibility focus. This will NOT send
8605        // an event or update internal state if focus is cleared from a
8606        // descendant view, which may leave views in inconsistent states.
8607        final ViewRootImpl viewRootImpl = getViewRootImpl();
8608        if (viewRootImpl != null) {
8609            final View focusHost = viewRootImpl.getAccessibilityFocusedHost();
8610            if (focusHost != null && ViewRootImpl.isViewDescendantOf(focusHost, this)) {
8611                viewRootImpl.setAccessibilityFocus(null, null);
8612            }
8613        }
8614    }
8615
8616    private void sendAccessibilityHoverEvent(int eventType) {
8617        // Since we are not delivering to a client accessibility events from not
8618        // important views (unless the clinet request that) we need to fire the
8619        // event from the deepest view exposed to the client. As a consequence if
8620        // the user crosses a not exposed view the client will see enter and exit
8621        // of the exposed predecessor followed by and enter and exit of that same
8622        // predecessor when entering and exiting the not exposed descendant. This
8623        // is fine since the client has a clear idea which view is hovered at the
8624        // price of a couple more events being sent. This is a simple and
8625        // working solution.
8626        View source = this;
8627        while (true) {
8628            if (source.includeForAccessibility()) {
8629                source.sendAccessibilityEvent(eventType);
8630                return;
8631            }
8632            ViewParent parent = source.getParent();
8633            if (parent instanceof View) {
8634                source = (View) parent;
8635            } else {
8636                return;
8637            }
8638        }
8639    }
8640
8641    /**
8642     * Clears accessibility focus without calling any callback methods
8643     * normally invoked in {@link #clearAccessibilityFocus()}. This method
8644     * is used for clearing accessibility focus when giving this focus to
8645     * another view.
8646     */
8647    void clearAccessibilityFocusNoCallbacks() {
8648        if ((mPrivateFlags2 & PFLAG2_ACCESSIBILITY_FOCUSED) != 0) {
8649            mPrivateFlags2 &= ~PFLAG2_ACCESSIBILITY_FOCUSED;
8650            invalidate();
8651            sendAccessibilityEvent(AccessibilityEvent.TYPE_VIEW_ACCESSIBILITY_FOCUS_CLEARED);
8652        }
8653    }
8654
8655    /**
8656     * Call this to try to give focus to a specific view or to one of its
8657     * descendants.
8658     *
8659     * A view will not actually take focus if it is not focusable ({@link #isFocusable} returns
8660     * false), or if it is focusable and it is not focusable in touch mode
8661     * ({@link #isFocusableInTouchMode}) while the device is in touch mode.
8662     *
8663     * See also {@link #focusSearch(int)}, which is what you call to say that you
8664     * have focus, and you want your parent to look for the next one.
8665     *
8666     * This is equivalent to calling {@link #requestFocus(int, Rect)} with arguments
8667     * {@link #FOCUS_DOWN} and <code>null</code>.
8668     *
8669     * @return Whether this view or one of its descendants actually took focus.
8670     */
8671    public final boolean requestFocus() {
8672        return requestFocus(View.FOCUS_DOWN);
8673    }
8674
8675    /**
8676     * Call this to try to give focus to a specific view or to one of its
8677     * descendants and give it a hint about what direction focus is heading.
8678     *
8679     * A view will not actually take focus if it is not focusable ({@link #isFocusable} returns
8680     * false), or if it is focusable and it is not focusable in touch mode
8681     * ({@link #isFocusableInTouchMode}) while the device is in touch mode.
8682     *
8683     * See also {@link #focusSearch(int)}, which is what you call to say that you
8684     * have focus, and you want your parent to look for the next one.
8685     *
8686     * This is equivalent to calling {@link #requestFocus(int, Rect)} with
8687     * <code>null</code> set for the previously focused rectangle.
8688     *
8689     * @param direction One of FOCUS_UP, FOCUS_DOWN, FOCUS_LEFT, and FOCUS_RIGHT
8690     * @return Whether this view or one of its descendants actually took focus.
8691     */
8692    public final boolean requestFocus(int direction) {
8693        return requestFocus(direction, null);
8694    }
8695
8696    /**
8697     * Call this to try to give focus to a specific view or to one of its descendants
8698     * and give it hints about the direction and a specific rectangle that the focus
8699     * is coming from.  The rectangle can help give larger views a finer grained hint
8700     * about where focus is coming from, and therefore, where to show selection, or
8701     * forward focus change internally.
8702     *
8703     * A view will not actually take focus if it is not focusable ({@link #isFocusable} returns
8704     * false), or if it is focusable and it is not focusable in touch mode
8705     * ({@link #isFocusableInTouchMode}) while the device is in touch mode.
8706     *
8707     * A View will not take focus if it is not visible.
8708     *
8709     * A View will not take focus if one of its parents has
8710     * {@link android.view.ViewGroup#getDescendantFocusability()} equal to
8711     * {@link ViewGroup#FOCUS_BLOCK_DESCENDANTS}.
8712     *
8713     * See also {@link #focusSearch(int)}, which is what you call to say that you
8714     * have focus, and you want your parent to look for the next one.
8715     *
8716     * You may wish to override this method if your custom {@link View} has an internal
8717     * {@link View} that it wishes to forward the request to.
8718     *
8719     * @param direction One of FOCUS_UP, FOCUS_DOWN, FOCUS_LEFT, and FOCUS_RIGHT
8720     * @param previouslyFocusedRect The rectangle (in this View's coordinate system)
8721     *        to give a finer grained hint about where focus is coming from.  May be null
8722     *        if there is no hint.
8723     * @return Whether this view or one of its descendants actually took focus.
8724     */
8725    public boolean requestFocus(int direction, Rect previouslyFocusedRect) {
8726        return requestFocusNoSearch(direction, previouslyFocusedRect);
8727    }
8728
8729    private boolean requestFocusNoSearch(int direction, Rect previouslyFocusedRect) {
8730        // need to be focusable
8731        if ((mViewFlags & FOCUSABLE_MASK) != FOCUSABLE ||
8732                (mViewFlags & VISIBILITY_MASK) != VISIBLE) {
8733            return false;
8734        }
8735
8736        // need to be focusable in touch mode if in touch mode
8737        if (isInTouchMode() &&
8738            (FOCUSABLE_IN_TOUCH_MODE != (mViewFlags & FOCUSABLE_IN_TOUCH_MODE))) {
8739               return false;
8740        }
8741
8742        // need to not have any parents blocking us
8743        if (hasAncestorThatBlocksDescendantFocus()) {
8744            return false;
8745        }
8746
8747        handleFocusGainInternal(direction, previouslyFocusedRect);
8748        return true;
8749    }
8750
8751    /**
8752     * Call this to try to give focus to a specific view or to one of its descendants. This is a
8753     * special variant of {@link #requestFocus() } that will allow views that are not focusable in
8754     * touch mode to request focus when they are touched.
8755     *
8756     * @return Whether this view or one of its descendants actually took focus.
8757     *
8758     * @see #isInTouchMode()
8759     *
8760     */
8761    public final boolean requestFocusFromTouch() {
8762        // Leave touch mode if we need to
8763        if (isInTouchMode()) {
8764            ViewRootImpl viewRoot = getViewRootImpl();
8765            if (viewRoot != null) {
8766                viewRoot.ensureTouchMode(false);
8767            }
8768        }
8769        return requestFocus(View.FOCUS_DOWN);
8770    }
8771
8772    /**
8773     * @return Whether any ancestor of this view blocks descendant focus.
8774     */
8775    private boolean hasAncestorThatBlocksDescendantFocus() {
8776        final boolean focusableInTouchMode = isFocusableInTouchMode();
8777        ViewParent ancestor = mParent;
8778        while (ancestor instanceof ViewGroup) {
8779            final ViewGroup vgAncestor = (ViewGroup) ancestor;
8780            if (vgAncestor.getDescendantFocusability() == ViewGroup.FOCUS_BLOCK_DESCENDANTS
8781                    || (!focusableInTouchMode && vgAncestor.shouldBlockFocusForTouchscreen())) {
8782                return true;
8783            } else {
8784                ancestor = vgAncestor.getParent();
8785            }
8786        }
8787        return false;
8788    }
8789
8790    /**
8791     * Gets the mode for determining whether this View is important for accessibility
8792     * which is if it fires accessibility events and if it is reported to
8793     * accessibility services that query the screen.
8794     *
8795     * @return The mode for determining whether a View is important for accessibility.
8796     *
8797     * @attr ref android.R.styleable#View_importantForAccessibility
8798     *
8799     * @see #IMPORTANT_FOR_ACCESSIBILITY_YES
8800     * @see #IMPORTANT_FOR_ACCESSIBILITY_NO
8801     * @see #IMPORTANT_FOR_ACCESSIBILITY_NO_HIDE_DESCENDANTS
8802     * @see #IMPORTANT_FOR_ACCESSIBILITY_AUTO
8803     */
8804    @ViewDebug.ExportedProperty(category = "accessibility", mapping = {
8805            @ViewDebug.IntToString(from = IMPORTANT_FOR_ACCESSIBILITY_AUTO, to = "auto"),
8806            @ViewDebug.IntToString(from = IMPORTANT_FOR_ACCESSIBILITY_YES, to = "yes"),
8807            @ViewDebug.IntToString(from = IMPORTANT_FOR_ACCESSIBILITY_NO, to = "no"),
8808            @ViewDebug.IntToString(from = IMPORTANT_FOR_ACCESSIBILITY_NO_HIDE_DESCENDANTS,
8809                    to = "noHideDescendants")
8810        })
8811    public int getImportantForAccessibility() {
8812        return (mPrivateFlags2 & PFLAG2_IMPORTANT_FOR_ACCESSIBILITY_MASK)
8813                >> PFLAG2_IMPORTANT_FOR_ACCESSIBILITY_SHIFT;
8814    }
8815
8816    /**
8817     * Sets the live region mode for this view. This indicates to accessibility
8818     * services whether they should automatically notify the user about changes
8819     * to the view's content description or text, or to the content descriptions
8820     * or text of the view's children (where applicable).
8821     * <p>
8822     * For example, in a login screen with a TextView that displays an "incorrect
8823     * password" notification, that view should be marked as a live region with
8824     * mode {@link #ACCESSIBILITY_LIVE_REGION_POLITE}.
8825     * <p>
8826     * To disable change notifications for this view, use
8827     * {@link #ACCESSIBILITY_LIVE_REGION_NONE}. This is the default live region
8828     * mode for most views.
8829     * <p>
8830     * To indicate that the user should be notified of changes, use
8831     * {@link #ACCESSIBILITY_LIVE_REGION_POLITE}.
8832     * <p>
8833     * If the view's changes should interrupt ongoing speech and notify the user
8834     * immediately, use {@link #ACCESSIBILITY_LIVE_REGION_ASSERTIVE}.
8835     *
8836     * @param mode The live region mode for this view, one of:
8837     *        <ul>
8838     *        <li>{@link #ACCESSIBILITY_LIVE_REGION_NONE}
8839     *        <li>{@link #ACCESSIBILITY_LIVE_REGION_POLITE}
8840     *        <li>{@link #ACCESSIBILITY_LIVE_REGION_ASSERTIVE}
8841     *        </ul>
8842     * @attr ref android.R.styleable#View_accessibilityLiveRegion
8843     */
8844    public void setAccessibilityLiveRegion(int mode) {
8845        if (mode != getAccessibilityLiveRegion()) {
8846            mPrivateFlags2 &= ~PFLAG2_ACCESSIBILITY_LIVE_REGION_MASK;
8847            mPrivateFlags2 |= (mode << PFLAG2_ACCESSIBILITY_LIVE_REGION_SHIFT)
8848                    & PFLAG2_ACCESSIBILITY_LIVE_REGION_MASK;
8849            notifyViewAccessibilityStateChangedIfNeeded(
8850                    AccessibilityEvent.CONTENT_CHANGE_TYPE_UNDEFINED);
8851        }
8852    }
8853
8854    /**
8855     * Gets the live region mode for this View.
8856     *
8857     * @return The live region mode for the view.
8858     *
8859     * @attr ref android.R.styleable#View_accessibilityLiveRegion
8860     *
8861     * @see #setAccessibilityLiveRegion(int)
8862     */
8863    public int getAccessibilityLiveRegion() {
8864        return (mPrivateFlags2 & PFLAG2_ACCESSIBILITY_LIVE_REGION_MASK)
8865                >> PFLAG2_ACCESSIBILITY_LIVE_REGION_SHIFT;
8866    }
8867
8868    /**
8869     * Sets how to determine whether this view is important for accessibility
8870     * which is if it fires accessibility events and if it is reported to
8871     * accessibility services that query the screen.
8872     *
8873     * @param mode How to determine whether this view is important for accessibility.
8874     *
8875     * @attr ref android.R.styleable#View_importantForAccessibility
8876     *
8877     * @see #IMPORTANT_FOR_ACCESSIBILITY_YES
8878     * @see #IMPORTANT_FOR_ACCESSIBILITY_NO
8879     * @see #IMPORTANT_FOR_ACCESSIBILITY_NO_HIDE_DESCENDANTS
8880     * @see #IMPORTANT_FOR_ACCESSIBILITY_AUTO
8881     */
8882    public void setImportantForAccessibility(int mode) {
8883        final int oldMode = getImportantForAccessibility();
8884        if (mode != oldMode) {
8885            final boolean hideDescendants =
8886                    mode == IMPORTANT_FOR_ACCESSIBILITY_NO_HIDE_DESCENDANTS;
8887
8888            // If this node or its descendants are no longer important, try to
8889            // clear accessibility focus.
8890            if (mode == IMPORTANT_FOR_ACCESSIBILITY_NO || hideDescendants) {
8891                final View focusHost = findAccessibilityFocusHost(hideDescendants);
8892                if (focusHost != null) {
8893                    focusHost.clearAccessibilityFocus();
8894                }
8895            }
8896
8897            // If we're moving between AUTO and another state, we might not need
8898            // to send a subtree changed notification. We'll store the computed
8899            // importance, since we'll need to check it later to make sure.
8900            final boolean maySkipNotify = oldMode == IMPORTANT_FOR_ACCESSIBILITY_AUTO
8901                    || mode == IMPORTANT_FOR_ACCESSIBILITY_AUTO;
8902            final boolean oldIncludeForAccessibility = maySkipNotify && includeForAccessibility();
8903            mPrivateFlags2 &= ~PFLAG2_IMPORTANT_FOR_ACCESSIBILITY_MASK;
8904            mPrivateFlags2 |= (mode << PFLAG2_IMPORTANT_FOR_ACCESSIBILITY_SHIFT)
8905                    & PFLAG2_IMPORTANT_FOR_ACCESSIBILITY_MASK;
8906            if (!maySkipNotify || oldIncludeForAccessibility != includeForAccessibility()) {
8907                notifySubtreeAccessibilityStateChangedIfNeeded();
8908            } else {
8909                notifyViewAccessibilityStateChangedIfNeeded(
8910                        AccessibilityEvent.CONTENT_CHANGE_TYPE_UNDEFINED);
8911            }
8912        }
8913    }
8914
8915    /**
8916     * Returns the view within this view's hierarchy that is hosting
8917     * accessibility focus.
8918     *
8919     * @param searchDescendants whether to search for focus in descendant views
8920     * @return the view hosting accessibility focus, or {@code null}
8921     */
8922    private View findAccessibilityFocusHost(boolean searchDescendants) {
8923        if (isAccessibilityFocusedViewOrHost()) {
8924            return this;
8925        }
8926
8927        if (searchDescendants) {
8928            final ViewRootImpl viewRoot = getViewRootImpl();
8929            if (viewRoot != null) {
8930                final View focusHost = viewRoot.getAccessibilityFocusedHost();
8931                if (focusHost != null && ViewRootImpl.isViewDescendantOf(focusHost, this)) {
8932                    return focusHost;
8933                }
8934            }
8935        }
8936
8937        return null;
8938    }
8939
8940    /**
8941     * Computes whether this view should be exposed for accessibility. In
8942     * general, views that are interactive or provide information are exposed
8943     * while views that serve only as containers are hidden.
8944     * <p>
8945     * If an ancestor of this view has importance
8946     * {@link #IMPORTANT_FOR_ACCESSIBILITY_NO_HIDE_DESCENDANTS}, this method
8947     * returns <code>false</code>.
8948     * <p>
8949     * Otherwise, the value is computed according to the view's
8950     * {@link #getImportantForAccessibility()} value:
8951     * <ol>
8952     * <li>{@link #IMPORTANT_FOR_ACCESSIBILITY_NO} or
8953     * {@link #IMPORTANT_FOR_ACCESSIBILITY_NO_HIDE_DESCENDANTS}, return <code>false
8954     * </code>
8955     * <li>{@link #IMPORTANT_FOR_ACCESSIBILITY_YES}, return <code>true</code>
8956     * <li>{@link #IMPORTANT_FOR_ACCESSIBILITY_AUTO}, return <code>true</code> if
8957     * view satisfies any of the following:
8958     * <ul>
8959     * <li>Is actionable, e.g. {@link #isClickable()},
8960     * {@link #isLongClickable()}, or {@link #isFocusable()}
8961     * <li>Has an {@link AccessibilityDelegate}
8962     * <li>Has an interaction listener, e.g. {@link OnTouchListener},
8963     * {@link OnKeyListener}, etc.
8964     * <li>Is an accessibility live region, e.g.
8965     * {@link #getAccessibilityLiveRegion()} is not
8966     * {@link #ACCESSIBILITY_LIVE_REGION_NONE}.
8967     * </ul>
8968     * </ol>
8969     *
8970     * @return Whether the view is exposed for accessibility.
8971     * @see #setImportantForAccessibility(int)
8972     * @see #getImportantForAccessibility()
8973     */
8974    public boolean isImportantForAccessibility() {
8975        final int mode = (mPrivateFlags2 & PFLAG2_IMPORTANT_FOR_ACCESSIBILITY_MASK)
8976                >> PFLAG2_IMPORTANT_FOR_ACCESSIBILITY_SHIFT;
8977        if (mode == IMPORTANT_FOR_ACCESSIBILITY_NO
8978                || mode == IMPORTANT_FOR_ACCESSIBILITY_NO_HIDE_DESCENDANTS) {
8979            return false;
8980        }
8981
8982        // Check parent mode to ensure we're not hidden.
8983        ViewParent parent = mParent;
8984        while (parent instanceof View) {
8985            if (((View) parent).getImportantForAccessibility()
8986                    == IMPORTANT_FOR_ACCESSIBILITY_NO_HIDE_DESCENDANTS) {
8987                return false;
8988            }
8989            parent = parent.getParent();
8990        }
8991
8992        return mode == IMPORTANT_FOR_ACCESSIBILITY_YES || isActionableForAccessibility()
8993                || hasListenersForAccessibility() || getAccessibilityNodeProvider() != null
8994                || getAccessibilityLiveRegion() != ACCESSIBILITY_LIVE_REGION_NONE;
8995    }
8996
8997    /**
8998     * Gets the parent for accessibility purposes. Note that the parent for
8999     * accessibility is not necessary the immediate parent. It is the first
9000     * predecessor that is important for accessibility.
9001     *
9002     * @return The parent for accessibility purposes.
9003     */
9004    public ViewParent getParentForAccessibility() {
9005        if (mParent instanceof View) {
9006            View parentView = (View) mParent;
9007            if (parentView.includeForAccessibility()) {
9008                return mParent;
9009            } else {
9010                return mParent.getParentForAccessibility();
9011            }
9012        }
9013        return null;
9014    }
9015
9016    /**
9017     * Adds the children of this View relevant for accessibility to the given list
9018     * as output. Since some Views are not important for accessibility the added
9019     * child views are not necessarily direct children of this view, rather they are
9020     * the first level of descendants important for accessibility.
9021     *
9022     * @param outChildren The output list that will receive children for accessibility.
9023     */
9024    public void addChildrenForAccessibility(ArrayList<View> outChildren) {
9025
9026    }
9027
9028    /**
9029     * Whether to regard this view for accessibility. A view is regarded for
9030     * accessibility if it is important for accessibility or the querying
9031     * accessibility service has explicitly requested that view not
9032     * important for accessibility are regarded.
9033     *
9034     * @return Whether to regard the view for accessibility.
9035     *
9036     * @hide
9037     */
9038    public boolean includeForAccessibility() {
9039        if (mAttachInfo != null) {
9040            return (mAttachInfo.mAccessibilityFetchFlags
9041                    & AccessibilityNodeInfo.FLAG_INCLUDE_NOT_IMPORTANT_VIEWS) != 0
9042                    || isImportantForAccessibility();
9043        }
9044        return false;
9045    }
9046
9047    /**
9048     * Returns whether the View is considered actionable from
9049     * accessibility perspective. Such view are important for
9050     * accessibility.
9051     *
9052     * @return True if the view is actionable for accessibility.
9053     *
9054     * @hide
9055     */
9056    public boolean isActionableForAccessibility() {
9057        return (isClickable() || isLongClickable() || isFocusable());
9058    }
9059
9060    /**
9061     * Returns whether the View has registered callbacks which makes it
9062     * important for accessibility.
9063     *
9064     * @return True if the view is actionable for accessibility.
9065     */
9066    private boolean hasListenersForAccessibility() {
9067        ListenerInfo info = getListenerInfo();
9068        return mTouchDelegate != null || info.mOnKeyListener != null
9069                || info.mOnTouchListener != null || info.mOnGenericMotionListener != null
9070                || info.mOnHoverListener != null || info.mOnDragListener != null;
9071    }
9072
9073    /**
9074     * Notifies that the accessibility state of this view changed. The change
9075     * is local to this view and does not represent structural changes such
9076     * as children and parent. For example, the view became focusable. The
9077     * notification is at at most once every
9078     * {@link ViewConfiguration#getSendRecurringAccessibilityEventsInterval()}
9079     * to avoid unnecessary load to the system. Also once a view has a pending
9080     * notification this method is a NOP until the notification has been sent.
9081     *
9082     * @hide
9083     */
9084    public void notifyViewAccessibilityStateChangedIfNeeded(int changeType) {
9085        if (!AccessibilityManager.getInstance(mContext).isEnabled() || mAttachInfo == null) {
9086            return;
9087        }
9088        if (mSendViewStateChangedAccessibilityEvent == null) {
9089            mSendViewStateChangedAccessibilityEvent =
9090                    new SendViewStateChangedAccessibilityEvent();
9091        }
9092        mSendViewStateChangedAccessibilityEvent.runOrPost(changeType);
9093    }
9094
9095    /**
9096     * Notifies that the accessibility state of this view changed. The change
9097     * is *not* local to this view and does represent structural changes such
9098     * as children and parent. For example, the view size changed. The
9099     * notification is at at most once every
9100     * {@link ViewConfiguration#getSendRecurringAccessibilityEventsInterval()}
9101     * to avoid unnecessary load to the system. Also once a view has a pending
9102     * notification this method is a NOP until the notification has been sent.
9103     *
9104     * @hide
9105     */
9106    public void notifySubtreeAccessibilityStateChangedIfNeeded() {
9107        if (!AccessibilityManager.getInstance(mContext).isEnabled() || mAttachInfo == null) {
9108            return;
9109        }
9110        if ((mPrivateFlags2 & PFLAG2_SUBTREE_ACCESSIBILITY_STATE_CHANGED) == 0) {
9111            mPrivateFlags2 |= PFLAG2_SUBTREE_ACCESSIBILITY_STATE_CHANGED;
9112            if (mParent != null) {
9113                try {
9114                    mParent.notifySubtreeAccessibilityStateChanged(
9115                            this, this, AccessibilityEvent.CONTENT_CHANGE_TYPE_SUBTREE);
9116                } catch (AbstractMethodError e) {
9117                    Log.e(VIEW_LOG_TAG, mParent.getClass().getSimpleName() +
9118                            " does not fully implement ViewParent", e);
9119                }
9120            }
9121        }
9122    }
9123
9124    /**
9125     * Change the visibility of the View without triggering any other changes. This is
9126     * important for transitions, where visibility changes should not adjust focus or
9127     * trigger a new layout. This is only used when the visibility has already been changed
9128     * and we need a transient value during an animation. When the animation completes,
9129     * the original visibility value is always restored.
9130     *
9131     * @param visibility One of {@link #VISIBLE}, {@link #INVISIBLE}, or {@link #GONE}.
9132     * @hide
9133     */
9134    public void setTransitionVisibility(@Visibility int visibility) {
9135        mViewFlags = (mViewFlags & ~View.VISIBILITY_MASK) | visibility;
9136    }
9137
9138    /**
9139     * Reset the flag indicating the accessibility state of the subtree rooted
9140     * at this view changed.
9141     */
9142    void resetSubtreeAccessibilityStateChanged() {
9143        mPrivateFlags2 &= ~PFLAG2_SUBTREE_ACCESSIBILITY_STATE_CHANGED;
9144    }
9145
9146    /**
9147     * Report an accessibility action to this view's parents for delegated processing.
9148     *
9149     * <p>Implementations of {@link #performAccessibilityAction(int, Bundle)} may internally
9150     * call this method to delegate an accessibility action to a supporting parent. If the parent
9151     * returns true from its
9152     * {@link ViewParent#onNestedPrePerformAccessibilityAction(View, int, android.os.Bundle)}
9153     * method this method will return true to signify that the action was consumed.</p>
9154     *
9155     * <p>This method is useful for implementing nested scrolling child views. If
9156     * {@link #isNestedScrollingEnabled()} returns true and the action is a scrolling action
9157     * a custom view implementation may invoke this method to allow a parent to consume the
9158     * scroll first. If this method returns true the custom view should skip its own scrolling
9159     * behavior.</p>
9160     *
9161     * @param action Accessibility action to delegate
9162     * @param arguments Optional action arguments
9163     * @return true if the action was consumed by a parent
9164     */
9165    public boolean dispatchNestedPrePerformAccessibilityAction(int action, Bundle arguments) {
9166        for (ViewParent p = getParent(); p != null; p = p.getParent()) {
9167            if (p.onNestedPrePerformAccessibilityAction(this, action, arguments)) {
9168                return true;
9169            }
9170        }
9171        return false;
9172    }
9173
9174    /**
9175     * Performs the specified accessibility action on the view. For
9176     * possible accessibility actions look at {@link AccessibilityNodeInfo}.
9177     * <p>
9178     * If an {@link AccessibilityDelegate} has been specified via calling
9179     * {@link #setAccessibilityDelegate(AccessibilityDelegate)} its
9180     * {@link AccessibilityDelegate#performAccessibilityAction(View, int, Bundle)}
9181     * is responsible for handling this call.
9182     * </p>
9183     *
9184     * <p>The default implementation will delegate
9185     * {@link AccessibilityNodeInfo#ACTION_SCROLL_BACKWARD} and
9186     * {@link AccessibilityNodeInfo#ACTION_SCROLL_FORWARD} to nested scrolling parents if
9187     * {@link #isNestedScrollingEnabled() nested scrolling is enabled} on this view.</p>
9188     *
9189     * @param action The action to perform.
9190     * @param arguments Optional action arguments.
9191     * @return Whether the action was performed.
9192     */
9193    public boolean performAccessibilityAction(int action, Bundle arguments) {
9194      if (mAccessibilityDelegate != null) {
9195          return mAccessibilityDelegate.performAccessibilityAction(this, action, arguments);
9196      } else {
9197          return performAccessibilityActionInternal(action, arguments);
9198      }
9199    }
9200
9201   /**
9202    * @see #performAccessibilityAction(int, Bundle)
9203    *
9204    * Note: Called from the default {@link AccessibilityDelegate}.
9205    *
9206    * @hide
9207    */
9208    public boolean performAccessibilityActionInternal(int action, Bundle arguments) {
9209        if (isNestedScrollingEnabled()
9210                && (action == AccessibilityNodeInfo.ACTION_SCROLL_BACKWARD
9211                || action == AccessibilityNodeInfo.ACTION_SCROLL_FORWARD
9212                || action == R.id.accessibilityActionScrollUp
9213                || action == R.id.accessibilityActionScrollLeft
9214                || action == R.id.accessibilityActionScrollDown
9215                || action == R.id.accessibilityActionScrollRight)) {
9216            if (dispatchNestedPrePerformAccessibilityAction(action, arguments)) {
9217                return true;
9218            }
9219        }
9220
9221        switch (action) {
9222            case AccessibilityNodeInfo.ACTION_CLICK: {
9223                if (isClickable()) {
9224                    performClick();
9225                    return true;
9226                }
9227            } break;
9228            case AccessibilityNodeInfo.ACTION_LONG_CLICK: {
9229                if (isLongClickable()) {
9230                    performLongClick();
9231                    return true;
9232                }
9233            } break;
9234            case AccessibilityNodeInfo.ACTION_FOCUS: {
9235                if (!hasFocus()) {
9236                    // Get out of touch mode since accessibility
9237                    // wants to move focus around.
9238                    getViewRootImpl().ensureTouchMode(false);
9239                    return requestFocus();
9240                }
9241            } break;
9242            case AccessibilityNodeInfo.ACTION_CLEAR_FOCUS: {
9243                if (hasFocus()) {
9244                    clearFocus();
9245                    return !isFocused();
9246                }
9247            } break;
9248            case AccessibilityNodeInfo.ACTION_SELECT: {
9249                if (!isSelected()) {
9250                    setSelected(true);
9251                    return isSelected();
9252                }
9253            } break;
9254            case AccessibilityNodeInfo.ACTION_CLEAR_SELECTION: {
9255                if (isSelected()) {
9256                    setSelected(false);
9257                    return !isSelected();
9258                }
9259            } break;
9260            case AccessibilityNodeInfo.ACTION_ACCESSIBILITY_FOCUS: {
9261                if (!isAccessibilityFocused()) {
9262                    return requestAccessibilityFocus();
9263                }
9264            } break;
9265            case AccessibilityNodeInfo.ACTION_CLEAR_ACCESSIBILITY_FOCUS: {
9266                if (isAccessibilityFocused()) {
9267                    clearAccessibilityFocus();
9268                    return true;
9269                }
9270            } break;
9271            case AccessibilityNodeInfo.ACTION_NEXT_AT_MOVEMENT_GRANULARITY: {
9272                if (arguments != null) {
9273                    final int granularity = arguments.getInt(
9274                            AccessibilityNodeInfo.ACTION_ARGUMENT_MOVEMENT_GRANULARITY_INT);
9275                    final boolean extendSelection = arguments.getBoolean(
9276                            AccessibilityNodeInfo.ACTION_ARGUMENT_EXTEND_SELECTION_BOOLEAN);
9277                    return traverseAtGranularity(granularity, true, extendSelection);
9278                }
9279            } break;
9280            case AccessibilityNodeInfo.ACTION_PREVIOUS_AT_MOVEMENT_GRANULARITY: {
9281                if (arguments != null) {
9282                    final int granularity = arguments.getInt(
9283                            AccessibilityNodeInfo.ACTION_ARGUMENT_MOVEMENT_GRANULARITY_INT);
9284                    final boolean extendSelection = arguments.getBoolean(
9285                            AccessibilityNodeInfo.ACTION_ARGUMENT_EXTEND_SELECTION_BOOLEAN);
9286                    return traverseAtGranularity(granularity, false, extendSelection);
9287                }
9288            } break;
9289            case AccessibilityNodeInfo.ACTION_SET_SELECTION: {
9290                CharSequence text = getIterableTextForAccessibility();
9291                if (text == null) {
9292                    return false;
9293                }
9294                final int start = (arguments != null) ? arguments.getInt(
9295                        AccessibilityNodeInfo.ACTION_ARGUMENT_SELECTION_START_INT, -1) : -1;
9296                final int end = (arguments != null) ? arguments.getInt(
9297                AccessibilityNodeInfo.ACTION_ARGUMENT_SELECTION_END_INT, -1) : -1;
9298                // Only cursor position can be specified (selection length == 0)
9299                if ((getAccessibilitySelectionStart() != start
9300                        || getAccessibilitySelectionEnd() != end)
9301                        && (start == end)) {
9302                    setAccessibilitySelection(start, end);
9303                    notifyViewAccessibilityStateChangedIfNeeded(
9304                            AccessibilityEvent.CONTENT_CHANGE_TYPE_UNDEFINED);
9305                    return true;
9306                }
9307            } break;
9308            case R.id.accessibilityActionShowOnScreen: {
9309                if (mAttachInfo != null) {
9310                    final Rect r = mAttachInfo.mTmpInvalRect;
9311                    getDrawingRect(r);
9312                    return requestRectangleOnScreen(r, true);
9313                }
9314            } break;
9315            case R.id.accessibilityActionContextClick: {
9316                if (isContextClickable()) {
9317                    performContextClick();
9318                    return true;
9319                }
9320            } break;
9321        }
9322        return false;
9323    }
9324
9325    private boolean traverseAtGranularity(int granularity, boolean forward,
9326            boolean extendSelection) {
9327        CharSequence text = getIterableTextForAccessibility();
9328        if (text == null || text.length() == 0) {
9329            return false;
9330        }
9331        TextSegmentIterator iterator = getIteratorForGranularity(granularity);
9332        if (iterator == null) {
9333            return false;
9334        }
9335        int current = getAccessibilitySelectionEnd();
9336        if (current == ACCESSIBILITY_CURSOR_POSITION_UNDEFINED) {
9337            current = forward ? 0 : text.length();
9338        }
9339        final int[] range = forward ? iterator.following(current) : iterator.preceding(current);
9340        if (range == null) {
9341            return false;
9342        }
9343        final int segmentStart = range[0];
9344        final int segmentEnd = range[1];
9345        int selectionStart;
9346        int selectionEnd;
9347        if (extendSelection && isAccessibilitySelectionExtendable()) {
9348            selectionStart = getAccessibilitySelectionStart();
9349            if (selectionStart == ACCESSIBILITY_CURSOR_POSITION_UNDEFINED) {
9350                selectionStart = forward ? segmentStart : segmentEnd;
9351            }
9352            selectionEnd = forward ? segmentEnd : segmentStart;
9353        } else {
9354            selectionStart = selectionEnd= forward ? segmentEnd : segmentStart;
9355        }
9356        setAccessibilitySelection(selectionStart, selectionEnd);
9357        final int action = forward ? AccessibilityNodeInfo.ACTION_NEXT_AT_MOVEMENT_GRANULARITY
9358                : AccessibilityNodeInfo.ACTION_PREVIOUS_AT_MOVEMENT_GRANULARITY;
9359        sendViewTextTraversedAtGranularityEvent(action, granularity, segmentStart, segmentEnd);
9360        return true;
9361    }
9362
9363    /**
9364     * Gets the text reported for accessibility purposes.
9365     *
9366     * @return The accessibility text.
9367     *
9368     * @hide
9369     */
9370    public CharSequence getIterableTextForAccessibility() {
9371        return getContentDescription();
9372    }
9373
9374    /**
9375     * Gets whether accessibility selection can be extended.
9376     *
9377     * @return If selection is extensible.
9378     *
9379     * @hide
9380     */
9381    public boolean isAccessibilitySelectionExtendable() {
9382        return false;
9383    }
9384
9385    /**
9386     * @hide
9387     */
9388    public int getAccessibilitySelectionStart() {
9389        return mAccessibilityCursorPosition;
9390    }
9391
9392    /**
9393     * @hide
9394     */
9395    public int getAccessibilitySelectionEnd() {
9396        return getAccessibilitySelectionStart();
9397    }
9398
9399    /**
9400     * @hide
9401     */
9402    public void setAccessibilitySelection(int start, int end) {
9403        if (start ==  end && end == mAccessibilityCursorPosition) {
9404            return;
9405        }
9406        if (start >= 0 && start == end && end <= getIterableTextForAccessibility().length()) {
9407            mAccessibilityCursorPosition = start;
9408        } else {
9409            mAccessibilityCursorPosition = ACCESSIBILITY_CURSOR_POSITION_UNDEFINED;
9410        }
9411        sendAccessibilityEvent(AccessibilityEvent.TYPE_VIEW_TEXT_SELECTION_CHANGED);
9412    }
9413
9414    private void sendViewTextTraversedAtGranularityEvent(int action, int granularity,
9415            int fromIndex, int toIndex) {
9416        if (mParent == null) {
9417            return;
9418        }
9419        AccessibilityEvent event = AccessibilityEvent.obtain(
9420                AccessibilityEvent.TYPE_VIEW_TEXT_TRAVERSED_AT_MOVEMENT_GRANULARITY);
9421        onInitializeAccessibilityEvent(event);
9422        onPopulateAccessibilityEvent(event);
9423        event.setFromIndex(fromIndex);
9424        event.setToIndex(toIndex);
9425        event.setAction(action);
9426        event.setMovementGranularity(granularity);
9427        mParent.requestSendAccessibilityEvent(this, event);
9428    }
9429
9430    /**
9431     * @hide
9432     */
9433    public TextSegmentIterator getIteratorForGranularity(int granularity) {
9434        switch (granularity) {
9435            case AccessibilityNodeInfo.MOVEMENT_GRANULARITY_CHARACTER: {
9436                CharSequence text = getIterableTextForAccessibility();
9437                if (text != null && text.length() > 0) {
9438                    CharacterTextSegmentIterator iterator =
9439                        CharacterTextSegmentIterator.getInstance(
9440                                mContext.getResources().getConfiguration().locale);
9441                    iterator.initialize(text.toString());
9442                    return iterator;
9443                }
9444            } break;
9445            case AccessibilityNodeInfo.MOVEMENT_GRANULARITY_WORD: {
9446                CharSequence text = getIterableTextForAccessibility();
9447                if (text != null && text.length() > 0) {
9448                    WordTextSegmentIterator iterator =
9449                        WordTextSegmentIterator.getInstance(
9450                                mContext.getResources().getConfiguration().locale);
9451                    iterator.initialize(text.toString());
9452                    return iterator;
9453                }
9454            } break;
9455            case AccessibilityNodeInfo.MOVEMENT_GRANULARITY_PARAGRAPH: {
9456                CharSequence text = getIterableTextForAccessibility();
9457                if (text != null && text.length() > 0) {
9458                    ParagraphTextSegmentIterator iterator =
9459                        ParagraphTextSegmentIterator.getInstance();
9460                    iterator.initialize(text.toString());
9461                    return iterator;
9462                }
9463            } break;
9464        }
9465        return null;
9466    }
9467
9468    /**
9469     * @hide
9470     */
9471    public void dispatchStartTemporaryDetach() {
9472        onStartTemporaryDetach();
9473    }
9474
9475    /**
9476     * This is called when a container is going to temporarily detach a child, with
9477     * {@link ViewGroup#detachViewFromParent(View) ViewGroup.detachViewFromParent}.
9478     * It will either be followed by {@link #onFinishTemporaryDetach()} or
9479     * {@link #onDetachedFromWindow()} when the container is done.
9480     */
9481    public void onStartTemporaryDetach() {
9482        removeUnsetPressCallback();
9483        mPrivateFlags |= PFLAG_CANCEL_NEXT_UP_EVENT;
9484    }
9485
9486    /**
9487     * @hide
9488     */
9489    public void dispatchFinishTemporaryDetach() {
9490        onFinishTemporaryDetach();
9491    }
9492
9493    /**
9494     * Called after {@link #onStartTemporaryDetach} when the container is done
9495     * changing the view.
9496     */
9497    public void onFinishTemporaryDetach() {
9498    }
9499
9500    /**
9501     * Return the global {@link KeyEvent.DispatcherState KeyEvent.DispatcherState}
9502     * for this view's window.  Returns null if the view is not currently attached
9503     * to the window.  Normally you will not need to use this directly, but
9504     * just use the standard high-level event callbacks like
9505     * {@link #onKeyDown(int, KeyEvent)}.
9506     */
9507    public KeyEvent.DispatcherState getKeyDispatcherState() {
9508        return mAttachInfo != null ? mAttachInfo.mKeyDispatchState : null;
9509    }
9510
9511    /**
9512     * Dispatch a key event before it is processed by any input method
9513     * associated with the view hierarchy.  This can be used to intercept
9514     * key events in special situations before the IME consumes them; a
9515     * typical example would be handling the BACK key to update the application's
9516     * UI instead of allowing the IME to see it and close itself.
9517     *
9518     * @param event The key event to be dispatched.
9519     * @return True if the event was handled, false otherwise.
9520     */
9521    public boolean dispatchKeyEventPreIme(KeyEvent event) {
9522        return onKeyPreIme(event.getKeyCode(), event);
9523    }
9524
9525    /**
9526     * Dispatch a key event to the next view on the focus path. This path runs
9527     * from the top of the view tree down to the currently focused view. If this
9528     * view has focus, it will dispatch to itself. Otherwise it will dispatch
9529     * the next node down the focus path. This method also fires any key
9530     * listeners.
9531     *
9532     * @param event The key event to be dispatched.
9533     * @return True if the event was handled, false otherwise.
9534     */
9535    public boolean dispatchKeyEvent(KeyEvent event) {
9536        if (mInputEventConsistencyVerifier != null) {
9537            mInputEventConsistencyVerifier.onKeyEvent(event, 0);
9538        }
9539
9540        // Give any attached key listener a first crack at the event.
9541        //noinspection SimplifiableIfStatement
9542        ListenerInfo li = mListenerInfo;
9543        if (li != null && li.mOnKeyListener != null && (mViewFlags & ENABLED_MASK) == ENABLED
9544                && li.mOnKeyListener.onKey(this, event.getKeyCode(), event)) {
9545            return true;
9546        }
9547
9548        if (event.dispatch(this, mAttachInfo != null
9549                ? mAttachInfo.mKeyDispatchState : null, this)) {
9550            return true;
9551        }
9552
9553        if (mInputEventConsistencyVerifier != null) {
9554            mInputEventConsistencyVerifier.onUnhandledEvent(event, 0);
9555        }
9556        return false;
9557    }
9558
9559    /**
9560     * Dispatches a key shortcut event.
9561     *
9562     * @param event The key event to be dispatched.
9563     * @return True if the event was handled by the view, false otherwise.
9564     */
9565    public boolean dispatchKeyShortcutEvent(KeyEvent event) {
9566        return onKeyShortcut(event.getKeyCode(), event);
9567    }
9568
9569    /**
9570     * Pass the touch screen motion event down to the target view, or this
9571     * view if it is the target.
9572     *
9573     * @param event The motion event to be dispatched.
9574     * @return True if the event was handled by the view, false otherwise.
9575     */
9576    public boolean dispatchTouchEvent(MotionEvent event) {
9577        // If the event should be handled by accessibility focus first.
9578        if (event.isTargetAccessibilityFocus()) {
9579            // We don't have focus or no virtual descendant has it, do not handle the event.
9580            if (!isAccessibilityFocusedViewOrHost()) {
9581                return false;
9582            }
9583            // We have focus and got the event, then use normal event dispatch.
9584            event.setTargetAccessibilityFocus(false);
9585        }
9586
9587        boolean result = false;
9588
9589        if (mInputEventConsistencyVerifier != null) {
9590            mInputEventConsistencyVerifier.onTouchEvent(event, 0);
9591        }
9592
9593        final int actionMasked = event.getActionMasked();
9594        if (actionMasked == MotionEvent.ACTION_DOWN) {
9595            // Defensive cleanup for new gesture
9596            stopNestedScroll();
9597        }
9598
9599        if (onFilterTouchEventForSecurity(event)) {
9600            //noinspection SimplifiableIfStatement
9601            ListenerInfo li = mListenerInfo;
9602            if (li != null && li.mOnTouchListener != null
9603                    && (mViewFlags & ENABLED_MASK) == ENABLED
9604                    && li.mOnTouchListener.onTouch(this, event)) {
9605                result = true;
9606            }
9607
9608            if (!result && onTouchEvent(event)) {
9609                result = true;
9610            }
9611        }
9612
9613        if (!result && mInputEventConsistencyVerifier != null) {
9614            mInputEventConsistencyVerifier.onUnhandledEvent(event, 0);
9615        }
9616
9617        // Clean up after nested scrolls if this is the end of a gesture;
9618        // also cancel it if we tried an ACTION_DOWN but we didn't want the rest
9619        // of the gesture.
9620        if (actionMasked == MotionEvent.ACTION_UP ||
9621                actionMasked == MotionEvent.ACTION_CANCEL ||
9622                (actionMasked == MotionEvent.ACTION_DOWN && !result)) {
9623            stopNestedScroll();
9624        }
9625
9626        return result;
9627    }
9628
9629    boolean isAccessibilityFocusedViewOrHost() {
9630        return isAccessibilityFocused() || (getViewRootImpl() != null && getViewRootImpl()
9631                .getAccessibilityFocusedHost() == this);
9632    }
9633
9634    /**
9635     * Filter the touch event to apply security policies.
9636     *
9637     * @param event The motion event to be filtered.
9638     * @return True if the event should be dispatched, false if the event should be dropped.
9639     *
9640     * @see #getFilterTouchesWhenObscured
9641     */
9642    public boolean onFilterTouchEventForSecurity(MotionEvent event) {
9643        //noinspection RedundantIfStatement
9644        if ((mViewFlags & FILTER_TOUCHES_WHEN_OBSCURED) != 0
9645                && (event.getFlags() & MotionEvent.FLAG_WINDOW_IS_OBSCURED) != 0) {
9646            // Window is obscured, drop this touch.
9647            return false;
9648        }
9649        return true;
9650    }
9651
9652    /**
9653     * Pass a trackball motion event down to the focused view.
9654     *
9655     * @param event The motion event to be dispatched.
9656     * @return True if the event was handled by the view, false otherwise.
9657     */
9658    public boolean dispatchTrackballEvent(MotionEvent event) {
9659        if (mInputEventConsistencyVerifier != null) {
9660            mInputEventConsistencyVerifier.onTrackballEvent(event, 0);
9661        }
9662
9663        return onTrackballEvent(event);
9664    }
9665
9666    /**
9667     * Dispatch a generic motion event.
9668     * <p>
9669     * Generic motion events with source class {@link InputDevice#SOURCE_CLASS_POINTER}
9670     * are delivered to the view under the pointer.  All other generic motion events are
9671     * delivered to the focused view.  Hover events are handled specially and are delivered
9672     * to {@link #onHoverEvent(MotionEvent)}.
9673     * </p>
9674     *
9675     * @param event The motion event to be dispatched.
9676     * @return True if the event was handled by the view, false otherwise.
9677     */
9678    public boolean dispatchGenericMotionEvent(MotionEvent event) {
9679        if (mInputEventConsistencyVerifier != null) {
9680            mInputEventConsistencyVerifier.onGenericMotionEvent(event, 0);
9681        }
9682
9683        final int source = event.getSource();
9684        if ((source & InputDevice.SOURCE_CLASS_POINTER) != 0) {
9685            final int action = event.getAction();
9686            if (action == MotionEvent.ACTION_HOVER_ENTER
9687                    || action == MotionEvent.ACTION_HOVER_MOVE
9688                    || action == MotionEvent.ACTION_HOVER_EXIT) {
9689                if (dispatchHoverEvent(event)) {
9690                    return true;
9691                }
9692            } else if (dispatchGenericPointerEvent(event)) {
9693                return true;
9694            }
9695        } else if (dispatchGenericFocusedEvent(event)) {
9696            return true;
9697        }
9698
9699        if (dispatchGenericMotionEventInternal(event)) {
9700            return true;
9701        }
9702
9703        if (mInputEventConsistencyVerifier != null) {
9704            mInputEventConsistencyVerifier.onUnhandledEvent(event, 0);
9705        }
9706        return false;
9707    }
9708
9709    private boolean dispatchGenericMotionEventInternal(MotionEvent event) {
9710        //noinspection SimplifiableIfStatement
9711        ListenerInfo li = mListenerInfo;
9712        if (li != null && li.mOnGenericMotionListener != null
9713                && (mViewFlags & ENABLED_MASK) == ENABLED
9714                && li.mOnGenericMotionListener.onGenericMotion(this, event)) {
9715            return true;
9716        }
9717
9718        if (onGenericMotionEvent(event)) {
9719            return true;
9720        }
9721
9722        final int actionButton = event.getActionButton();
9723        switch (event.getActionMasked()) {
9724            case MotionEvent.ACTION_BUTTON_PRESS:
9725                if (isContextClickable() && !mInContextButtonPress && !mHasPerformedLongPress
9726                        && (actionButton == MotionEvent.BUTTON_STYLUS_PRIMARY
9727                        || actionButton == MotionEvent.BUTTON_SECONDARY)) {
9728                    if (performContextClick()) {
9729                        mInContextButtonPress = true;
9730                        setPressed(true, event.getX(), event.getY());
9731                        removeTapCallback();
9732                        removeLongPressCallback();
9733                        return true;
9734                    }
9735                }
9736                break;
9737
9738            case MotionEvent.ACTION_BUTTON_RELEASE:
9739                if (mInContextButtonPress && (actionButton == MotionEvent.BUTTON_STYLUS_PRIMARY
9740                        || actionButton == MotionEvent.BUTTON_SECONDARY)) {
9741                    mInContextButtonPress = false;
9742                    mIgnoreNextUpEvent = true;
9743                }
9744                break;
9745        }
9746
9747        if (mInputEventConsistencyVerifier != null) {
9748            mInputEventConsistencyVerifier.onUnhandledEvent(event, 0);
9749        }
9750        return false;
9751    }
9752
9753    /**
9754     * Dispatch a hover event.
9755     * <p>
9756     * Do not call this method directly.
9757     * Call {@link #dispatchGenericMotionEvent(MotionEvent)} instead.
9758     * </p>
9759     *
9760     * @param event The motion event to be dispatched.
9761     * @return True if the event was handled by the view, false otherwise.
9762     */
9763    protected boolean dispatchHoverEvent(MotionEvent event) {
9764        ListenerInfo li = mListenerInfo;
9765        //noinspection SimplifiableIfStatement
9766        if (li != null && li.mOnHoverListener != null
9767                && (mViewFlags & ENABLED_MASK) == ENABLED
9768                && li.mOnHoverListener.onHover(this, event)) {
9769            return true;
9770        }
9771
9772        return onHoverEvent(event);
9773    }
9774
9775    /**
9776     * Returns true if the view has a child to which it has recently sent
9777     * {@link MotionEvent#ACTION_HOVER_ENTER}.  If this view is hovered and
9778     * it does not have a hovered child, then it must be the innermost hovered view.
9779     * @hide
9780     */
9781    protected boolean hasHoveredChild() {
9782        return false;
9783    }
9784
9785    /**
9786     * Dispatch a generic motion event to the view under the first pointer.
9787     * <p>
9788     * Do not call this method directly.
9789     * Call {@link #dispatchGenericMotionEvent(MotionEvent)} instead.
9790     * </p>
9791     *
9792     * @param event The motion event to be dispatched.
9793     * @return True if the event was handled by the view, false otherwise.
9794     */
9795    protected boolean dispatchGenericPointerEvent(MotionEvent event) {
9796        return false;
9797    }
9798
9799    /**
9800     * Dispatch a generic motion event to the currently focused view.
9801     * <p>
9802     * Do not call this method directly.
9803     * Call {@link #dispatchGenericMotionEvent(MotionEvent)} instead.
9804     * </p>
9805     *
9806     * @param event The motion event to be dispatched.
9807     * @return True if the event was handled by the view, false otherwise.
9808     */
9809    protected boolean dispatchGenericFocusedEvent(MotionEvent event) {
9810        return false;
9811    }
9812
9813    /**
9814     * Dispatch a pointer event.
9815     * <p>
9816     * Dispatches touch related pointer events to {@link #onTouchEvent(MotionEvent)} and all
9817     * other events to {@link #onGenericMotionEvent(MotionEvent)}.  This separation of concerns
9818     * reinforces the invariant that {@link #onTouchEvent(MotionEvent)} is really about touches
9819     * and should not be expected to handle other pointing device features.
9820     * </p>
9821     *
9822     * @param event The motion event to be dispatched.
9823     * @return True if the event was handled by the view, false otherwise.
9824     * @hide
9825     */
9826    public final boolean dispatchPointerEvent(MotionEvent event) {
9827        if (event.isTouchEvent()) {
9828            return dispatchTouchEvent(event);
9829        } else {
9830            return dispatchGenericMotionEvent(event);
9831        }
9832    }
9833
9834    /**
9835     * Called when the window containing this view gains or loses window focus.
9836     * ViewGroups should override to route to their children.
9837     *
9838     * @param hasFocus True if the window containing this view now has focus,
9839     *        false otherwise.
9840     */
9841    public void dispatchWindowFocusChanged(boolean hasFocus) {
9842        onWindowFocusChanged(hasFocus);
9843    }
9844
9845    /**
9846     * Called when the window containing this view gains or loses focus.  Note
9847     * that this is separate from view focus: to receive key events, both
9848     * your view and its window must have focus.  If a window is displayed
9849     * on top of yours that takes input focus, then your own window will lose
9850     * focus but the view focus will remain unchanged.
9851     *
9852     * @param hasWindowFocus True if the window containing this view now has
9853     *        focus, false otherwise.
9854     */
9855    public void onWindowFocusChanged(boolean hasWindowFocus) {
9856        InputMethodManager imm = InputMethodManager.peekInstance();
9857        if (!hasWindowFocus) {
9858            if (isPressed()) {
9859                setPressed(false);
9860            }
9861            if (imm != null && (mPrivateFlags & PFLAG_FOCUSED) != 0) {
9862                imm.focusOut(this);
9863            }
9864            removeLongPressCallback();
9865            removeTapCallback();
9866            onFocusLost();
9867        } else if (imm != null && (mPrivateFlags & PFLAG_FOCUSED) != 0) {
9868            imm.focusIn(this);
9869        }
9870        refreshDrawableState();
9871    }
9872
9873    /**
9874     * Returns true if this view is in a window that currently has window focus.
9875     * Note that this is not the same as the view itself having focus.
9876     *
9877     * @return True if this view is in a window that currently has window focus.
9878     */
9879    public boolean hasWindowFocus() {
9880        return mAttachInfo != null && mAttachInfo.mHasWindowFocus;
9881    }
9882
9883    /**
9884     * Dispatch a view visibility change down the view hierarchy.
9885     * ViewGroups should override to route to their children.
9886     * @param changedView The view whose visibility changed. Could be 'this' or
9887     * an ancestor view.
9888     * @param visibility The new visibility of changedView: {@link #VISIBLE},
9889     * {@link #INVISIBLE} or {@link #GONE}.
9890     */
9891    protected void dispatchVisibilityChanged(@NonNull View changedView,
9892            @Visibility int visibility) {
9893        onVisibilityChanged(changedView, visibility);
9894    }
9895
9896    /**
9897     * Called when the visibility of the view or an ancestor of the view has
9898     * changed.
9899     *
9900     * @param changedView The view whose visibility changed. May be
9901     *                    {@code this} or an ancestor view.
9902     * @param visibility The new visibility, one of {@link #VISIBLE},
9903     *                   {@link #INVISIBLE} or {@link #GONE}.
9904     */
9905    protected void onVisibilityChanged(@NonNull View changedView, @Visibility int visibility) {
9906        final boolean visible = visibility == VISIBLE && getVisibility() == VISIBLE;
9907        if (visible && mAttachInfo != null) {
9908            initialAwakenScrollBars();
9909        }
9910
9911        final Drawable dr = mBackground;
9912        if (dr != null && visible != dr.isVisible()) {
9913            dr.setVisible(visible, false);
9914        }
9915        final Drawable fg = mForegroundInfo != null ? mForegroundInfo.mDrawable : null;
9916        if (fg != null && visible != fg.isVisible()) {
9917            fg.setVisible(visible, false);
9918        }
9919    }
9920
9921    /**
9922     * Dispatch a hint about whether this view is displayed. For instance, when
9923     * a View moves out of the screen, it might receives a display hint indicating
9924     * the view is not displayed. Applications should not <em>rely</em> on this hint
9925     * as there is no guarantee that they will receive one.
9926     *
9927     * @param hint A hint about whether or not this view is displayed:
9928     * {@link #VISIBLE} or {@link #INVISIBLE}.
9929     */
9930    public void dispatchDisplayHint(@Visibility int hint) {
9931        onDisplayHint(hint);
9932    }
9933
9934    /**
9935     * Gives this view a hint about whether is displayed or not. For instance, when
9936     * a View moves out of the screen, it might receives a display hint indicating
9937     * the view is not displayed. Applications should not <em>rely</em> on this hint
9938     * as there is no guarantee that they will receive one.
9939     *
9940     * @param hint A hint about whether or not this view is displayed:
9941     * {@link #VISIBLE} or {@link #INVISIBLE}.
9942     */
9943    protected void onDisplayHint(@Visibility int hint) {
9944    }
9945
9946    /**
9947     * Dispatch a window visibility change down the view hierarchy.
9948     * ViewGroups should override to route to their children.
9949     *
9950     * @param visibility The new visibility of the window.
9951     *
9952     * @see #onWindowVisibilityChanged(int)
9953     */
9954    public void dispatchWindowVisibilityChanged(@Visibility int visibility) {
9955        onWindowVisibilityChanged(visibility);
9956    }
9957
9958    /**
9959     * Called when the window containing has change its visibility
9960     * (between {@link #GONE}, {@link #INVISIBLE}, and {@link #VISIBLE}).  Note
9961     * that this tells you whether or not your window is being made visible
9962     * to the window manager; this does <em>not</em> tell you whether or not
9963     * your window is obscured by other windows on the screen, even if it
9964     * is itself visible.
9965     *
9966     * @param visibility The new visibility of the window.
9967     */
9968    protected void onWindowVisibilityChanged(@Visibility int visibility) {
9969        if (visibility == VISIBLE) {
9970            initialAwakenScrollBars();
9971        }
9972    }
9973
9974    /**
9975     * Returns the current visibility of the window this view is attached to
9976     * (either {@link #GONE}, {@link #INVISIBLE}, or {@link #VISIBLE}).
9977     *
9978     * @return Returns the current visibility of the view's window.
9979     */
9980    @Visibility
9981    public int getWindowVisibility() {
9982        return mAttachInfo != null ? mAttachInfo.mWindowVisibility : GONE;
9983    }
9984
9985    /**
9986     * Retrieve the overall visible display size in which the window this view is
9987     * attached to has been positioned in.  This takes into account screen
9988     * decorations above the window, for both cases where the window itself
9989     * is being position inside of them or the window is being placed under
9990     * then and covered insets are used for the window to position its content
9991     * inside.  In effect, this tells you the available area where content can
9992     * be placed and remain visible to users.
9993     *
9994     * <p>This function requires an IPC back to the window manager to retrieve
9995     * the requested information, so should not be used in performance critical
9996     * code like drawing.
9997     *
9998     * @param outRect Filled in with the visible display frame.  If the view
9999     * is not attached to a window, this is simply the raw display size.
10000     */
10001    public void getWindowVisibleDisplayFrame(Rect outRect) {
10002        if (mAttachInfo != null) {
10003            try {
10004                mAttachInfo.mSession.getDisplayFrame(mAttachInfo.mWindow, outRect);
10005            } catch (RemoteException e) {
10006                return;
10007            }
10008            // XXX This is really broken, and probably all needs to be done
10009            // in the window manager, and we need to know more about whether
10010            // we want the area behind or in front of the IME.
10011            final Rect insets = mAttachInfo.mVisibleInsets;
10012            outRect.left += insets.left;
10013            outRect.top += insets.top;
10014            outRect.right -= insets.right;
10015            outRect.bottom -= insets.bottom;
10016            return;
10017        }
10018        // The view is not attached to a display so we don't have a context.
10019        // Make a best guess about the display size.
10020        Display d = DisplayManagerGlobal.getInstance().getRealDisplay(Display.DEFAULT_DISPLAY);
10021        d.getRectSize(outRect);
10022    }
10023
10024    /**
10025     * Dispatch a notification about a resource configuration change down
10026     * the view hierarchy.
10027     * ViewGroups should override to route to their children.
10028     *
10029     * @param newConfig The new resource configuration.
10030     *
10031     * @see #onConfigurationChanged(android.content.res.Configuration)
10032     */
10033    public void dispatchConfigurationChanged(Configuration newConfig) {
10034        onConfigurationChanged(newConfig);
10035    }
10036
10037    /**
10038     * Called when the current configuration of the resources being used
10039     * by the application have changed.  You can use this to decide when
10040     * to reload resources that can changed based on orientation and other
10041     * configuration characteristics.  You only need to use this if you are
10042     * not relying on the normal {@link android.app.Activity} mechanism of
10043     * recreating the activity instance upon a configuration change.
10044     *
10045     * @param newConfig The new resource configuration.
10046     */
10047    protected void onConfigurationChanged(Configuration newConfig) {
10048    }
10049
10050    /**
10051     * Private function to aggregate all per-view attributes in to the view
10052     * root.
10053     */
10054    void dispatchCollectViewAttributes(AttachInfo attachInfo, int visibility) {
10055        performCollectViewAttributes(attachInfo, visibility);
10056    }
10057
10058    void performCollectViewAttributes(AttachInfo attachInfo, int visibility) {
10059        if ((visibility & VISIBILITY_MASK) == VISIBLE) {
10060            if ((mViewFlags & KEEP_SCREEN_ON) == KEEP_SCREEN_ON) {
10061                attachInfo.mKeepScreenOn = true;
10062            }
10063            attachInfo.mSystemUiVisibility |= mSystemUiVisibility;
10064            ListenerInfo li = mListenerInfo;
10065            if (li != null && li.mOnSystemUiVisibilityChangeListener != null) {
10066                attachInfo.mHasSystemUiListeners = true;
10067            }
10068        }
10069    }
10070
10071    void needGlobalAttributesUpdate(boolean force) {
10072        final AttachInfo ai = mAttachInfo;
10073        if (ai != null && !ai.mRecomputeGlobalAttributes) {
10074            if (force || ai.mKeepScreenOn || (ai.mSystemUiVisibility != 0)
10075                    || ai.mHasSystemUiListeners) {
10076                ai.mRecomputeGlobalAttributes = true;
10077            }
10078        }
10079    }
10080
10081    /**
10082     * Returns whether the device is currently in touch mode.  Touch mode is entered
10083     * once the user begins interacting with the device by touch, and affects various
10084     * things like whether focus is always visible to the user.
10085     *
10086     * @return Whether the device is in touch mode.
10087     */
10088    @ViewDebug.ExportedProperty
10089    public boolean isInTouchMode() {
10090        if (mAttachInfo != null) {
10091            return mAttachInfo.mInTouchMode;
10092        } else {
10093            return ViewRootImpl.isInTouchMode();
10094        }
10095    }
10096
10097    /**
10098     * Returns the context the view is running in, through which it can
10099     * access the current theme, resources, etc.
10100     *
10101     * @return The view's Context.
10102     */
10103    @ViewDebug.CapturedViewProperty
10104    public final Context getContext() {
10105        return mContext;
10106    }
10107
10108    /**
10109     * Handle a key event before it is processed by any input method
10110     * associated with the view hierarchy.  This can be used to intercept
10111     * key events in special situations before the IME consumes them; a
10112     * typical example would be handling the BACK key to update the application's
10113     * UI instead of allowing the IME to see it and close itself.
10114     *
10115     * @param keyCode The value in event.getKeyCode().
10116     * @param event Description of the key event.
10117     * @return If you handled the event, return true. If you want to allow the
10118     *         event to be handled by the next receiver, return false.
10119     */
10120    public boolean onKeyPreIme(int keyCode, KeyEvent event) {
10121        return false;
10122    }
10123
10124    /**
10125     * Default implementation of {@link KeyEvent.Callback#onKeyDown(int, KeyEvent)
10126     * KeyEvent.Callback.onKeyDown()}: perform press of the view
10127     * when {@link KeyEvent#KEYCODE_DPAD_CENTER} or {@link KeyEvent#KEYCODE_ENTER}
10128     * is released, if the view is enabled and clickable.
10129     * <p>
10130     * Key presses in software keyboards will generally NOT trigger this
10131     * listener, although some may elect to do so in some situations. Do not
10132     * rely on this to catch software key presses.
10133     *
10134     * @param keyCode a key code that represents the button pressed, from
10135     *                {@link android.view.KeyEvent}
10136     * @param event the KeyEvent object that defines the button action
10137     */
10138    public boolean onKeyDown(int keyCode, KeyEvent event) {
10139        if (KeyEvent.isConfirmKey(keyCode)) {
10140            if ((mViewFlags & ENABLED_MASK) == DISABLED) {
10141                return true;
10142            }
10143
10144            // Long clickable items don't necessarily have to be clickable.
10145            if (((mViewFlags & CLICKABLE) == CLICKABLE
10146                    || (mViewFlags & LONG_CLICKABLE) == LONG_CLICKABLE)
10147                    && (event.getRepeatCount() == 0)) {
10148                // For the purposes of menu anchoring and drawable hotspots,
10149                // key events are considered to be at the center of the view.
10150                final float x = getWidth() / 2f;
10151                final float y = getHeight() / 2f;
10152                setPressed(true, x, y);
10153                checkForLongClick(0, x, y);
10154                return true;
10155            }
10156        }
10157
10158        return false;
10159    }
10160
10161    /**
10162     * Default implementation of {@link KeyEvent.Callback#onKeyLongPress(int, KeyEvent)
10163     * KeyEvent.Callback.onKeyLongPress()}: always returns false (doesn't handle
10164     * the event).
10165     * <p>Key presses in software keyboards will generally NOT trigger this listener,
10166     * although some may elect to do so in some situations. Do not rely on this to
10167     * catch software key presses.
10168     */
10169    public boolean onKeyLongPress(int keyCode, KeyEvent event) {
10170        return false;
10171    }
10172
10173    /**
10174     * Default implementation of {@link KeyEvent.Callback#onKeyUp(int, KeyEvent)
10175     * KeyEvent.Callback.onKeyUp()}: perform clicking of the view
10176     * when {@link KeyEvent#KEYCODE_DPAD_CENTER}, {@link KeyEvent#KEYCODE_ENTER}
10177     * or {@link KeyEvent#KEYCODE_SPACE} is released.
10178     * <p>Key presses in software keyboards will generally NOT trigger this listener,
10179     * although some may elect to do so in some situations. Do not rely on this to
10180     * catch software key presses.
10181     *
10182     * @param keyCode A key code that represents the button pressed, from
10183     *                {@link android.view.KeyEvent}.
10184     * @param event   The KeyEvent object that defines the button action.
10185     */
10186    public boolean onKeyUp(int keyCode, KeyEvent event) {
10187        if (KeyEvent.isConfirmKey(keyCode)) {
10188            if ((mViewFlags & ENABLED_MASK) == DISABLED) {
10189                return true;
10190            }
10191            if ((mViewFlags & CLICKABLE) == CLICKABLE && isPressed()) {
10192                setPressed(false);
10193
10194                if (!mHasPerformedLongPress) {
10195                    // This is a tap, so remove the longpress check
10196                    removeLongPressCallback();
10197                    return performClick();
10198                }
10199            }
10200        }
10201        return false;
10202    }
10203
10204    /**
10205     * Default implementation of {@link KeyEvent.Callback#onKeyMultiple(int, int, KeyEvent)
10206     * KeyEvent.Callback.onKeyMultiple()}: always returns false (doesn't handle
10207     * the event).
10208     * <p>Key presses in software keyboards will generally NOT trigger this listener,
10209     * although some may elect to do so in some situations. Do not rely on this to
10210     * catch software key presses.
10211     *
10212     * @param keyCode     A key code that represents the button pressed, from
10213     *                    {@link android.view.KeyEvent}.
10214     * @param repeatCount The number of times the action was made.
10215     * @param event       The KeyEvent object that defines the button action.
10216     */
10217    public boolean onKeyMultiple(int keyCode, int repeatCount, KeyEvent event) {
10218        return false;
10219    }
10220
10221    /**
10222     * Called on the focused view when a key shortcut event is not handled.
10223     * Override this method to implement local key shortcuts for the View.
10224     * Key shortcuts can also be implemented by setting the
10225     * {@link MenuItem#setShortcut(char, char) shortcut} property of menu items.
10226     *
10227     * @param keyCode The value in event.getKeyCode().
10228     * @param event Description of the key event.
10229     * @return If you handled the event, return true. If you want to allow the
10230     *         event to be handled by the next receiver, return false.
10231     */
10232    public boolean onKeyShortcut(int keyCode, KeyEvent event) {
10233        return false;
10234    }
10235
10236    /**
10237     * Check whether the called view is a text editor, in which case it
10238     * would make sense to automatically display a soft input window for
10239     * it.  Subclasses should override this if they implement
10240     * {@link #onCreateInputConnection(EditorInfo)} to return true if
10241     * a call on that method would return a non-null InputConnection, and
10242     * they are really a first-class editor that the user would normally
10243     * start typing on when the go into a window containing your view.
10244     *
10245     * <p>The default implementation always returns false.  This does
10246     * <em>not</em> mean that its {@link #onCreateInputConnection(EditorInfo)}
10247     * will not be called or the user can not otherwise perform edits on your
10248     * view; it is just a hint to the system that this is not the primary
10249     * purpose of this view.
10250     *
10251     * @return Returns true if this view is a text editor, else false.
10252     */
10253    public boolean onCheckIsTextEditor() {
10254        return false;
10255    }
10256
10257    /**
10258     * Create a new InputConnection for an InputMethod to interact
10259     * with the view.  The default implementation returns null, since it doesn't
10260     * support input methods.  You can override this to implement such support.
10261     * This is only needed for views that take focus and text input.
10262     *
10263     * <p>When implementing this, you probably also want to implement
10264     * {@link #onCheckIsTextEditor()} to indicate you will return a
10265     * non-null InputConnection.</p>
10266     *
10267     * <p>Also, take good care to fill in the {@link android.view.inputmethod.EditorInfo}
10268     * object correctly and in its entirety, so that the connected IME can rely
10269     * on its values. For example, {@link android.view.inputmethod.EditorInfo#initialSelStart}
10270     * and  {@link android.view.inputmethod.EditorInfo#initialSelEnd} members
10271     * must be filled in with the correct cursor position for IMEs to work correctly
10272     * with your application.</p>
10273     *
10274     * @param outAttrs Fill in with attribute information about the connection.
10275     */
10276    public InputConnection onCreateInputConnection(EditorInfo outAttrs) {
10277        return null;
10278    }
10279
10280    /**
10281     * Called by the {@link android.view.inputmethod.InputMethodManager}
10282     * when a view who is not the current
10283     * input connection target is trying to make a call on the manager.  The
10284     * default implementation returns false; you can override this to return
10285     * true for certain views if you are performing InputConnection proxying
10286     * to them.
10287     * @param view The View that is making the InputMethodManager call.
10288     * @return Return true to allow the call, false to reject.
10289     */
10290    public boolean checkInputConnectionProxy(View view) {
10291        return false;
10292    }
10293
10294    /**
10295     * Show the context menu for this view. It is not safe to hold on to the
10296     * menu after returning from this method.
10297     *
10298     * You should normally not overload this method. Overload
10299     * {@link #onCreateContextMenu(ContextMenu)} or define an
10300     * {@link OnCreateContextMenuListener} to add items to the context menu.
10301     *
10302     * @param menu The context menu to populate
10303     */
10304    public void createContextMenu(ContextMenu menu) {
10305        ContextMenuInfo menuInfo = getContextMenuInfo();
10306
10307        // Sets the current menu info so all items added to menu will have
10308        // my extra info set.
10309        ((MenuBuilder)menu).setCurrentMenuInfo(menuInfo);
10310
10311        onCreateContextMenu(menu);
10312        ListenerInfo li = mListenerInfo;
10313        if (li != null && li.mOnCreateContextMenuListener != null) {
10314            li.mOnCreateContextMenuListener.onCreateContextMenu(menu, this, menuInfo);
10315        }
10316
10317        // Clear the extra information so subsequent items that aren't mine don't
10318        // have my extra info.
10319        ((MenuBuilder)menu).setCurrentMenuInfo(null);
10320
10321        if (mParent != null) {
10322            mParent.createContextMenu(menu);
10323        }
10324    }
10325
10326    /**
10327     * Views should implement this if they have extra information to associate
10328     * with the context menu. The return result is supplied as a parameter to
10329     * the {@link OnCreateContextMenuListener#onCreateContextMenu(ContextMenu, View, ContextMenuInfo)}
10330     * callback.
10331     *
10332     * @return Extra information about the item for which the context menu
10333     *         should be shown. This information will vary across different
10334     *         subclasses of View.
10335     */
10336    protected ContextMenuInfo getContextMenuInfo() {
10337        return null;
10338    }
10339
10340    /**
10341     * Views should implement this if the view itself is going to add items to
10342     * the context menu.
10343     *
10344     * @param menu the context menu to populate
10345     */
10346    protected void onCreateContextMenu(ContextMenu menu) {
10347    }
10348
10349    /**
10350     * Implement this method to handle trackball motion events.  The
10351     * <em>relative</em> movement of the trackball since the last event
10352     * can be retrieve with {@link MotionEvent#getX MotionEvent.getX()} and
10353     * {@link MotionEvent#getY MotionEvent.getY()}.  These are normalized so
10354     * that a movement of 1 corresponds to the user pressing one DPAD key (so
10355     * they will often be fractional values, representing the more fine-grained
10356     * movement information available from a trackball).
10357     *
10358     * @param event The motion event.
10359     * @return True if the event was handled, false otherwise.
10360     */
10361    public boolean onTrackballEvent(MotionEvent event) {
10362        return false;
10363    }
10364
10365    /**
10366     * Implement this method to handle generic motion events.
10367     * <p>
10368     * Generic motion events describe joystick movements, mouse hovers, track pad
10369     * touches, scroll wheel movements and other input events.  The
10370     * {@link MotionEvent#getSource() source} of the motion event specifies
10371     * the class of input that was received.  Implementations of this method
10372     * must examine the bits in the source before processing the event.
10373     * The following code example shows how this is done.
10374     * </p><p>
10375     * Generic motion events with source class {@link InputDevice#SOURCE_CLASS_POINTER}
10376     * are delivered to the view under the pointer.  All other generic motion events are
10377     * delivered to the focused view.
10378     * </p>
10379     * <pre> public boolean onGenericMotionEvent(MotionEvent event) {
10380     *     if (event.isFromSource(InputDevice.SOURCE_CLASS_JOYSTICK)) {
10381     *         if (event.getAction() == MotionEvent.ACTION_MOVE) {
10382     *             // process the joystick movement...
10383     *             return true;
10384     *         }
10385     *     }
10386     *     if (event.isFromSource(InputDevice.SOURCE_CLASS_POINTER)) {
10387     *         switch (event.getAction()) {
10388     *             case MotionEvent.ACTION_HOVER_MOVE:
10389     *                 // process the mouse hover movement...
10390     *                 return true;
10391     *             case MotionEvent.ACTION_SCROLL:
10392     *                 // process the scroll wheel movement...
10393     *                 return true;
10394     *         }
10395     *     }
10396     *     return super.onGenericMotionEvent(event);
10397     * }</pre>
10398     *
10399     * @param event The generic motion event being processed.
10400     * @return True if the event was handled, false otherwise.
10401     */
10402    public boolean onGenericMotionEvent(MotionEvent event) {
10403        return false;
10404    }
10405
10406    /**
10407     * Implement this method to handle hover events.
10408     * <p>
10409     * This method is called whenever a pointer is hovering into, over, or out of the
10410     * bounds of a view and the view is not currently being touched.
10411     * Hover events are represented as pointer events with action
10412     * {@link MotionEvent#ACTION_HOVER_ENTER}, {@link MotionEvent#ACTION_HOVER_MOVE},
10413     * or {@link MotionEvent#ACTION_HOVER_EXIT}.
10414     * </p>
10415     * <ul>
10416     * <li>The view receives a hover event with action {@link MotionEvent#ACTION_HOVER_ENTER}
10417     * when the pointer enters the bounds of the view.</li>
10418     * <li>The view receives a hover event with action {@link MotionEvent#ACTION_HOVER_MOVE}
10419     * when the pointer has already entered the bounds of the view and has moved.</li>
10420     * <li>The view receives a hover event with action {@link MotionEvent#ACTION_HOVER_EXIT}
10421     * when the pointer has exited the bounds of the view or when the pointer is
10422     * about to go down due to a button click, tap, or similar user action that
10423     * causes the view to be touched.</li>
10424     * </ul>
10425     * <p>
10426     * The view should implement this method to return true to indicate that it is
10427     * handling the hover event, such as by changing its drawable state.
10428     * </p><p>
10429     * The default implementation calls {@link #setHovered} to update the hovered state
10430     * of the view when a hover enter or hover exit event is received, if the view
10431     * is enabled and is clickable.  The default implementation also sends hover
10432     * accessibility events.
10433     * </p>
10434     *
10435     * @param event The motion event that describes the hover.
10436     * @return True if the view handled the hover event.
10437     *
10438     * @see #isHovered
10439     * @see #setHovered
10440     * @see #onHoverChanged
10441     */
10442    public boolean onHoverEvent(MotionEvent event) {
10443        // The root view may receive hover (or touch) events that are outside the bounds of
10444        // the window.  This code ensures that we only send accessibility events for
10445        // hovers that are actually within the bounds of the root view.
10446        final int action = event.getActionMasked();
10447        if (!mSendingHoverAccessibilityEvents) {
10448            if ((action == MotionEvent.ACTION_HOVER_ENTER
10449                    || action == MotionEvent.ACTION_HOVER_MOVE)
10450                    && !hasHoveredChild()
10451                    && pointInView(event.getX(), event.getY())) {
10452                sendAccessibilityHoverEvent(AccessibilityEvent.TYPE_VIEW_HOVER_ENTER);
10453                mSendingHoverAccessibilityEvents = true;
10454            }
10455        } else {
10456            if (action == MotionEvent.ACTION_HOVER_EXIT
10457                    || (action == MotionEvent.ACTION_MOVE
10458                            && !pointInView(event.getX(), event.getY()))) {
10459                mSendingHoverAccessibilityEvents = false;
10460                sendAccessibilityHoverEvent(AccessibilityEvent.TYPE_VIEW_HOVER_EXIT);
10461            }
10462        }
10463
10464        if (isHoverable()) {
10465            switch (action) {
10466                case MotionEvent.ACTION_HOVER_ENTER:
10467                    setHovered(true);
10468                    break;
10469                case MotionEvent.ACTION_HOVER_EXIT:
10470                    setHovered(false);
10471                    break;
10472            }
10473
10474            // Dispatch the event to onGenericMotionEvent before returning true.
10475            // This is to provide compatibility with existing applications that
10476            // handled HOVER_MOVE events in onGenericMotionEvent and that would
10477            // break because of the new default handling for hoverable views
10478            // in onHoverEvent.
10479            // Note that onGenericMotionEvent will be called by default when
10480            // onHoverEvent returns false (refer to dispatchGenericMotionEvent).
10481            dispatchGenericMotionEventInternal(event);
10482            // The event was already handled by calling setHovered(), so always
10483            // return true.
10484            return true;
10485        }
10486
10487        return false;
10488    }
10489
10490    /**
10491     * Returns true if the view should handle {@link #onHoverEvent}
10492     * by calling {@link #setHovered} to change its hovered state.
10493     *
10494     * @return True if the view is hoverable.
10495     */
10496    private boolean isHoverable() {
10497        final int viewFlags = mViewFlags;
10498        if ((viewFlags & ENABLED_MASK) == DISABLED) {
10499            return false;
10500        }
10501
10502        return (viewFlags & CLICKABLE) == CLICKABLE
10503                || (viewFlags & LONG_CLICKABLE) == LONG_CLICKABLE
10504                || (viewFlags & CONTEXT_CLICKABLE) == CONTEXT_CLICKABLE;
10505    }
10506
10507    /**
10508     * Returns true if the view is currently hovered.
10509     *
10510     * @return True if the view is currently hovered.
10511     *
10512     * @see #setHovered
10513     * @see #onHoverChanged
10514     */
10515    @ViewDebug.ExportedProperty
10516    public boolean isHovered() {
10517        return (mPrivateFlags & PFLAG_HOVERED) != 0;
10518    }
10519
10520    /**
10521     * Sets whether the view is currently hovered.
10522     * <p>
10523     * Calling this method also changes the drawable state of the view.  This
10524     * enables the view to react to hover by using different drawable resources
10525     * to change its appearance.
10526     * </p><p>
10527     * The {@link #onHoverChanged} method is called when the hovered state changes.
10528     * </p>
10529     *
10530     * @param hovered True if the view is hovered.
10531     *
10532     * @see #isHovered
10533     * @see #onHoverChanged
10534     */
10535    public void setHovered(boolean hovered) {
10536        if (hovered) {
10537            if ((mPrivateFlags & PFLAG_HOVERED) == 0) {
10538                mPrivateFlags |= PFLAG_HOVERED;
10539                refreshDrawableState();
10540                onHoverChanged(true);
10541            }
10542        } else {
10543            if ((mPrivateFlags & PFLAG_HOVERED) != 0) {
10544                mPrivateFlags &= ~PFLAG_HOVERED;
10545                refreshDrawableState();
10546                onHoverChanged(false);
10547            }
10548        }
10549    }
10550
10551    /**
10552     * Implement this method to handle hover state changes.
10553     * <p>
10554     * This method is called whenever the hover state changes as a result of a
10555     * call to {@link #setHovered}.
10556     * </p>
10557     *
10558     * @param hovered The current hover state, as returned by {@link #isHovered}.
10559     *
10560     * @see #isHovered
10561     * @see #setHovered
10562     */
10563    public void onHoverChanged(boolean hovered) {
10564    }
10565
10566    /**
10567     * Implement this method to handle touch screen motion events.
10568     * <p>
10569     * If this method is used to detect click actions, it is recommended that
10570     * the actions be performed by implementing and calling
10571     * {@link #performClick()}. This will ensure consistent system behavior,
10572     * including:
10573     * <ul>
10574     * <li>obeying click sound preferences
10575     * <li>dispatching OnClickListener calls
10576     * <li>handling {@link AccessibilityNodeInfo#ACTION_CLICK ACTION_CLICK} when
10577     * accessibility features are enabled
10578     * </ul>
10579     *
10580     * @param event The motion event.
10581     * @return True if the event was handled, false otherwise.
10582     */
10583    public boolean onTouchEvent(MotionEvent event) {
10584        final float x = event.getX();
10585        final float y = event.getY();
10586        final int viewFlags = mViewFlags;
10587        final int action = event.getAction();
10588
10589        if ((viewFlags & ENABLED_MASK) == DISABLED) {
10590            if (action == MotionEvent.ACTION_UP && (mPrivateFlags & PFLAG_PRESSED) != 0) {
10591                setPressed(false);
10592            }
10593            // A disabled view that is clickable still consumes the touch
10594            // events, it just doesn't respond to them.
10595            return (((viewFlags & CLICKABLE) == CLICKABLE
10596                    || (viewFlags & LONG_CLICKABLE) == LONG_CLICKABLE)
10597                    || (viewFlags & CONTEXT_CLICKABLE) == CONTEXT_CLICKABLE);
10598        }
10599
10600        if (mTouchDelegate != null) {
10601            if (mTouchDelegate.onTouchEvent(event)) {
10602                return true;
10603            }
10604        }
10605
10606        if (((viewFlags & CLICKABLE) == CLICKABLE ||
10607                (viewFlags & LONG_CLICKABLE) == LONG_CLICKABLE) ||
10608                (viewFlags & CONTEXT_CLICKABLE) == CONTEXT_CLICKABLE) {
10609            switch (action) {
10610                case MotionEvent.ACTION_UP:
10611                    boolean prepressed = (mPrivateFlags & PFLAG_PREPRESSED) != 0;
10612                    if ((mPrivateFlags & PFLAG_PRESSED) != 0 || prepressed) {
10613                        // take focus if we don't have it already and we should in
10614                        // touch mode.
10615                        boolean focusTaken = false;
10616                        if (isFocusable() && isFocusableInTouchMode() && !isFocused()) {
10617                            focusTaken = requestFocus();
10618                        }
10619
10620                        if (prepressed) {
10621                            // The button is being released before we actually
10622                            // showed it as pressed.  Make it show the pressed
10623                            // state now (before scheduling the click) to ensure
10624                            // the user sees it.
10625                            setPressed(true, x, y);
10626                       }
10627
10628                        if (!mHasPerformedLongPress && !mIgnoreNextUpEvent) {
10629                            // This is a tap, so remove the longpress check
10630                            removeLongPressCallback();
10631
10632                            // Only perform take click actions if we were in the pressed state
10633                            if (!focusTaken) {
10634                                // Use a Runnable and post this rather than calling
10635                                // performClick directly. This lets other visual state
10636                                // of the view update before click actions start.
10637                                if (mPerformClick == null) {
10638                                    mPerformClick = new PerformClick();
10639                                }
10640                                if (!post(mPerformClick)) {
10641                                    performClick();
10642                                }
10643                            }
10644                        }
10645
10646                        if (mUnsetPressedState == null) {
10647                            mUnsetPressedState = new UnsetPressedState();
10648                        }
10649
10650                        if (prepressed) {
10651                            postDelayed(mUnsetPressedState,
10652                                    ViewConfiguration.getPressedStateDuration());
10653                        } else if (!post(mUnsetPressedState)) {
10654                            // If the post failed, unpress right now
10655                            mUnsetPressedState.run();
10656                        }
10657
10658                        removeTapCallback();
10659                    }
10660                    mIgnoreNextUpEvent = false;
10661                    break;
10662
10663                case MotionEvent.ACTION_DOWN:
10664                    mHasPerformedLongPress = false;
10665
10666                    if (performButtonActionOnTouchDown(event)) {
10667                        break;
10668                    }
10669
10670                    // Walk up the hierarchy to determine if we're inside a scrolling container.
10671                    boolean isInScrollingContainer = isInScrollingContainer();
10672
10673                    // For views inside a scrolling container, delay the pressed feedback for
10674                    // a short period in case this is a scroll.
10675                    if (isInScrollingContainer) {
10676                        mPrivateFlags |= PFLAG_PREPRESSED;
10677                        if (mPendingCheckForTap == null) {
10678                            mPendingCheckForTap = new CheckForTap();
10679                        }
10680                        mPendingCheckForTap.x = event.getX();
10681                        mPendingCheckForTap.y = event.getY();
10682                        postDelayed(mPendingCheckForTap, ViewConfiguration.getTapTimeout());
10683                    } else {
10684                        // Not inside a scrolling container, so show the feedback right away
10685                        setPressed(true, x, y);
10686                        checkForLongClick(0, x, y);
10687                    }
10688                    break;
10689
10690                case MotionEvent.ACTION_CANCEL:
10691                    setPressed(false);
10692                    removeTapCallback();
10693                    removeLongPressCallback();
10694                    mInContextButtonPress = false;
10695                    mHasPerformedLongPress = false;
10696                    mIgnoreNextUpEvent = false;
10697                    break;
10698
10699                case MotionEvent.ACTION_MOVE:
10700                    drawableHotspotChanged(x, y);
10701
10702                    // Be lenient about moving outside of buttons
10703                    if (!pointInView(x, y, mTouchSlop)) {
10704                        // Outside button
10705                        removeTapCallback();
10706                        if ((mPrivateFlags & PFLAG_PRESSED) != 0) {
10707                            // Remove any future long press/tap checks
10708                            removeLongPressCallback();
10709
10710                            setPressed(false);
10711                        }
10712                    }
10713                    break;
10714            }
10715
10716            return true;
10717        }
10718
10719        return false;
10720    }
10721
10722    /**
10723     * @hide
10724     */
10725    public boolean isInScrollingContainer() {
10726        ViewParent p = getParent();
10727        while (p != null && p instanceof ViewGroup) {
10728            if (((ViewGroup) p).shouldDelayChildPressedState()) {
10729                return true;
10730            }
10731            p = p.getParent();
10732        }
10733        return false;
10734    }
10735
10736    /**
10737     * Remove the longpress detection timer.
10738     */
10739    private void removeLongPressCallback() {
10740        if (mPendingCheckForLongPress != null) {
10741          removeCallbacks(mPendingCheckForLongPress);
10742        }
10743    }
10744
10745    /**
10746     * Remove the pending click action
10747     */
10748    private void removePerformClickCallback() {
10749        if (mPerformClick != null) {
10750            removeCallbacks(mPerformClick);
10751        }
10752    }
10753
10754    /**
10755     * Remove the prepress detection timer.
10756     */
10757    private void removeUnsetPressCallback() {
10758        if ((mPrivateFlags & PFLAG_PRESSED) != 0 && mUnsetPressedState != null) {
10759            setPressed(false);
10760            removeCallbacks(mUnsetPressedState);
10761        }
10762    }
10763
10764    /**
10765     * Remove the tap detection timer.
10766     */
10767    private void removeTapCallback() {
10768        if (mPendingCheckForTap != null) {
10769            mPrivateFlags &= ~PFLAG_PREPRESSED;
10770            removeCallbacks(mPendingCheckForTap);
10771        }
10772    }
10773
10774    /**
10775     * Cancels a pending long press.  Your subclass can use this if you
10776     * want the context menu to come up if the user presses and holds
10777     * at the same place, but you don't want it to come up if they press
10778     * and then move around enough to cause scrolling.
10779     */
10780    public void cancelLongPress() {
10781        removeLongPressCallback();
10782
10783        /*
10784         * The prepressed state handled by the tap callback is a display
10785         * construct, but the tap callback will post a long press callback
10786         * less its own timeout. Remove it here.
10787         */
10788        removeTapCallback();
10789    }
10790
10791    /**
10792     * Remove the pending callback for sending a
10793     * {@link AccessibilityEvent#TYPE_VIEW_SCROLLED} accessibility event.
10794     */
10795    private void removeSendViewScrolledAccessibilityEventCallback() {
10796        if (mSendViewScrolledAccessibilityEvent != null) {
10797            removeCallbacks(mSendViewScrolledAccessibilityEvent);
10798            mSendViewScrolledAccessibilityEvent.mIsPending = false;
10799        }
10800    }
10801
10802    /**
10803     * Sets the TouchDelegate for this View.
10804     */
10805    public void setTouchDelegate(TouchDelegate delegate) {
10806        mTouchDelegate = delegate;
10807    }
10808
10809    /**
10810     * Gets the TouchDelegate for this View.
10811     */
10812    public TouchDelegate getTouchDelegate() {
10813        return mTouchDelegate;
10814    }
10815
10816    /**
10817     * Request unbuffered dispatch of the given stream of MotionEvents to this View.
10818     *
10819     * Until this View receives a corresponding {@link MotionEvent#ACTION_UP}, ask that the input
10820     * system not batch {@link MotionEvent}s but instead deliver them as soon as they're
10821     * available. This method should only be called for touch events.
10822     *
10823     * <p class="note">This api is not intended for most applications. Buffered dispatch
10824     * provides many of benefits, and just requesting unbuffered dispatch on most MotionEvent
10825     * streams will not improve your input latency. Side effects include: increased latency,
10826     * jittery scrolls and inability to take advantage of system resampling. Talk to your input
10827     * professional to see if {@link #requestUnbufferedDispatch(MotionEvent)} is right for
10828     * you.</p>
10829     */
10830    public final void requestUnbufferedDispatch(MotionEvent event) {
10831        final int action = event.getAction();
10832        if (mAttachInfo == null
10833                || action != MotionEvent.ACTION_DOWN && action != MotionEvent.ACTION_MOVE
10834                || !event.isTouchEvent()) {
10835            return;
10836        }
10837        mAttachInfo.mUnbufferedDispatchRequested = true;
10838    }
10839
10840    /**
10841     * Set flags controlling behavior of this view.
10842     *
10843     * @param flags Constant indicating the value which should be set
10844     * @param mask Constant indicating the bit range that should be changed
10845     */
10846    void setFlags(int flags, int mask) {
10847        final boolean accessibilityEnabled =
10848                AccessibilityManager.getInstance(mContext).isEnabled();
10849        final boolean oldIncludeForAccessibility = accessibilityEnabled && includeForAccessibility();
10850
10851        int old = mViewFlags;
10852        mViewFlags = (mViewFlags & ~mask) | (flags & mask);
10853
10854        int changed = mViewFlags ^ old;
10855        if (changed == 0) {
10856            return;
10857        }
10858        int privateFlags = mPrivateFlags;
10859
10860        /* Check if the FOCUSABLE bit has changed */
10861        if (((changed & FOCUSABLE_MASK) != 0) &&
10862                ((privateFlags & PFLAG_HAS_BOUNDS) !=0)) {
10863            if (((old & FOCUSABLE_MASK) == FOCUSABLE)
10864                    && ((privateFlags & PFLAG_FOCUSED) != 0)) {
10865                /* Give up focus if we are no longer focusable */
10866                clearFocus();
10867            } else if (((old & FOCUSABLE_MASK) == NOT_FOCUSABLE)
10868                    && ((privateFlags & PFLAG_FOCUSED) == 0)) {
10869                /*
10870                 * Tell the view system that we are now available to take focus
10871                 * if no one else already has it.
10872                 */
10873                if (mParent != null) mParent.focusableViewAvailable(this);
10874            }
10875        }
10876
10877        final int newVisibility = flags & VISIBILITY_MASK;
10878        if (newVisibility == VISIBLE) {
10879            if ((changed & VISIBILITY_MASK) != 0) {
10880                /*
10881                 * If this view is becoming visible, invalidate it in case it changed while
10882                 * it was not visible. Marking it drawn ensures that the invalidation will
10883                 * go through.
10884                 */
10885                mPrivateFlags |= PFLAG_DRAWN;
10886                invalidate(true);
10887
10888                needGlobalAttributesUpdate(true);
10889
10890                // a view becoming visible is worth notifying the parent
10891                // about in case nothing has focus.  even if this specific view
10892                // isn't focusable, it may contain something that is, so let
10893                // the root view try to give this focus if nothing else does.
10894                if ((mParent != null) && (mBottom > mTop) && (mRight > mLeft)) {
10895                    mParent.focusableViewAvailable(this);
10896                }
10897            }
10898        }
10899
10900        /* Check if the GONE bit has changed */
10901        if ((changed & GONE) != 0) {
10902            needGlobalAttributesUpdate(false);
10903            requestLayout();
10904
10905            if (((mViewFlags & VISIBILITY_MASK) == GONE)) {
10906                if (hasFocus()) clearFocus();
10907                clearAccessibilityFocus();
10908                destroyDrawingCache();
10909                if (mParent instanceof View) {
10910                    // GONE views noop invalidation, so invalidate the parent
10911                    ((View) mParent).invalidate(true);
10912                }
10913                // Mark the view drawn to ensure that it gets invalidated properly the next
10914                // time it is visible and gets invalidated
10915                mPrivateFlags |= PFLAG_DRAWN;
10916            }
10917            if (mAttachInfo != null) {
10918                mAttachInfo.mViewVisibilityChanged = true;
10919            }
10920        }
10921
10922        /* Check if the VISIBLE bit has changed */
10923        if ((changed & INVISIBLE) != 0) {
10924            needGlobalAttributesUpdate(false);
10925            /*
10926             * If this view is becoming invisible, set the DRAWN flag so that
10927             * the next invalidate() will not be skipped.
10928             */
10929            mPrivateFlags |= PFLAG_DRAWN;
10930
10931            if (((mViewFlags & VISIBILITY_MASK) == INVISIBLE)) {
10932                // root view becoming invisible shouldn't clear focus and accessibility focus
10933                if (getRootView() != this) {
10934                    if (hasFocus()) clearFocus();
10935                    clearAccessibilityFocus();
10936                }
10937            }
10938            if (mAttachInfo != null) {
10939                mAttachInfo.mViewVisibilityChanged = true;
10940            }
10941        }
10942
10943        if ((changed & VISIBILITY_MASK) != 0) {
10944            // If the view is invisible, cleanup its display list to free up resources
10945            if (newVisibility != VISIBLE && mAttachInfo != null) {
10946                cleanupDraw();
10947            }
10948
10949            if (mParent instanceof ViewGroup) {
10950                ((ViewGroup) mParent).onChildVisibilityChanged(this,
10951                        (changed & VISIBILITY_MASK), newVisibility);
10952                ((View) mParent).invalidate(true);
10953            } else if (mParent != null) {
10954                mParent.invalidateChild(this, null);
10955            }
10956
10957            if (mAttachInfo != null) {
10958                dispatchVisibilityChanged(this, newVisibility);
10959                notifySubtreeAccessibilityStateChangedIfNeeded();
10960            }
10961        }
10962
10963        if ((changed & WILL_NOT_CACHE_DRAWING) != 0) {
10964            destroyDrawingCache();
10965        }
10966
10967        if ((changed & DRAWING_CACHE_ENABLED) != 0) {
10968            destroyDrawingCache();
10969            mPrivateFlags &= ~PFLAG_DRAWING_CACHE_VALID;
10970            invalidateParentCaches();
10971        }
10972
10973        if ((changed & DRAWING_CACHE_QUALITY_MASK) != 0) {
10974            destroyDrawingCache();
10975            mPrivateFlags &= ~PFLAG_DRAWING_CACHE_VALID;
10976        }
10977
10978        if ((changed & DRAW_MASK) != 0) {
10979            if ((mViewFlags & WILL_NOT_DRAW) != 0) {
10980                if (mBackground != null
10981                        || (mForegroundInfo != null && mForegroundInfo.mDrawable != null)) {
10982                    mPrivateFlags &= ~PFLAG_SKIP_DRAW;
10983                } else {
10984                    mPrivateFlags |= PFLAG_SKIP_DRAW;
10985                }
10986            } else {
10987                mPrivateFlags &= ~PFLAG_SKIP_DRAW;
10988            }
10989            requestLayout();
10990            invalidate(true);
10991        }
10992
10993        if ((changed & KEEP_SCREEN_ON) != 0) {
10994            if (mParent != null && mAttachInfo != null && !mAttachInfo.mRecomputeGlobalAttributes) {
10995                mParent.recomputeViewAttributes(this);
10996            }
10997        }
10998
10999        if (accessibilityEnabled) {
11000            if ((changed & FOCUSABLE_MASK) != 0 || (changed & VISIBILITY_MASK) != 0
11001                    || (changed & CLICKABLE) != 0 || (changed & LONG_CLICKABLE) != 0
11002                    || (changed & CONTEXT_CLICKABLE) != 0) {
11003                if (oldIncludeForAccessibility != includeForAccessibility()) {
11004                    notifySubtreeAccessibilityStateChangedIfNeeded();
11005                } else {
11006                    notifyViewAccessibilityStateChangedIfNeeded(
11007                            AccessibilityEvent.CONTENT_CHANGE_TYPE_UNDEFINED);
11008                }
11009            } else if ((changed & ENABLED_MASK) != 0) {
11010                notifyViewAccessibilityStateChangedIfNeeded(
11011                        AccessibilityEvent.CONTENT_CHANGE_TYPE_UNDEFINED);
11012            }
11013        }
11014    }
11015
11016    /**
11017     * Change the view's z order in the tree, so it's on top of other sibling
11018     * views. This ordering change may affect layout, if the parent container
11019     * uses an order-dependent layout scheme (e.g., LinearLayout). Prior
11020     * to {@link android.os.Build.VERSION_CODES#KITKAT} this
11021     * method should be followed by calls to {@link #requestLayout()} and
11022     * {@link View#invalidate()} on the view's parent to force the parent to redraw
11023     * with the new child ordering.
11024     *
11025     * @see ViewGroup#bringChildToFront(View)
11026     */
11027    public void bringToFront() {
11028        if (mParent != null) {
11029            mParent.bringChildToFront(this);
11030        }
11031    }
11032
11033    /**
11034     * This is called in response to an internal scroll in this view (i.e., the
11035     * view scrolled its own contents). This is typically as a result of
11036     * {@link #scrollBy(int, int)} or {@link #scrollTo(int, int)} having been
11037     * called.
11038     *
11039     * @param l Current horizontal scroll origin.
11040     * @param t Current vertical scroll origin.
11041     * @param oldl Previous horizontal scroll origin.
11042     * @param oldt Previous vertical scroll origin.
11043     */
11044    protected void onScrollChanged(int l, int t, int oldl, int oldt) {
11045        notifySubtreeAccessibilityStateChangedIfNeeded();
11046
11047        if (AccessibilityManager.getInstance(mContext).isEnabled()) {
11048            postSendViewScrolledAccessibilityEventCallback();
11049        }
11050
11051        mBackgroundSizeChanged = true;
11052        if (mForegroundInfo != null) {
11053            mForegroundInfo.mBoundsChanged = true;
11054        }
11055
11056        final AttachInfo ai = mAttachInfo;
11057        if (ai != null) {
11058            ai.mViewScrollChanged = true;
11059        }
11060
11061        if (mListenerInfo != null && mListenerInfo.mOnScrollChangeListener != null) {
11062            mListenerInfo.mOnScrollChangeListener.onScrollChange(this, l, t, oldl, oldt);
11063        }
11064    }
11065
11066    /**
11067     * Interface definition for a callback to be invoked when the scroll
11068     * X or Y positions of a view change.
11069     * <p>
11070     * <b>Note:</b> Some views handle scrolling independently from View and may
11071     * have their own separate listeners for scroll-type events. For example,
11072     * {@link android.widget.ListView ListView} allows clients to register an
11073     * {@link android.widget.ListView#setOnScrollListener(android.widget.AbsListView.OnScrollListener) AbsListView.OnScrollListener}
11074     * to listen for changes in list scroll position.
11075     *
11076     * @see #setOnScrollChangeListener(View.OnScrollChangeListener)
11077     */
11078    public interface OnScrollChangeListener {
11079        /**
11080         * Called when the scroll position of a view changes.
11081         *
11082         * @param v The view whose scroll position has changed.
11083         * @param scrollX Current horizontal scroll origin.
11084         * @param scrollY Current vertical scroll origin.
11085         * @param oldScrollX Previous horizontal scroll origin.
11086         * @param oldScrollY Previous vertical scroll origin.
11087         */
11088        void onScrollChange(View v, int scrollX, int scrollY, int oldScrollX, int oldScrollY);
11089    }
11090
11091    /**
11092     * Interface definition for a callback to be invoked when the layout bounds of a view
11093     * changes due to layout processing.
11094     */
11095    public interface OnLayoutChangeListener {
11096        /**
11097         * Called when the layout bounds of a view changes due to layout processing.
11098         *
11099         * @param v The view whose bounds have changed.
11100         * @param left The new value of the view's left property.
11101         * @param top The new value of the view's top property.
11102         * @param right The new value of the view's right property.
11103         * @param bottom The new value of the view's bottom property.
11104         * @param oldLeft The previous value of the view's left property.
11105         * @param oldTop The previous value of the view's top property.
11106         * @param oldRight The previous value of the view's right property.
11107         * @param oldBottom The previous value of the view's bottom property.
11108         */
11109        void onLayoutChange(View v, int left, int top, int right, int bottom,
11110            int oldLeft, int oldTop, int oldRight, int oldBottom);
11111    }
11112
11113    /**
11114     * This is called during layout when the size of this view has changed. If
11115     * you were just added to the view hierarchy, you're called with the old
11116     * values of 0.
11117     *
11118     * @param w Current width of this view.
11119     * @param h Current height of this view.
11120     * @param oldw Old width of this view.
11121     * @param oldh Old height of this view.
11122     */
11123    protected void onSizeChanged(int w, int h, int oldw, int oldh) {
11124    }
11125
11126    /**
11127     * Called by draw to draw the child views. This may be overridden
11128     * by derived classes to gain control just before its children are drawn
11129     * (but after its own view has been drawn).
11130     * @param canvas the canvas on which to draw the view
11131     */
11132    protected void dispatchDraw(Canvas canvas) {
11133
11134    }
11135
11136    /**
11137     * Gets the parent of this view. Note that the parent is a
11138     * ViewParent and not necessarily a View.
11139     *
11140     * @return Parent of this view.
11141     */
11142    public final ViewParent getParent() {
11143        return mParent;
11144    }
11145
11146    /**
11147     * Set the horizontal scrolled position of your view. This will cause a call to
11148     * {@link #onScrollChanged(int, int, int, int)} and the view will be
11149     * invalidated.
11150     * @param value the x position to scroll to
11151     */
11152    public void setScrollX(int value) {
11153        scrollTo(value, mScrollY);
11154    }
11155
11156    /**
11157     * Set the vertical scrolled position of your view. This will cause a call to
11158     * {@link #onScrollChanged(int, int, int, int)} and the view will be
11159     * invalidated.
11160     * @param value the y position to scroll to
11161     */
11162    public void setScrollY(int value) {
11163        scrollTo(mScrollX, value);
11164    }
11165
11166    /**
11167     * Return the scrolled left position of this view. This is the left edge of
11168     * the displayed part of your view. You do not need to draw any pixels
11169     * farther left, since those are outside of the frame of your view on
11170     * screen.
11171     *
11172     * @return The left edge of the displayed part of your view, in pixels.
11173     */
11174    public final int getScrollX() {
11175        return mScrollX;
11176    }
11177
11178    /**
11179     * Return the scrolled top position of this view. This is the top edge of
11180     * the displayed part of your view. You do not need to draw any pixels above
11181     * it, since those are outside of the frame of your view on screen.
11182     *
11183     * @return The top edge of the displayed part of your view, in pixels.
11184     */
11185    public final int getScrollY() {
11186        return mScrollY;
11187    }
11188
11189    /**
11190     * Return the width of the your view.
11191     *
11192     * @return The width of your view, in pixels.
11193     */
11194    @ViewDebug.ExportedProperty(category = "layout")
11195    public final int getWidth() {
11196        return mRight - mLeft;
11197    }
11198
11199    /**
11200     * Return the height of your view.
11201     *
11202     * @return The height of your view, in pixels.
11203     */
11204    @ViewDebug.ExportedProperty(category = "layout")
11205    public final int getHeight() {
11206        return mBottom - mTop;
11207    }
11208
11209    /**
11210     * Return the visible drawing bounds of your view. Fills in the output
11211     * rectangle with the values from getScrollX(), getScrollY(),
11212     * getWidth(), and getHeight(). These bounds do not account for any
11213     * transformation properties currently set on the view, such as
11214     * {@link #setScaleX(float)} or {@link #setRotation(float)}.
11215     *
11216     * @param outRect The (scrolled) drawing bounds of the view.
11217     */
11218    public void getDrawingRect(Rect outRect) {
11219        outRect.left = mScrollX;
11220        outRect.top = mScrollY;
11221        outRect.right = mScrollX + (mRight - mLeft);
11222        outRect.bottom = mScrollY + (mBottom - mTop);
11223    }
11224
11225    /**
11226     * Like {@link #getMeasuredWidthAndState()}, but only returns the
11227     * raw width component (that is the result is masked by
11228     * {@link #MEASURED_SIZE_MASK}).
11229     *
11230     * @return The raw measured width of this view.
11231     */
11232    public final int getMeasuredWidth() {
11233        return mMeasuredWidth & MEASURED_SIZE_MASK;
11234    }
11235
11236    /**
11237     * Return the full width measurement information for this view as computed
11238     * by the most recent call to {@link #measure(int, int)}.  This result is a bit mask
11239     * as defined by {@link #MEASURED_SIZE_MASK} and {@link #MEASURED_STATE_TOO_SMALL}.
11240     * This should be used during measurement and layout calculations only. Use
11241     * {@link #getWidth()} to see how wide a view is after layout.
11242     *
11243     * @return The measured width of this view as a bit mask.
11244     */
11245    @ViewDebug.ExportedProperty(category = "measurement", flagMapping = {
11246            @ViewDebug.FlagToString(mask = MEASURED_STATE_MASK, equals = MEASURED_STATE_TOO_SMALL,
11247                    name = "MEASURED_STATE_TOO_SMALL"),
11248    })
11249    public final int getMeasuredWidthAndState() {
11250        return mMeasuredWidth;
11251    }
11252
11253    /**
11254     * Like {@link #getMeasuredHeightAndState()}, but only returns the
11255     * raw width component (that is the result is masked by
11256     * {@link #MEASURED_SIZE_MASK}).
11257     *
11258     * @return The raw measured height of this view.
11259     */
11260    public final int getMeasuredHeight() {
11261        return mMeasuredHeight & MEASURED_SIZE_MASK;
11262    }
11263
11264    /**
11265     * Return the full height measurement information for this view as computed
11266     * by the most recent call to {@link #measure(int, int)}.  This result is a bit mask
11267     * as defined by {@link #MEASURED_SIZE_MASK} and {@link #MEASURED_STATE_TOO_SMALL}.
11268     * This should be used during measurement and layout calculations only. Use
11269     * {@link #getHeight()} to see how wide a view is after layout.
11270     *
11271     * @return The measured width of this view as a bit mask.
11272     */
11273    @ViewDebug.ExportedProperty(category = "measurement", flagMapping = {
11274            @ViewDebug.FlagToString(mask = MEASURED_STATE_MASK, equals = MEASURED_STATE_TOO_SMALL,
11275                    name = "MEASURED_STATE_TOO_SMALL"),
11276    })
11277    public final int getMeasuredHeightAndState() {
11278        return mMeasuredHeight;
11279    }
11280
11281    /**
11282     * Return only the state bits of {@link #getMeasuredWidthAndState()}
11283     * and {@link #getMeasuredHeightAndState()}, combined into one integer.
11284     * The width component is in the regular bits {@link #MEASURED_STATE_MASK}
11285     * and the height component is at the shifted bits
11286     * {@link #MEASURED_HEIGHT_STATE_SHIFT}>>{@link #MEASURED_STATE_MASK}.
11287     */
11288    public final int getMeasuredState() {
11289        return (mMeasuredWidth&MEASURED_STATE_MASK)
11290                | ((mMeasuredHeight>>MEASURED_HEIGHT_STATE_SHIFT)
11291                        & (MEASURED_STATE_MASK>>MEASURED_HEIGHT_STATE_SHIFT));
11292    }
11293
11294    /**
11295     * The transform matrix of this view, which is calculated based on the current
11296     * rotation, scale, and pivot properties.
11297     *
11298     * @see #getRotation()
11299     * @see #getScaleX()
11300     * @see #getScaleY()
11301     * @see #getPivotX()
11302     * @see #getPivotY()
11303     * @return The current transform matrix for the view
11304     */
11305    public Matrix getMatrix() {
11306        ensureTransformationInfo();
11307        final Matrix matrix = mTransformationInfo.mMatrix;
11308        mRenderNode.getMatrix(matrix);
11309        return matrix;
11310    }
11311
11312    /**
11313     * Returns true if the transform matrix is the identity matrix.
11314     * Recomputes the matrix if necessary.
11315     *
11316     * @return True if the transform matrix is the identity matrix, false otherwise.
11317     */
11318    final boolean hasIdentityMatrix() {
11319        return mRenderNode.hasIdentityMatrix();
11320    }
11321
11322    void ensureTransformationInfo() {
11323        if (mTransformationInfo == null) {
11324            mTransformationInfo = new TransformationInfo();
11325        }
11326    }
11327
11328   /**
11329     * Utility method to retrieve the inverse of the current mMatrix property.
11330     * We cache the matrix to avoid recalculating it when transform properties
11331     * have not changed.
11332     *
11333     * @return The inverse of the current matrix of this view.
11334     * @hide
11335     */
11336    public final Matrix getInverseMatrix() {
11337        ensureTransformationInfo();
11338        if (mTransformationInfo.mInverseMatrix == null) {
11339            mTransformationInfo.mInverseMatrix = new Matrix();
11340        }
11341        final Matrix matrix = mTransformationInfo.mInverseMatrix;
11342        mRenderNode.getInverseMatrix(matrix);
11343        return matrix;
11344    }
11345
11346    /**
11347     * Gets the distance along the Z axis from the camera to this view.
11348     *
11349     * @see #setCameraDistance(float)
11350     *
11351     * @return The distance along the Z axis.
11352     */
11353    public float getCameraDistance() {
11354        final float dpi = mResources.getDisplayMetrics().densityDpi;
11355        return -(mRenderNode.getCameraDistance() * dpi);
11356    }
11357
11358    /**
11359     * <p>Sets the distance along the Z axis (orthogonal to the X/Y plane on which
11360     * views are drawn) from the camera to this view. The camera's distance
11361     * affects 3D transformations, for instance rotations around the X and Y
11362     * axis. If the rotationX or rotationY properties are changed and this view is
11363     * large (more than half the size of the screen), it is recommended to always
11364     * use a camera distance that's greater than the height (X axis rotation) or
11365     * the width (Y axis rotation) of this view.</p>
11366     *
11367     * <p>The distance of the camera from the view plane can have an affect on the
11368     * perspective distortion of the view when it is rotated around the x or y axis.
11369     * For example, a large distance will result in a large viewing angle, and there
11370     * will not be much perspective distortion of the view as it rotates. A short
11371     * distance may cause much more perspective distortion upon rotation, and can
11372     * also result in some drawing artifacts if the rotated view ends up partially
11373     * behind the camera (which is why the recommendation is to use a distance at
11374     * least as far as the size of the view, if the view is to be rotated.)</p>
11375     *
11376     * <p>The distance is expressed in "depth pixels." The default distance depends
11377     * on the screen density. For instance, on a medium density display, the
11378     * default distance is 1280. On a high density display, the default distance
11379     * is 1920.</p>
11380     *
11381     * <p>If you want to specify a distance that leads to visually consistent
11382     * results across various densities, use the following formula:</p>
11383     * <pre>
11384     * float scale = context.getResources().getDisplayMetrics().density;
11385     * view.setCameraDistance(distance * scale);
11386     * </pre>
11387     *
11388     * <p>The density scale factor of a high density display is 1.5,
11389     * and 1920 = 1280 * 1.5.</p>
11390     *
11391     * @param distance The distance in "depth pixels", if negative the opposite
11392     *        value is used
11393     *
11394     * @see #setRotationX(float)
11395     * @see #setRotationY(float)
11396     */
11397    public void setCameraDistance(float distance) {
11398        final float dpi = mResources.getDisplayMetrics().densityDpi;
11399
11400        invalidateViewProperty(true, false);
11401        mRenderNode.setCameraDistance(-Math.abs(distance) / dpi);
11402        invalidateViewProperty(false, false);
11403
11404        invalidateParentIfNeededAndWasQuickRejected();
11405    }
11406
11407    /**
11408     * The degrees that the view is rotated around the pivot point.
11409     *
11410     * @see #setRotation(float)
11411     * @see #getPivotX()
11412     * @see #getPivotY()
11413     *
11414     * @return The degrees of rotation.
11415     */
11416    @ViewDebug.ExportedProperty(category = "drawing")
11417    public float getRotation() {
11418        return mRenderNode.getRotation();
11419    }
11420
11421    /**
11422     * Sets the degrees that the view is rotated around the pivot point. Increasing values
11423     * result in clockwise rotation.
11424     *
11425     * @param rotation The degrees of rotation.
11426     *
11427     * @see #getRotation()
11428     * @see #getPivotX()
11429     * @see #getPivotY()
11430     * @see #setRotationX(float)
11431     * @see #setRotationY(float)
11432     *
11433     * @attr ref android.R.styleable#View_rotation
11434     */
11435    public void setRotation(float rotation) {
11436        if (rotation != getRotation()) {
11437            // Double-invalidation is necessary to capture view's old and new areas
11438            invalidateViewProperty(true, false);
11439            mRenderNode.setRotation(rotation);
11440            invalidateViewProperty(false, true);
11441
11442            invalidateParentIfNeededAndWasQuickRejected();
11443            notifySubtreeAccessibilityStateChangedIfNeeded();
11444        }
11445    }
11446
11447    /**
11448     * The degrees that the view is rotated around the vertical axis through the pivot point.
11449     *
11450     * @see #getPivotX()
11451     * @see #getPivotY()
11452     * @see #setRotationY(float)
11453     *
11454     * @return The degrees of Y rotation.
11455     */
11456    @ViewDebug.ExportedProperty(category = "drawing")
11457    public float getRotationY() {
11458        return mRenderNode.getRotationY();
11459    }
11460
11461    /**
11462     * Sets the degrees that the view is rotated around the vertical axis through the pivot point.
11463     * Increasing values result in counter-clockwise rotation from the viewpoint of looking
11464     * down the y axis.
11465     *
11466     * When rotating large views, it is recommended to adjust the camera distance
11467     * accordingly. Refer to {@link #setCameraDistance(float)} for more information.
11468     *
11469     * @param rotationY The degrees of Y rotation.
11470     *
11471     * @see #getRotationY()
11472     * @see #getPivotX()
11473     * @see #getPivotY()
11474     * @see #setRotation(float)
11475     * @see #setRotationX(float)
11476     * @see #setCameraDistance(float)
11477     *
11478     * @attr ref android.R.styleable#View_rotationY
11479     */
11480    public void setRotationY(float rotationY) {
11481        if (rotationY != getRotationY()) {
11482            invalidateViewProperty(true, false);
11483            mRenderNode.setRotationY(rotationY);
11484            invalidateViewProperty(false, true);
11485
11486            invalidateParentIfNeededAndWasQuickRejected();
11487            notifySubtreeAccessibilityStateChangedIfNeeded();
11488        }
11489    }
11490
11491    /**
11492     * The degrees that the view is rotated around the horizontal axis through the pivot point.
11493     *
11494     * @see #getPivotX()
11495     * @see #getPivotY()
11496     * @see #setRotationX(float)
11497     *
11498     * @return The degrees of X rotation.
11499     */
11500    @ViewDebug.ExportedProperty(category = "drawing")
11501    public float getRotationX() {
11502        return mRenderNode.getRotationX();
11503    }
11504
11505    /**
11506     * Sets the degrees that the view is rotated around the horizontal axis through the pivot point.
11507     * Increasing values result in clockwise rotation from the viewpoint of looking down the
11508     * x axis.
11509     *
11510     * When rotating large views, it is recommended to adjust the camera distance
11511     * accordingly. Refer to {@link #setCameraDistance(float)} for more information.
11512     *
11513     * @param rotationX The degrees of X rotation.
11514     *
11515     * @see #getRotationX()
11516     * @see #getPivotX()
11517     * @see #getPivotY()
11518     * @see #setRotation(float)
11519     * @see #setRotationY(float)
11520     * @see #setCameraDistance(float)
11521     *
11522     * @attr ref android.R.styleable#View_rotationX
11523     */
11524    public void setRotationX(float rotationX) {
11525        if (rotationX != getRotationX()) {
11526            invalidateViewProperty(true, false);
11527            mRenderNode.setRotationX(rotationX);
11528            invalidateViewProperty(false, true);
11529
11530            invalidateParentIfNeededAndWasQuickRejected();
11531            notifySubtreeAccessibilityStateChangedIfNeeded();
11532        }
11533    }
11534
11535    /**
11536     * The amount that the view is scaled in x around the pivot point, as a proportion of
11537     * the view's unscaled width. A value of 1, the default, means that no scaling is applied.
11538     *
11539     * <p>By default, this is 1.0f.
11540     *
11541     * @see #getPivotX()
11542     * @see #getPivotY()
11543     * @return The scaling factor.
11544     */
11545    @ViewDebug.ExportedProperty(category = "drawing")
11546    public float getScaleX() {
11547        return mRenderNode.getScaleX();
11548    }
11549
11550    /**
11551     * Sets the amount that the view is scaled in x around the pivot point, as a proportion of
11552     * the view's unscaled width. A value of 1 means that no scaling is applied.
11553     *
11554     * @param scaleX The scaling factor.
11555     * @see #getPivotX()
11556     * @see #getPivotY()
11557     *
11558     * @attr ref android.R.styleable#View_scaleX
11559     */
11560    public void setScaleX(float scaleX) {
11561        if (scaleX != getScaleX()) {
11562            invalidateViewProperty(true, false);
11563            mRenderNode.setScaleX(scaleX);
11564            invalidateViewProperty(false, true);
11565
11566            invalidateParentIfNeededAndWasQuickRejected();
11567            notifySubtreeAccessibilityStateChangedIfNeeded();
11568        }
11569    }
11570
11571    /**
11572     * The amount that the view is scaled in y around the pivot point, as a proportion of
11573     * the view's unscaled height. A value of 1, the default, means that no scaling is applied.
11574     *
11575     * <p>By default, this is 1.0f.
11576     *
11577     * @see #getPivotX()
11578     * @see #getPivotY()
11579     * @return The scaling factor.
11580     */
11581    @ViewDebug.ExportedProperty(category = "drawing")
11582    public float getScaleY() {
11583        return mRenderNode.getScaleY();
11584    }
11585
11586    /**
11587     * Sets the amount that the view is scaled in Y around the pivot point, as a proportion of
11588     * the view's unscaled width. A value of 1 means that no scaling is applied.
11589     *
11590     * @param scaleY The scaling factor.
11591     * @see #getPivotX()
11592     * @see #getPivotY()
11593     *
11594     * @attr ref android.R.styleable#View_scaleY
11595     */
11596    public void setScaleY(float scaleY) {
11597        if (scaleY != getScaleY()) {
11598            invalidateViewProperty(true, false);
11599            mRenderNode.setScaleY(scaleY);
11600            invalidateViewProperty(false, true);
11601
11602            invalidateParentIfNeededAndWasQuickRejected();
11603            notifySubtreeAccessibilityStateChangedIfNeeded();
11604        }
11605    }
11606
11607    /**
11608     * The x location of the point around which the view is {@link #setRotation(float) rotated}
11609     * and {@link #setScaleX(float) scaled}.
11610     *
11611     * @see #getRotation()
11612     * @see #getScaleX()
11613     * @see #getScaleY()
11614     * @see #getPivotY()
11615     * @return The x location of the pivot point.
11616     *
11617     * @attr ref android.R.styleable#View_transformPivotX
11618     */
11619    @ViewDebug.ExportedProperty(category = "drawing")
11620    public float getPivotX() {
11621        return mRenderNode.getPivotX();
11622    }
11623
11624    /**
11625     * Sets the x location of the point around which the view is
11626     * {@link #setRotation(float) rotated} and {@link #setScaleX(float) scaled}.
11627     * By default, the pivot point is centered on the object.
11628     * Setting this property disables this behavior and causes the view to use only the
11629     * explicitly set pivotX and pivotY values.
11630     *
11631     * @param pivotX The x location of the pivot point.
11632     * @see #getRotation()
11633     * @see #getScaleX()
11634     * @see #getScaleY()
11635     * @see #getPivotY()
11636     *
11637     * @attr ref android.R.styleable#View_transformPivotX
11638     */
11639    public void setPivotX(float pivotX) {
11640        if (!mRenderNode.isPivotExplicitlySet() || pivotX != getPivotX()) {
11641            invalidateViewProperty(true, false);
11642            mRenderNode.setPivotX(pivotX);
11643            invalidateViewProperty(false, true);
11644
11645            invalidateParentIfNeededAndWasQuickRejected();
11646        }
11647    }
11648
11649    /**
11650     * The y location of the point around which the view is {@link #setRotation(float) rotated}
11651     * and {@link #setScaleY(float) scaled}.
11652     *
11653     * @see #getRotation()
11654     * @see #getScaleX()
11655     * @see #getScaleY()
11656     * @see #getPivotY()
11657     * @return The y location of the pivot point.
11658     *
11659     * @attr ref android.R.styleable#View_transformPivotY
11660     */
11661    @ViewDebug.ExportedProperty(category = "drawing")
11662    public float getPivotY() {
11663        return mRenderNode.getPivotY();
11664    }
11665
11666    /**
11667     * Sets the y location of the point around which the view is {@link #setRotation(float) rotated}
11668     * and {@link #setScaleY(float) scaled}. By default, the pivot point is centered on the object.
11669     * Setting this property disables this behavior and causes the view to use only the
11670     * explicitly set pivotX and pivotY values.
11671     *
11672     * @param pivotY The y location of the pivot point.
11673     * @see #getRotation()
11674     * @see #getScaleX()
11675     * @see #getScaleY()
11676     * @see #getPivotY()
11677     *
11678     * @attr ref android.R.styleable#View_transformPivotY
11679     */
11680    public void setPivotY(float pivotY) {
11681        if (!mRenderNode.isPivotExplicitlySet() || pivotY != getPivotY()) {
11682            invalidateViewProperty(true, false);
11683            mRenderNode.setPivotY(pivotY);
11684            invalidateViewProperty(false, true);
11685
11686            invalidateParentIfNeededAndWasQuickRejected();
11687        }
11688    }
11689
11690    /**
11691     * The opacity of the view. This is a value from 0 to 1, where 0 means the view is
11692     * completely transparent and 1 means the view is completely opaque.
11693     *
11694     * <p>By default this is 1.0f.
11695     * @return The opacity of the view.
11696     */
11697    @ViewDebug.ExportedProperty(category = "drawing")
11698    public float getAlpha() {
11699        return mTransformationInfo != null ? mTransformationInfo.mAlpha : 1;
11700    }
11701
11702    /**
11703     * Returns whether this View has content which overlaps.
11704     *
11705     * <p>This function, intended to be overridden by specific View types, is an optimization when
11706     * alpha is set on a view. If rendering overlaps in a view with alpha < 1, that view is drawn to
11707     * an offscreen buffer and then composited into place, which can be expensive. If the view has
11708     * no overlapping rendering, the view can draw each primitive with the appropriate alpha value
11709     * directly. An example of overlapping rendering is a TextView with a background image, such as
11710     * a Button. An example of non-overlapping rendering is a TextView with no background, or an
11711     * ImageView with only the foreground image. The default implementation returns true; subclasses
11712     * should override if they have cases which can be optimized.</p>
11713     *
11714     * <p>The current implementation of the saveLayer and saveLayerAlpha methods in {@link Canvas}
11715     * necessitates that a View return true if it uses the methods internally without passing the
11716     * {@link Canvas#CLIP_TO_LAYER_SAVE_FLAG}.</p>
11717     *
11718     * @return true if the content in this view might overlap, false otherwise.
11719     */
11720    @ViewDebug.ExportedProperty(category = "drawing")
11721    public boolean hasOverlappingRendering() {
11722        return true;
11723    }
11724
11725    /**
11726     * Sets the opacity of the view to a value from 0 to 1, where 0 means the view is
11727     * completely transparent and 1 means the view is completely opaque.
11728     *
11729     * <p class="note"><strong>Note:</strong> setting alpha to a translucent value (0 < alpha < 1)
11730     * can have significant performance implications, especially for large views. It is best to use
11731     * the alpha property sparingly and transiently, as in the case of fading animations.</p>
11732     *
11733     * <p>For a view with a frequently changing alpha, such as during a fading animation, it is
11734     * strongly recommended for performance reasons to either override
11735     * {@link #hasOverlappingRendering()} to return <code>false</code> if appropriate, or setting a
11736     * {@link #setLayerType(int, android.graphics.Paint) layer type} on the view for the duration
11737     * of the animation. On versions {@link android.os.Build.VERSION_CODES#M} and below,
11738     * the default path for rendering an unlayered View with alpha could add multiple milliseconds
11739     * of rendering cost, even for simple or small views. Starting with
11740     * {@link android.os.Build.VERSION_CODES#M}, {@link #LAYER_TYPE_HARDWARE} is automatically
11741     * applied to the view at the rendering level.</p>
11742     *
11743     * <p>If this view overrides {@link #onSetAlpha(int)} to return true, then this view is
11744     * responsible for applying the opacity itself.</p>
11745     *
11746     * <p>On versions {@link android.os.Build.VERSION_CODES#LOLLIPOP_MR1} and below, note that if
11747     * the view is backed by a {@link #setLayerType(int, android.graphics.Paint) layer} and is
11748     * associated with a {@link #setLayerPaint(android.graphics.Paint) layer paint}, setting an
11749     * alpha value less than 1.0 will supersede the alpha of the layer paint.</p>
11750     *
11751     * <p>Starting with {@link android.os.Build.VERSION_CODES#M}, setting a translucent alpha
11752     * value will clip a View to its bounds, unless the View returns <code>false</code> from
11753     * {@link #hasOverlappingRendering}.</p>
11754     *
11755     * @param alpha The opacity of the view.
11756     *
11757     * @see #hasOverlappingRendering()
11758     * @see #setLayerType(int, android.graphics.Paint)
11759     *
11760     * @attr ref android.R.styleable#View_alpha
11761     */
11762    public void setAlpha(@FloatRange(from=0.0, to=1.0) float alpha) {
11763        ensureTransformationInfo();
11764        if (mTransformationInfo.mAlpha != alpha) {
11765            mTransformationInfo.mAlpha = alpha;
11766            if (onSetAlpha((int) (alpha * 255))) {
11767                mPrivateFlags |= PFLAG_ALPHA_SET;
11768                // subclass is handling alpha - don't optimize rendering cache invalidation
11769                invalidateParentCaches();
11770                invalidate(true);
11771            } else {
11772                mPrivateFlags &= ~PFLAG_ALPHA_SET;
11773                invalidateViewProperty(true, false);
11774                mRenderNode.setAlpha(getFinalAlpha());
11775                notifyViewAccessibilityStateChangedIfNeeded(
11776                        AccessibilityEvent.CONTENT_CHANGE_TYPE_UNDEFINED);
11777            }
11778        }
11779    }
11780
11781    /**
11782     * Faster version of setAlpha() which performs the same steps except there are
11783     * no calls to invalidate(). The caller of this function should perform proper invalidation
11784     * on the parent and this object. The return value indicates whether the subclass handles
11785     * alpha (the return value for onSetAlpha()).
11786     *
11787     * @param alpha The new value for the alpha property
11788     * @return true if the View subclass handles alpha (the return value for onSetAlpha()) and
11789     *         the new value for the alpha property is different from the old value
11790     */
11791    boolean setAlphaNoInvalidation(float alpha) {
11792        ensureTransformationInfo();
11793        if (mTransformationInfo.mAlpha != alpha) {
11794            mTransformationInfo.mAlpha = alpha;
11795            boolean subclassHandlesAlpha = onSetAlpha((int) (alpha * 255));
11796            if (subclassHandlesAlpha) {
11797                mPrivateFlags |= PFLAG_ALPHA_SET;
11798                return true;
11799            } else {
11800                mPrivateFlags &= ~PFLAG_ALPHA_SET;
11801                mRenderNode.setAlpha(getFinalAlpha());
11802            }
11803        }
11804        return false;
11805    }
11806
11807    /**
11808     * This property is hidden and intended only for use by the Fade transition, which
11809     * animates it to produce a visual translucency that does not side-effect (or get
11810     * affected by) the real alpha property. This value is composited with the other
11811     * alpha value (and the AlphaAnimation value, when that is present) to produce
11812     * a final visual translucency result, which is what is passed into the DisplayList.
11813     *
11814     * @hide
11815     */
11816    public void setTransitionAlpha(float alpha) {
11817        ensureTransformationInfo();
11818        if (mTransformationInfo.mTransitionAlpha != alpha) {
11819            mTransformationInfo.mTransitionAlpha = alpha;
11820            mPrivateFlags &= ~PFLAG_ALPHA_SET;
11821            invalidateViewProperty(true, false);
11822            mRenderNode.setAlpha(getFinalAlpha());
11823        }
11824    }
11825
11826    /**
11827     * Calculates the visual alpha of this view, which is a combination of the actual
11828     * alpha value and the transitionAlpha value (if set).
11829     */
11830    private float getFinalAlpha() {
11831        if (mTransformationInfo != null) {
11832            return mTransformationInfo.mAlpha * mTransformationInfo.mTransitionAlpha;
11833        }
11834        return 1;
11835    }
11836
11837    /**
11838     * This property is hidden and intended only for use by the Fade transition, which
11839     * animates it to produce a visual translucency that does not side-effect (or get
11840     * affected by) the real alpha property. This value is composited with the other
11841     * alpha value (and the AlphaAnimation value, when that is present) to produce
11842     * a final visual translucency result, which is what is passed into the DisplayList.
11843     *
11844     * @hide
11845     */
11846    @ViewDebug.ExportedProperty(category = "drawing")
11847    public float getTransitionAlpha() {
11848        return mTransformationInfo != null ? mTransformationInfo.mTransitionAlpha : 1;
11849    }
11850
11851    /**
11852     * Top position of this view relative to its parent.
11853     *
11854     * @return The top of this view, in pixels.
11855     */
11856    @ViewDebug.CapturedViewProperty
11857    public final int getTop() {
11858        return mTop;
11859    }
11860
11861    /**
11862     * Sets the top position of this view relative to its parent. This method is meant to be called
11863     * by the layout system and should not generally be called otherwise, because the property
11864     * may be changed at any time by the layout.
11865     *
11866     * @param top The top of this view, in pixels.
11867     */
11868    public final void setTop(int top) {
11869        if (top != mTop) {
11870            final boolean matrixIsIdentity = hasIdentityMatrix();
11871            if (matrixIsIdentity) {
11872                if (mAttachInfo != null) {
11873                    int minTop;
11874                    int yLoc;
11875                    if (top < mTop) {
11876                        minTop = top;
11877                        yLoc = top - mTop;
11878                    } else {
11879                        minTop = mTop;
11880                        yLoc = 0;
11881                    }
11882                    invalidate(0, yLoc, mRight - mLeft, mBottom - minTop);
11883                }
11884            } else {
11885                // Double-invalidation is necessary to capture view's old and new areas
11886                invalidate(true);
11887            }
11888
11889            int width = mRight - mLeft;
11890            int oldHeight = mBottom - mTop;
11891
11892            mTop = top;
11893            mRenderNode.setTop(mTop);
11894
11895            sizeChange(width, mBottom - mTop, width, oldHeight);
11896
11897            if (!matrixIsIdentity) {
11898                mPrivateFlags |= PFLAG_DRAWN; // force another invalidation with the new orientation
11899                invalidate(true);
11900            }
11901            mBackgroundSizeChanged = true;
11902            if (mForegroundInfo != null) {
11903                mForegroundInfo.mBoundsChanged = true;
11904            }
11905            invalidateParentIfNeeded();
11906            if ((mPrivateFlags2 & PFLAG2_VIEW_QUICK_REJECTED) == PFLAG2_VIEW_QUICK_REJECTED) {
11907                // View was rejected last time it was drawn by its parent; this may have changed
11908                invalidateParentIfNeeded();
11909            }
11910        }
11911    }
11912
11913    /**
11914     * Bottom position of this view relative to its parent.
11915     *
11916     * @return The bottom of this view, in pixels.
11917     */
11918    @ViewDebug.CapturedViewProperty
11919    public final int getBottom() {
11920        return mBottom;
11921    }
11922
11923    /**
11924     * True if this view has changed since the last time being drawn.
11925     *
11926     * @return The dirty state of this view.
11927     */
11928    public boolean isDirty() {
11929        return (mPrivateFlags & PFLAG_DIRTY_MASK) != 0;
11930    }
11931
11932    /**
11933     * Sets the bottom position of this view relative to its parent. This method is meant to be
11934     * called by the layout system and should not generally be called otherwise, because the
11935     * property may be changed at any time by the layout.
11936     *
11937     * @param bottom The bottom of this view, in pixels.
11938     */
11939    public final void setBottom(int bottom) {
11940        if (bottom != mBottom) {
11941            final boolean matrixIsIdentity = hasIdentityMatrix();
11942            if (matrixIsIdentity) {
11943                if (mAttachInfo != null) {
11944                    int maxBottom;
11945                    if (bottom < mBottom) {
11946                        maxBottom = mBottom;
11947                    } else {
11948                        maxBottom = bottom;
11949                    }
11950                    invalidate(0, 0, mRight - mLeft, maxBottom - mTop);
11951                }
11952            } else {
11953                // Double-invalidation is necessary to capture view's old and new areas
11954                invalidate(true);
11955            }
11956
11957            int width = mRight - mLeft;
11958            int oldHeight = mBottom - mTop;
11959
11960            mBottom = bottom;
11961            mRenderNode.setBottom(mBottom);
11962
11963            sizeChange(width, mBottom - mTop, width, oldHeight);
11964
11965            if (!matrixIsIdentity) {
11966                mPrivateFlags |= PFLAG_DRAWN; // force another invalidation with the new orientation
11967                invalidate(true);
11968            }
11969            mBackgroundSizeChanged = true;
11970            if (mForegroundInfo != null) {
11971                mForegroundInfo.mBoundsChanged = true;
11972            }
11973            invalidateParentIfNeeded();
11974            if ((mPrivateFlags2 & PFLAG2_VIEW_QUICK_REJECTED) == PFLAG2_VIEW_QUICK_REJECTED) {
11975                // View was rejected last time it was drawn by its parent; this may have changed
11976                invalidateParentIfNeeded();
11977            }
11978        }
11979    }
11980
11981    /**
11982     * Left position of this view relative to its parent.
11983     *
11984     * @return The left edge of this view, in pixels.
11985     */
11986    @ViewDebug.CapturedViewProperty
11987    public final int getLeft() {
11988        return mLeft;
11989    }
11990
11991    /**
11992     * Sets the left position of this view relative to its parent. This method is meant to be called
11993     * by the layout system and should not generally be called otherwise, because the property
11994     * may be changed at any time by the layout.
11995     *
11996     * @param left The left of this view, in pixels.
11997     */
11998    public final void setLeft(int left) {
11999        if (left != mLeft) {
12000            final boolean matrixIsIdentity = hasIdentityMatrix();
12001            if (matrixIsIdentity) {
12002                if (mAttachInfo != null) {
12003                    int minLeft;
12004                    int xLoc;
12005                    if (left < mLeft) {
12006                        minLeft = left;
12007                        xLoc = left - mLeft;
12008                    } else {
12009                        minLeft = mLeft;
12010                        xLoc = 0;
12011                    }
12012                    invalidate(xLoc, 0, mRight - minLeft, mBottom - mTop);
12013                }
12014            } else {
12015                // Double-invalidation is necessary to capture view's old and new areas
12016                invalidate(true);
12017            }
12018
12019            int oldWidth = mRight - mLeft;
12020            int height = mBottom - mTop;
12021
12022            mLeft = left;
12023            mRenderNode.setLeft(left);
12024
12025            sizeChange(mRight - mLeft, height, oldWidth, height);
12026
12027            if (!matrixIsIdentity) {
12028                mPrivateFlags |= PFLAG_DRAWN; // force another invalidation with the new orientation
12029                invalidate(true);
12030            }
12031            mBackgroundSizeChanged = true;
12032            if (mForegroundInfo != null) {
12033                mForegroundInfo.mBoundsChanged = true;
12034            }
12035            invalidateParentIfNeeded();
12036            if ((mPrivateFlags2 & PFLAG2_VIEW_QUICK_REJECTED) == PFLAG2_VIEW_QUICK_REJECTED) {
12037                // View was rejected last time it was drawn by its parent; this may have changed
12038                invalidateParentIfNeeded();
12039            }
12040        }
12041    }
12042
12043    /**
12044     * Right position of this view relative to its parent.
12045     *
12046     * @return The right edge of this view, in pixels.
12047     */
12048    @ViewDebug.CapturedViewProperty
12049    public final int getRight() {
12050        return mRight;
12051    }
12052
12053    /**
12054     * Sets the right position of this view relative to its parent. This method is meant to be called
12055     * by the layout system and should not generally be called otherwise, because the property
12056     * may be changed at any time by the layout.
12057     *
12058     * @param right The right of this view, in pixels.
12059     */
12060    public final void setRight(int right) {
12061        if (right != mRight) {
12062            final boolean matrixIsIdentity = hasIdentityMatrix();
12063            if (matrixIsIdentity) {
12064                if (mAttachInfo != null) {
12065                    int maxRight;
12066                    if (right < mRight) {
12067                        maxRight = mRight;
12068                    } else {
12069                        maxRight = right;
12070                    }
12071                    invalidate(0, 0, maxRight - mLeft, mBottom - mTop);
12072                }
12073            } else {
12074                // Double-invalidation is necessary to capture view's old and new areas
12075                invalidate(true);
12076            }
12077
12078            int oldWidth = mRight - mLeft;
12079            int height = mBottom - mTop;
12080
12081            mRight = right;
12082            mRenderNode.setRight(mRight);
12083
12084            sizeChange(mRight - mLeft, height, oldWidth, height);
12085
12086            if (!matrixIsIdentity) {
12087                mPrivateFlags |= PFLAG_DRAWN; // force another invalidation with the new orientation
12088                invalidate(true);
12089            }
12090            mBackgroundSizeChanged = true;
12091            if (mForegroundInfo != null) {
12092                mForegroundInfo.mBoundsChanged = true;
12093            }
12094            invalidateParentIfNeeded();
12095            if ((mPrivateFlags2 & PFLAG2_VIEW_QUICK_REJECTED) == PFLAG2_VIEW_QUICK_REJECTED) {
12096                // View was rejected last time it was drawn by its parent; this may have changed
12097                invalidateParentIfNeeded();
12098            }
12099        }
12100    }
12101
12102    /**
12103     * The visual x position of this view, in pixels. This is equivalent to the
12104     * {@link #setTranslationX(float) translationX} property plus the current
12105     * {@link #getLeft() left} property.
12106     *
12107     * @return The visual x position of this view, in pixels.
12108     */
12109    @ViewDebug.ExportedProperty(category = "drawing")
12110    public float getX() {
12111        return mLeft + getTranslationX();
12112    }
12113
12114    /**
12115     * Sets the visual x position of this view, in pixels. This is equivalent to setting the
12116     * {@link #setTranslationX(float) translationX} property to be the difference between
12117     * the x value passed in and the current {@link #getLeft() left} property.
12118     *
12119     * @param x The visual x position of this view, in pixels.
12120     */
12121    public void setX(float x) {
12122        setTranslationX(x - mLeft);
12123    }
12124
12125    /**
12126     * The visual y position of this view, in pixels. This is equivalent to the
12127     * {@link #setTranslationY(float) translationY} property plus the current
12128     * {@link #getTop() top} property.
12129     *
12130     * @return The visual y position of this view, in pixels.
12131     */
12132    @ViewDebug.ExportedProperty(category = "drawing")
12133    public float getY() {
12134        return mTop + getTranslationY();
12135    }
12136
12137    /**
12138     * Sets the visual y position of this view, in pixels. This is equivalent to setting the
12139     * {@link #setTranslationY(float) translationY} property to be the difference between
12140     * the y value passed in and the current {@link #getTop() top} property.
12141     *
12142     * @param y The visual y position of this view, in pixels.
12143     */
12144    public void setY(float y) {
12145        setTranslationY(y - mTop);
12146    }
12147
12148    /**
12149     * The visual z position of this view, in pixels. This is equivalent to the
12150     * {@link #setTranslationZ(float) translationZ} property plus the current
12151     * {@link #getElevation() elevation} property.
12152     *
12153     * @return The visual z position of this view, in pixels.
12154     */
12155    @ViewDebug.ExportedProperty(category = "drawing")
12156    public float getZ() {
12157        return getElevation() + getTranslationZ();
12158    }
12159
12160    /**
12161     * Sets the visual z position of this view, in pixels. This is equivalent to setting the
12162     * {@link #setTranslationZ(float) translationZ} property to be the difference between
12163     * the x value passed in and the current {@link #getElevation() elevation} property.
12164     *
12165     * @param z The visual z position of this view, in pixels.
12166     */
12167    public void setZ(float z) {
12168        setTranslationZ(z - getElevation());
12169    }
12170
12171    /**
12172     * The base elevation of this view relative to its parent, in pixels.
12173     *
12174     * @return The base depth position of the view, in pixels.
12175     */
12176    @ViewDebug.ExportedProperty(category = "drawing")
12177    public float getElevation() {
12178        return mRenderNode.getElevation();
12179    }
12180
12181    /**
12182     * Sets the base elevation of this view, in pixels.
12183     *
12184     * @attr ref android.R.styleable#View_elevation
12185     */
12186    public void setElevation(float elevation) {
12187        if (elevation != getElevation()) {
12188            invalidateViewProperty(true, false);
12189            mRenderNode.setElevation(elevation);
12190            invalidateViewProperty(false, true);
12191
12192            invalidateParentIfNeededAndWasQuickRejected();
12193        }
12194    }
12195
12196    /**
12197     * The horizontal location of this view relative to its {@link #getLeft() left} position.
12198     * This position is post-layout, in addition to wherever the object's
12199     * layout placed it.
12200     *
12201     * @return The horizontal position of this view relative to its left position, in pixels.
12202     */
12203    @ViewDebug.ExportedProperty(category = "drawing")
12204    public float getTranslationX() {
12205        return mRenderNode.getTranslationX();
12206    }
12207
12208    /**
12209     * Sets the horizontal location of this view relative to its {@link #getLeft() left} position.
12210     * This effectively positions the object post-layout, in addition to wherever the object's
12211     * layout placed it.
12212     *
12213     * @param translationX The horizontal position of this view relative to its left position,
12214     * in pixels.
12215     *
12216     * @attr ref android.R.styleable#View_translationX
12217     */
12218    public void setTranslationX(float translationX) {
12219        if (translationX != getTranslationX()) {
12220            invalidateViewProperty(true, false);
12221            mRenderNode.setTranslationX(translationX);
12222            invalidateViewProperty(false, true);
12223
12224            invalidateParentIfNeededAndWasQuickRejected();
12225            notifySubtreeAccessibilityStateChangedIfNeeded();
12226        }
12227    }
12228
12229    /**
12230     * The vertical location of this view relative to its {@link #getTop() top} position.
12231     * This position is post-layout, in addition to wherever the object's
12232     * layout placed it.
12233     *
12234     * @return The vertical position of this view relative to its top position,
12235     * in pixels.
12236     */
12237    @ViewDebug.ExportedProperty(category = "drawing")
12238    public float getTranslationY() {
12239        return mRenderNode.getTranslationY();
12240    }
12241
12242    /**
12243     * Sets the vertical location of this view relative to its {@link #getTop() top} position.
12244     * This effectively positions the object post-layout, in addition to wherever the object's
12245     * layout placed it.
12246     *
12247     * @param translationY The vertical position of this view relative to its top position,
12248     * in pixels.
12249     *
12250     * @attr ref android.R.styleable#View_translationY
12251     */
12252    public void setTranslationY(float translationY) {
12253        if (translationY != getTranslationY()) {
12254            invalidateViewProperty(true, false);
12255            mRenderNode.setTranslationY(translationY);
12256            invalidateViewProperty(false, true);
12257
12258            invalidateParentIfNeededAndWasQuickRejected();
12259            notifySubtreeAccessibilityStateChangedIfNeeded();
12260        }
12261    }
12262
12263    /**
12264     * The depth location of this view relative to its {@link #getElevation() elevation}.
12265     *
12266     * @return The depth of this view relative to its elevation.
12267     */
12268    @ViewDebug.ExportedProperty(category = "drawing")
12269    public float getTranslationZ() {
12270        return mRenderNode.getTranslationZ();
12271    }
12272
12273    /**
12274     * Sets the depth location of this view relative to its {@link #getElevation() elevation}.
12275     *
12276     * @attr ref android.R.styleable#View_translationZ
12277     */
12278    public void setTranslationZ(float translationZ) {
12279        if (translationZ != getTranslationZ()) {
12280            invalidateViewProperty(true, false);
12281            mRenderNode.setTranslationZ(translationZ);
12282            invalidateViewProperty(false, true);
12283
12284            invalidateParentIfNeededAndWasQuickRejected();
12285        }
12286    }
12287
12288    /** @hide */
12289    public void setAnimationMatrix(Matrix matrix) {
12290        invalidateViewProperty(true, false);
12291        mRenderNode.setAnimationMatrix(matrix);
12292        invalidateViewProperty(false, true);
12293
12294        invalidateParentIfNeededAndWasQuickRejected();
12295    }
12296
12297    /**
12298     * Returns the current StateListAnimator if exists.
12299     *
12300     * @return StateListAnimator or null if it does not exists
12301     * @see    #setStateListAnimator(android.animation.StateListAnimator)
12302     */
12303    public StateListAnimator getStateListAnimator() {
12304        return mStateListAnimator;
12305    }
12306
12307    /**
12308     * Attaches the provided StateListAnimator to this View.
12309     * <p>
12310     * Any previously attached StateListAnimator will be detached.
12311     *
12312     * @param stateListAnimator The StateListAnimator to update the view
12313     * @see {@link android.animation.StateListAnimator}
12314     */
12315    public void setStateListAnimator(StateListAnimator stateListAnimator) {
12316        if (mStateListAnimator == stateListAnimator) {
12317            return;
12318        }
12319        if (mStateListAnimator != null) {
12320            mStateListAnimator.setTarget(null);
12321        }
12322        mStateListAnimator = stateListAnimator;
12323        if (stateListAnimator != null) {
12324            stateListAnimator.setTarget(this);
12325            if (isAttachedToWindow()) {
12326                stateListAnimator.setState(getDrawableState());
12327            }
12328        }
12329    }
12330
12331    /**
12332     * Returns whether the Outline should be used to clip the contents of the View.
12333     * <p>
12334     * Note that this flag will only be respected if the View's Outline returns true from
12335     * {@link Outline#canClip()}.
12336     *
12337     * @see #setOutlineProvider(ViewOutlineProvider)
12338     * @see #setClipToOutline(boolean)
12339     */
12340    public final boolean getClipToOutline() {
12341        return mRenderNode.getClipToOutline();
12342    }
12343
12344    /**
12345     * Sets whether the View's Outline should be used to clip the contents of the View.
12346     * <p>
12347     * Only a single non-rectangular clip can be applied on a View at any time.
12348     * Circular clips from a {@link ViewAnimationUtils#createCircularReveal(View, int, int, float, float)
12349     * circular reveal} animation take priority over Outline clipping, and
12350     * child Outline clipping takes priority over Outline clipping done by a
12351     * parent.
12352     * <p>
12353     * Note that this flag will only be respected if the View's Outline returns true from
12354     * {@link Outline#canClip()}.
12355     *
12356     * @see #setOutlineProvider(ViewOutlineProvider)
12357     * @see #getClipToOutline()
12358     */
12359    public void setClipToOutline(boolean clipToOutline) {
12360        damageInParent();
12361        if (getClipToOutline() != clipToOutline) {
12362            mRenderNode.setClipToOutline(clipToOutline);
12363        }
12364    }
12365
12366    // correspond to the enum values of View_outlineProvider
12367    private static final int PROVIDER_BACKGROUND = 0;
12368    private static final int PROVIDER_NONE = 1;
12369    private static final int PROVIDER_BOUNDS = 2;
12370    private static final int PROVIDER_PADDED_BOUNDS = 3;
12371    private void setOutlineProviderFromAttribute(int providerInt) {
12372        switch (providerInt) {
12373            case PROVIDER_BACKGROUND:
12374                setOutlineProvider(ViewOutlineProvider.BACKGROUND);
12375                break;
12376            case PROVIDER_NONE:
12377                setOutlineProvider(null);
12378                break;
12379            case PROVIDER_BOUNDS:
12380                setOutlineProvider(ViewOutlineProvider.BOUNDS);
12381                break;
12382            case PROVIDER_PADDED_BOUNDS:
12383                setOutlineProvider(ViewOutlineProvider.PADDED_BOUNDS);
12384                break;
12385        }
12386    }
12387
12388    /**
12389     * Sets the {@link ViewOutlineProvider} of the view, which generates the Outline that defines
12390     * the shape of the shadow it casts, and enables outline clipping.
12391     * <p>
12392     * The default ViewOutlineProvider, {@link ViewOutlineProvider#BACKGROUND}, queries the Outline
12393     * from the View's background drawable, via {@link Drawable#getOutline(Outline)}. Changing the
12394     * outline provider with this method allows this behavior to be overridden.
12395     * <p>
12396     * If the ViewOutlineProvider is null, if querying it for an outline returns false,
12397     * or if the produced Outline is {@link Outline#isEmpty()}, shadows will not be cast.
12398     * <p>
12399     * Only outlines that return true from {@link Outline#canClip()} may be used for clipping.
12400     *
12401     * @see #setClipToOutline(boolean)
12402     * @see #getClipToOutline()
12403     * @see #getOutlineProvider()
12404     */
12405    public void setOutlineProvider(ViewOutlineProvider provider) {
12406        mOutlineProvider = provider;
12407        invalidateOutline();
12408    }
12409
12410    /**
12411     * Returns the current {@link ViewOutlineProvider} of the view, which generates the Outline
12412     * that defines the shape of the shadow it casts, and enables outline clipping.
12413     *
12414     * @see #setOutlineProvider(ViewOutlineProvider)
12415     */
12416    public ViewOutlineProvider getOutlineProvider() {
12417        return mOutlineProvider;
12418    }
12419
12420    /**
12421     * Called to rebuild this View's Outline from its {@link ViewOutlineProvider outline provider}
12422     *
12423     * @see #setOutlineProvider(ViewOutlineProvider)
12424     */
12425    public void invalidateOutline() {
12426        rebuildOutline();
12427
12428        notifySubtreeAccessibilityStateChangedIfNeeded();
12429        invalidateViewProperty(false, false);
12430    }
12431
12432    /**
12433     * Internal version of {@link #invalidateOutline()} which invalidates the
12434     * outline without invalidating the view itself. This is intended to be called from
12435     * within methods in the View class itself which are the result of the view being
12436     * invalidated already. For example, when we are drawing the background of a View,
12437     * we invalidate the outline in case it changed in the meantime, but we do not
12438     * need to invalidate the view because we're already drawing the background as part
12439     * of drawing the view in response to an earlier invalidation of the view.
12440     */
12441    private void rebuildOutline() {
12442        // Unattached views ignore this signal, and outline is recomputed in onAttachedToWindow()
12443        if (mAttachInfo == null) return;
12444
12445        if (mOutlineProvider == null) {
12446            // no provider, remove outline
12447            mRenderNode.setOutline(null);
12448        } else {
12449            final Outline outline = mAttachInfo.mTmpOutline;
12450            outline.setEmpty();
12451            outline.setAlpha(1.0f);
12452
12453            mOutlineProvider.getOutline(this, outline);
12454            mRenderNode.setOutline(outline);
12455        }
12456    }
12457
12458    /**
12459     * HierarchyViewer only
12460     *
12461     * @hide
12462     */
12463    @ViewDebug.ExportedProperty(category = "drawing")
12464    public boolean hasShadow() {
12465        return mRenderNode.hasShadow();
12466    }
12467
12468
12469    /** @hide */
12470    public void setRevealClip(boolean shouldClip, float x, float y, float radius) {
12471        mRenderNode.setRevealClip(shouldClip, x, y, radius);
12472        invalidateViewProperty(false, false);
12473    }
12474
12475    /**
12476     * Hit rectangle in parent's coordinates
12477     *
12478     * @param outRect The hit rectangle of the view.
12479     */
12480    public void getHitRect(Rect outRect) {
12481        if (hasIdentityMatrix() || mAttachInfo == null) {
12482            outRect.set(mLeft, mTop, mRight, mBottom);
12483        } else {
12484            final RectF tmpRect = mAttachInfo.mTmpTransformRect;
12485            tmpRect.set(0, 0, getWidth(), getHeight());
12486            getMatrix().mapRect(tmpRect); // TODO: mRenderNode.mapRect(tmpRect)
12487            outRect.set((int) tmpRect.left + mLeft, (int) tmpRect.top + mTop,
12488                    (int) tmpRect.right + mLeft, (int) tmpRect.bottom + mTop);
12489        }
12490    }
12491
12492    /**
12493     * Determines whether the given point, in local coordinates is inside the view.
12494     */
12495    /*package*/ final boolean pointInView(float localX, float localY) {
12496        return localX >= 0 && localX < (mRight - mLeft)
12497                && localY >= 0 && localY < (mBottom - mTop);
12498    }
12499
12500    /**
12501     * Utility method to determine whether the given point, in local coordinates,
12502     * is inside the view, where the area of the view is expanded by the slop factor.
12503     * This method is called while processing touch-move events to determine if the event
12504     * is still within the view.
12505     *
12506     * @hide
12507     */
12508    public boolean pointInView(float localX, float localY, float slop) {
12509        return localX >= -slop && localY >= -slop && localX < ((mRight - mLeft) + slop) &&
12510                localY < ((mBottom - mTop) + slop);
12511    }
12512
12513    /**
12514     * When a view has focus and the user navigates away from it, the next view is searched for
12515     * starting from the rectangle filled in by this method.
12516     *
12517     * By default, the rectangle is the {@link #getDrawingRect(android.graphics.Rect)})
12518     * of the view.  However, if your view maintains some idea of internal selection,
12519     * such as a cursor, or a selected row or column, you should override this method and
12520     * fill in a more specific rectangle.
12521     *
12522     * @param r The rectangle to fill in, in this view's coordinates.
12523     */
12524    public void getFocusedRect(Rect r) {
12525        getDrawingRect(r);
12526    }
12527
12528    /**
12529     * If some part of this view is not clipped by any of its parents, then
12530     * return that area in r in global (root) coordinates. To convert r to local
12531     * coordinates (without taking possible View rotations into account), offset
12532     * it by -globalOffset (e.g. r.offset(-globalOffset.x, -globalOffset.y)).
12533     * If the view is completely clipped or translated out, return false.
12534     *
12535     * @param r If true is returned, r holds the global coordinates of the
12536     *        visible portion of this view.
12537     * @param globalOffset If true is returned, globalOffset holds the dx,dy
12538     *        between this view and its root. globalOffet may be null.
12539     * @return true if r is non-empty (i.e. part of the view is visible at the
12540     *         root level.
12541     */
12542    public boolean getGlobalVisibleRect(Rect r, Point globalOffset) {
12543        int width = mRight - mLeft;
12544        int height = mBottom - mTop;
12545        if (width > 0 && height > 0) {
12546            r.set(0, 0, width, height);
12547            if (globalOffset != null) {
12548                globalOffset.set(-mScrollX, -mScrollY);
12549            }
12550            return mParent == null || mParent.getChildVisibleRect(this, r, globalOffset);
12551        }
12552        return false;
12553    }
12554
12555    public final boolean getGlobalVisibleRect(Rect r) {
12556        return getGlobalVisibleRect(r, null);
12557    }
12558
12559    public final boolean getLocalVisibleRect(Rect r) {
12560        final Point offset = mAttachInfo != null ? mAttachInfo.mPoint : new Point();
12561        if (getGlobalVisibleRect(r, offset)) {
12562            r.offset(-offset.x, -offset.y); // make r local
12563            return true;
12564        }
12565        return false;
12566    }
12567
12568    /**
12569     * Offset this view's vertical location by the specified number of pixels.
12570     *
12571     * @param offset the number of pixels to offset the view by
12572     */
12573    public void offsetTopAndBottom(int offset) {
12574        if (offset != 0) {
12575            final boolean matrixIsIdentity = hasIdentityMatrix();
12576            if (matrixIsIdentity) {
12577                if (isHardwareAccelerated()) {
12578                    invalidateViewProperty(false, false);
12579                } else {
12580                    final ViewParent p = mParent;
12581                    if (p != null && mAttachInfo != null) {
12582                        final Rect r = mAttachInfo.mTmpInvalRect;
12583                        int minTop;
12584                        int maxBottom;
12585                        int yLoc;
12586                        if (offset < 0) {
12587                            minTop = mTop + offset;
12588                            maxBottom = mBottom;
12589                            yLoc = offset;
12590                        } else {
12591                            minTop = mTop;
12592                            maxBottom = mBottom + offset;
12593                            yLoc = 0;
12594                        }
12595                        r.set(0, yLoc, mRight - mLeft, maxBottom - minTop);
12596                        p.invalidateChild(this, r);
12597                    }
12598                }
12599            } else {
12600                invalidateViewProperty(false, false);
12601            }
12602
12603            mTop += offset;
12604            mBottom += offset;
12605            mRenderNode.offsetTopAndBottom(offset);
12606            if (isHardwareAccelerated()) {
12607                invalidateViewProperty(false, false);
12608                invalidateParentIfNeededAndWasQuickRejected();
12609            } else {
12610                if (!matrixIsIdentity) {
12611                    invalidateViewProperty(false, true);
12612                }
12613                invalidateParentIfNeeded();
12614            }
12615            notifySubtreeAccessibilityStateChangedIfNeeded();
12616        }
12617    }
12618
12619    /**
12620     * Offset this view's horizontal location by the specified amount of pixels.
12621     *
12622     * @param offset the number of pixels to offset the view by
12623     */
12624    public void offsetLeftAndRight(int offset) {
12625        if (offset != 0) {
12626            final boolean matrixIsIdentity = hasIdentityMatrix();
12627            if (matrixIsIdentity) {
12628                if (isHardwareAccelerated()) {
12629                    invalidateViewProperty(false, false);
12630                } else {
12631                    final ViewParent p = mParent;
12632                    if (p != null && mAttachInfo != null) {
12633                        final Rect r = mAttachInfo.mTmpInvalRect;
12634                        int minLeft;
12635                        int maxRight;
12636                        if (offset < 0) {
12637                            minLeft = mLeft + offset;
12638                            maxRight = mRight;
12639                        } else {
12640                            minLeft = mLeft;
12641                            maxRight = mRight + offset;
12642                        }
12643                        r.set(0, 0, maxRight - minLeft, mBottom - mTop);
12644                        p.invalidateChild(this, r);
12645                    }
12646                }
12647            } else {
12648                invalidateViewProperty(false, false);
12649            }
12650
12651            mLeft += offset;
12652            mRight += offset;
12653            mRenderNode.offsetLeftAndRight(offset);
12654            if (isHardwareAccelerated()) {
12655                invalidateViewProperty(false, false);
12656                invalidateParentIfNeededAndWasQuickRejected();
12657            } else {
12658                if (!matrixIsIdentity) {
12659                    invalidateViewProperty(false, true);
12660                }
12661                invalidateParentIfNeeded();
12662            }
12663            notifySubtreeAccessibilityStateChangedIfNeeded();
12664        }
12665    }
12666
12667    /**
12668     * Get the LayoutParams associated with this view. All views should have
12669     * layout parameters. These supply parameters to the <i>parent</i> of this
12670     * view specifying how it should be arranged. There are many subclasses of
12671     * ViewGroup.LayoutParams, and these correspond to the different subclasses
12672     * of ViewGroup that are responsible for arranging their children.
12673     *
12674     * <p>This method may return null if this View is not attached to a parent
12675     * ViewGroup or {@link #setLayoutParams(android.view.ViewGroup.LayoutParams)}
12676     * was not invoked successfully. When a View is attached to a parent
12677     * ViewGroup, this method must not return null.</p>
12678     *
12679     * <p>Callers that modify the returned LayoutParams object should call
12680     * {@link #setLayoutParams(LayoutParams)} to explicitly inform the view that
12681     * LayoutParams have changed.</p>
12682     *
12683     * @return The LayoutParams associated with this view, or null if no
12684     *         parameters have been set yet
12685     */
12686    @ViewDebug.ExportedProperty(deepExport = true, prefix = "layout_")
12687    public ViewGroup.LayoutParams getLayoutParams() {
12688        return mLayoutParams;
12689    }
12690
12691    /**
12692     * Set the layout parameters associated with this view. These supply
12693     * parameters to the <i>parent</i> of this view specifying how it should be
12694     * arranged. There are many subclasses of ViewGroup.LayoutParams, and these
12695     * correspond to the different subclasses of ViewGroup that are responsible
12696     * for arranging their children.
12697     *
12698     * <p>If the View's existing LayoutParams object as obtained by {@link #getLayoutParams()} is
12699     * modified, you should call this method to inform the view that it has changed.</p>
12700     *
12701     * @param params The layout parameters for this view, cannot be null
12702     */
12703    public void setLayoutParams(ViewGroup.LayoutParams params) {
12704        if (params == null) {
12705            throw new NullPointerException("Layout parameters cannot be null");
12706        }
12707        mLayoutParams = params;
12708        mPrivateFlags3 |= PFLAG3_LAYOUT_PARAMS_CHANGED;
12709        resolveLayoutParams();
12710        if (mParent instanceof ViewGroup) {
12711            ((ViewGroup) mParent).onSetLayoutParams(this, params);
12712        }
12713        requestLayout();
12714    }
12715
12716    /**
12717     * Resolve the layout parameters depending on the resolved layout direction
12718     *
12719     * @hide
12720     */
12721    public void resolveLayoutParams() {
12722        if (mLayoutParams != null) {
12723            mLayoutParams.resolveLayoutDirection(getLayoutDirection());
12724        }
12725    }
12726
12727    /**
12728     * Set the scrolled position of your view. This will cause a call to
12729     * {@link #onScrollChanged(int, int, int, int)} and the view will be
12730     * invalidated.
12731     * @param x the x position to scroll to
12732     * @param y the y position to scroll to
12733     */
12734    public void scrollTo(int x, int y) {
12735        if (mScrollX != x || mScrollY != y) {
12736            int oldX = mScrollX;
12737            int oldY = mScrollY;
12738            mScrollX = x;
12739            mScrollY = y;
12740            invalidateParentCaches();
12741            onScrollChanged(mScrollX, mScrollY, oldX, oldY);
12742            if (!awakenScrollBars()) {
12743                postInvalidateOnAnimation();
12744            }
12745        }
12746    }
12747
12748    /**
12749     * Move the scrolled position of your view. This will cause a call to
12750     * {@link #onScrollChanged(int, int, int, int)} and the view will be
12751     * invalidated.
12752     * @param x the amount of pixels to scroll by horizontally
12753     * @param y the amount of pixels to scroll by vertically
12754     */
12755    public void scrollBy(int x, int y) {
12756        scrollTo(mScrollX + x, mScrollY + y);
12757    }
12758
12759    /**
12760     * <p>Trigger the scrollbars to draw. When invoked this method starts an
12761     * animation to fade the scrollbars out after a default delay. If a subclass
12762     * provides animated scrolling, the start delay should equal the duration
12763     * of the scrolling animation.</p>
12764     *
12765     * <p>The animation starts only if at least one of the scrollbars is
12766     * enabled, as specified by {@link #isHorizontalScrollBarEnabled()} and
12767     * {@link #isVerticalScrollBarEnabled()}. When the animation is started,
12768     * this method returns true, and false otherwise. If the animation is
12769     * started, this method calls {@link #invalidate()}; in that case the
12770     * caller should not call {@link #invalidate()}.</p>
12771     *
12772     * <p>This method should be invoked every time a subclass directly updates
12773     * the scroll parameters.</p>
12774     *
12775     * <p>This method is automatically invoked by {@link #scrollBy(int, int)}
12776     * and {@link #scrollTo(int, int)}.</p>
12777     *
12778     * @return true if the animation is played, false otherwise
12779     *
12780     * @see #awakenScrollBars(int)
12781     * @see #scrollBy(int, int)
12782     * @see #scrollTo(int, int)
12783     * @see #isHorizontalScrollBarEnabled()
12784     * @see #isVerticalScrollBarEnabled()
12785     * @see #setHorizontalScrollBarEnabled(boolean)
12786     * @see #setVerticalScrollBarEnabled(boolean)
12787     */
12788    protected boolean awakenScrollBars() {
12789        return mScrollCache != null &&
12790                awakenScrollBars(mScrollCache.scrollBarDefaultDelayBeforeFade, true);
12791    }
12792
12793    /**
12794     * Trigger the scrollbars to draw.
12795     * This method differs from awakenScrollBars() only in its default duration.
12796     * initialAwakenScrollBars() will show the scroll bars for longer than
12797     * usual to give the user more of a chance to notice them.
12798     *
12799     * @return true if the animation is played, false otherwise.
12800     */
12801    private boolean initialAwakenScrollBars() {
12802        return mScrollCache != null &&
12803                awakenScrollBars(mScrollCache.scrollBarDefaultDelayBeforeFade * 4, true);
12804    }
12805
12806    /**
12807     * <p>
12808     * Trigger the scrollbars to draw. When invoked this method starts an
12809     * animation to fade the scrollbars out after a fixed delay. If a subclass
12810     * provides animated scrolling, the start delay should equal the duration of
12811     * the scrolling animation.
12812     * </p>
12813     *
12814     * <p>
12815     * The animation starts only if at least one of the scrollbars is enabled,
12816     * as specified by {@link #isHorizontalScrollBarEnabled()} and
12817     * {@link #isVerticalScrollBarEnabled()}. When the animation is started,
12818     * this method returns true, and false otherwise. If the animation is
12819     * started, this method calls {@link #invalidate()}; in that case the caller
12820     * should not call {@link #invalidate()}.
12821     * </p>
12822     *
12823     * <p>
12824     * This method should be invoked every time a subclass directly updates the
12825     * scroll parameters.
12826     * </p>
12827     *
12828     * @param startDelay the delay, in milliseconds, after which the animation
12829     *        should start; when the delay is 0, the animation starts
12830     *        immediately
12831     * @return true if the animation is played, false otherwise
12832     *
12833     * @see #scrollBy(int, int)
12834     * @see #scrollTo(int, int)
12835     * @see #isHorizontalScrollBarEnabled()
12836     * @see #isVerticalScrollBarEnabled()
12837     * @see #setHorizontalScrollBarEnabled(boolean)
12838     * @see #setVerticalScrollBarEnabled(boolean)
12839     */
12840    protected boolean awakenScrollBars(int startDelay) {
12841        return awakenScrollBars(startDelay, true);
12842    }
12843
12844    /**
12845     * <p>
12846     * Trigger the scrollbars to draw. When invoked this method starts an
12847     * animation to fade the scrollbars out after a fixed delay. If a subclass
12848     * provides animated scrolling, the start delay should equal the duration of
12849     * the scrolling animation.
12850     * </p>
12851     *
12852     * <p>
12853     * The animation starts only if at least one of the scrollbars is enabled,
12854     * as specified by {@link #isHorizontalScrollBarEnabled()} and
12855     * {@link #isVerticalScrollBarEnabled()}. When the animation is started,
12856     * this method returns true, and false otherwise. If the animation is
12857     * started, this method calls {@link #invalidate()} if the invalidate parameter
12858     * is set to true; in that case the caller
12859     * should not call {@link #invalidate()}.
12860     * </p>
12861     *
12862     * <p>
12863     * This method should be invoked every time a subclass directly updates the
12864     * scroll parameters.
12865     * </p>
12866     *
12867     * @param startDelay the delay, in milliseconds, after which the animation
12868     *        should start; when the delay is 0, the animation starts
12869     *        immediately
12870     *
12871     * @param invalidate Whether this method should call invalidate
12872     *
12873     * @return true if the animation is played, false otherwise
12874     *
12875     * @see #scrollBy(int, int)
12876     * @see #scrollTo(int, int)
12877     * @see #isHorizontalScrollBarEnabled()
12878     * @see #isVerticalScrollBarEnabled()
12879     * @see #setHorizontalScrollBarEnabled(boolean)
12880     * @see #setVerticalScrollBarEnabled(boolean)
12881     */
12882    protected boolean awakenScrollBars(int startDelay, boolean invalidate) {
12883        final ScrollabilityCache scrollCache = mScrollCache;
12884
12885        if (scrollCache == null || !scrollCache.fadeScrollBars) {
12886            return false;
12887        }
12888
12889        if (scrollCache.scrollBar == null) {
12890            scrollCache.scrollBar = new ScrollBarDrawable();
12891            scrollCache.scrollBar.setCallback(this);
12892            scrollCache.scrollBar.setState(getDrawableState());
12893        }
12894
12895        if (isHorizontalScrollBarEnabled() || isVerticalScrollBarEnabled()) {
12896
12897            if (invalidate) {
12898                // Invalidate to show the scrollbars
12899                postInvalidateOnAnimation();
12900            }
12901
12902            if (scrollCache.state == ScrollabilityCache.OFF) {
12903                // FIXME: this is copied from WindowManagerService.
12904                // We should get this value from the system when it
12905                // is possible to do so.
12906                final int KEY_REPEAT_FIRST_DELAY = 750;
12907                startDelay = Math.max(KEY_REPEAT_FIRST_DELAY, startDelay);
12908            }
12909
12910            // Tell mScrollCache when we should start fading. This may
12911            // extend the fade start time if one was already scheduled
12912            long fadeStartTime = AnimationUtils.currentAnimationTimeMillis() + startDelay;
12913            scrollCache.fadeStartTime = fadeStartTime;
12914            scrollCache.state = ScrollabilityCache.ON;
12915
12916            // Schedule our fader to run, unscheduling any old ones first
12917            if (mAttachInfo != null) {
12918                mAttachInfo.mHandler.removeCallbacks(scrollCache);
12919                mAttachInfo.mHandler.postAtTime(scrollCache, fadeStartTime);
12920            }
12921
12922            return true;
12923        }
12924
12925        return false;
12926    }
12927
12928    /**
12929     * Do not invalidate views which are not visible and which are not running an animation. They
12930     * will not get drawn and they should not set dirty flags as if they will be drawn
12931     */
12932    private boolean skipInvalidate() {
12933        return (mViewFlags & VISIBILITY_MASK) != VISIBLE && mCurrentAnimation == null &&
12934                (!(mParent instanceof ViewGroup) ||
12935                        !((ViewGroup) mParent).isViewTransitioning(this));
12936    }
12937
12938    /**
12939     * Mark the area defined by dirty as needing to be drawn. If the view is
12940     * visible, {@link #onDraw(android.graphics.Canvas)} will be called at some
12941     * point in the future.
12942     * <p>
12943     * This must be called from a UI thread. To call from a non-UI thread, call
12944     * {@link #postInvalidate()}.
12945     * <p>
12946     * <b>WARNING:</b> In API 19 and below, this method may be destructive to
12947     * {@code dirty}.
12948     *
12949     * @param dirty the rectangle representing the bounds of the dirty region
12950     */
12951    public void invalidate(Rect dirty) {
12952        final int scrollX = mScrollX;
12953        final int scrollY = mScrollY;
12954        invalidateInternal(dirty.left - scrollX, dirty.top - scrollY,
12955                dirty.right - scrollX, dirty.bottom - scrollY, true, false);
12956    }
12957
12958    /**
12959     * Mark the area defined by the rect (l,t,r,b) as needing to be drawn. The
12960     * coordinates of the dirty rect are relative to the view. If the view is
12961     * visible, {@link #onDraw(android.graphics.Canvas)} will be called at some
12962     * point in the future.
12963     * <p>
12964     * This must be called from a UI thread. To call from a non-UI thread, call
12965     * {@link #postInvalidate()}.
12966     *
12967     * @param l the left position of the dirty region
12968     * @param t the top position of the dirty region
12969     * @param r the right position of the dirty region
12970     * @param b the bottom position of the dirty region
12971     */
12972    public void invalidate(int l, int t, int r, int b) {
12973        final int scrollX = mScrollX;
12974        final int scrollY = mScrollY;
12975        invalidateInternal(l - scrollX, t - scrollY, r - scrollX, b - scrollY, true, false);
12976    }
12977
12978    /**
12979     * Invalidate the whole view. If the view is visible,
12980     * {@link #onDraw(android.graphics.Canvas)} will be called at some point in
12981     * the future.
12982     * <p>
12983     * This must be called from a UI thread. To call from a non-UI thread, call
12984     * {@link #postInvalidate()}.
12985     */
12986    public void invalidate() {
12987        invalidate(true);
12988    }
12989
12990    /**
12991     * This is where the invalidate() work actually happens. A full invalidate()
12992     * causes the drawing cache to be invalidated, but this function can be
12993     * called with invalidateCache set to false to skip that invalidation step
12994     * for cases that do not need it (for example, a component that remains at
12995     * the same dimensions with the same content).
12996     *
12997     * @param invalidateCache Whether the drawing cache for this view should be
12998     *            invalidated as well. This is usually true for a full
12999     *            invalidate, but may be set to false if the View's contents or
13000     *            dimensions have not changed.
13001     */
13002    void invalidate(boolean invalidateCache) {
13003        invalidateInternal(0, 0, mRight - mLeft, mBottom - mTop, invalidateCache, true);
13004    }
13005
13006    void invalidateInternal(int l, int t, int r, int b, boolean invalidateCache,
13007            boolean fullInvalidate) {
13008        if (mGhostView != null) {
13009            mGhostView.invalidate(true);
13010            return;
13011        }
13012
13013        if (skipInvalidate()) {
13014            return;
13015        }
13016
13017        if ((mPrivateFlags & (PFLAG_DRAWN | PFLAG_HAS_BOUNDS)) == (PFLAG_DRAWN | PFLAG_HAS_BOUNDS)
13018                || (invalidateCache && (mPrivateFlags & PFLAG_DRAWING_CACHE_VALID) == PFLAG_DRAWING_CACHE_VALID)
13019                || (mPrivateFlags & PFLAG_INVALIDATED) != PFLAG_INVALIDATED
13020                || (fullInvalidate && isOpaque() != mLastIsOpaque)) {
13021            if (fullInvalidate) {
13022                mLastIsOpaque = isOpaque();
13023                mPrivateFlags &= ~PFLAG_DRAWN;
13024            }
13025
13026            mPrivateFlags |= PFLAG_DIRTY;
13027
13028            if (invalidateCache) {
13029                mPrivateFlags |= PFLAG_INVALIDATED;
13030                mPrivateFlags &= ~PFLAG_DRAWING_CACHE_VALID;
13031            }
13032
13033            // Propagate the damage rectangle to the parent view.
13034            final AttachInfo ai = mAttachInfo;
13035            final ViewParent p = mParent;
13036            if (p != null && ai != null && l < r && t < b) {
13037                final Rect damage = ai.mTmpInvalRect;
13038                damage.set(l, t, r, b);
13039                p.invalidateChild(this, damage);
13040            }
13041
13042            // Damage the entire projection receiver, if necessary.
13043            if (mBackground != null && mBackground.isProjected()) {
13044                final View receiver = getProjectionReceiver();
13045                if (receiver != null) {
13046                    receiver.damageInParent();
13047                }
13048            }
13049
13050            // Damage the entire IsolatedZVolume receiving this view's shadow.
13051            if (isHardwareAccelerated() && getZ() != 0) {
13052                damageShadowReceiver();
13053            }
13054        }
13055    }
13056
13057    /**
13058     * @return this view's projection receiver, or {@code null} if none exists
13059     */
13060    private View getProjectionReceiver() {
13061        ViewParent p = getParent();
13062        while (p != null && p instanceof View) {
13063            final View v = (View) p;
13064            if (v.isProjectionReceiver()) {
13065                return v;
13066            }
13067            p = p.getParent();
13068        }
13069
13070        return null;
13071    }
13072
13073    /**
13074     * @return whether the view is a projection receiver
13075     */
13076    private boolean isProjectionReceiver() {
13077        return mBackground != null;
13078    }
13079
13080    /**
13081     * Damage area of the screen that can be covered by this View's shadow.
13082     *
13083     * This method will guarantee that any changes to shadows cast by a View
13084     * are damaged on the screen for future redraw.
13085     */
13086    private void damageShadowReceiver() {
13087        final AttachInfo ai = mAttachInfo;
13088        if (ai != null) {
13089            ViewParent p = getParent();
13090            if (p != null && p instanceof ViewGroup) {
13091                final ViewGroup vg = (ViewGroup) p;
13092                vg.damageInParent();
13093            }
13094        }
13095    }
13096
13097    /**
13098     * Quick invalidation for View property changes (alpha, translationXY, etc.). We don't want to
13099     * set any flags or handle all of the cases handled by the default invalidation methods.
13100     * Instead, we just want to schedule a traversal in ViewRootImpl with the appropriate
13101     * dirty rect. This method calls into fast invalidation methods in ViewGroup that
13102     * walk up the hierarchy, transforming the dirty rect as necessary.
13103     *
13104     * The method also handles normal invalidation logic if display list properties are not
13105     * being used in this view. The invalidateParent and forceRedraw flags are used by that
13106     * backup approach, to handle these cases used in the various property-setting methods.
13107     *
13108     * @param invalidateParent Force a call to invalidateParentCaches() if display list properties
13109     * are not being used in this view
13110     * @param forceRedraw Mark the view as DRAWN to force the invalidation to propagate, if display
13111     * list properties are not being used in this view
13112     */
13113    void invalidateViewProperty(boolean invalidateParent, boolean forceRedraw) {
13114        if (!isHardwareAccelerated()
13115                || !mRenderNode.isValid()
13116                || (mPrivateFlags & PFLAG_DRAW_ANIMATION) != 0) {
13117            if (invalidateParent) {
13118                invalidateParentCaches();
13119            }
13120            if (forceRedraw) {
13121                mPrivateFlags |= PFLAG_DRAWN; // force another invalidation with the new orientation
13122            }
13123            invalidate(false);
13124        } else {
13125            damageInParent();
13126        }
13127        if (isHardwareAccelerated() && invalidateParent && getZ() != 0) {
13128            damageShadowReceiver();
13129        }
13130    }
13131
13132    /**
13133     * Tells the parent view to damage this view's bounds.
13134     *
13135     * @hide
13136     */
13137    protected void damageInParent() {
13138        final AttachInfo ai = mAttachInfo;
13139        final ViewParent p = mParent;
13140        if (p != null && ai != null) {
13141            final Rect r = ai.mTmpInvalRect;
13142            r.set(0, 0, mRight - mLeft, mBottom - mTop);
13143            if (mParent instanceof ViewGroup) {
13144                ((ViewGroup) mParent).damageChild(this, r);
13145            } else {
13146                mParent.invalidateChild(this, r);
13147            }
13148        }
13149    }
13150
13151    /**
13152     * Utility method to transform a given Rect by the current matrix of this view.
13153     */
13154    void transformRect(final Rect rect) {
13155        if (!getMatrix().isIdentity()) {
13156            RectF boundingRect = mAttachInfo.mTmpTransformRect;
13157            boundingRect.set(rect);
13158            getMatrix().mapRect(boundingRect);
13159            rect.set((int) Math.floor(boundingRect.left),
13160                    (int) Math.floor(boundingRect.top),
13161                    (int) Math.ceil(boundingRect.right),
13162                    (int) Math.ceil(boundingRect.bottom));
13163        }
13164    }
13165
13166    /**
13167     * Used to indicate that the parent of this view should clear its caches. This functionality
13168     * is used to force the parent to rebuild its display list (when hardware-accelerated),
13169     * which is necessary when various parent-managed properties of the view change, such as
13170     * alpha, translationX/Y, scrollX/Y, scaleX/Y, and rotation/X/Y. This method only
13171     * clears the parent caches and does not causes an invalidate event.
13172     *
13173     * @hide
13174     */
13175    protected void invalidateParentCaches() {
13176        if (mParent instanceof View) {
13177            ((View) mParent).mPrivateFlags |= PFLAG_INVALIDATED;
13178        }
13179    }
13180
13181    /**
13182     * Used to indicate that the parent of this view should be invalidated. This functionality
13183     * is used to force the parent to rebuild its display list (when hardware-accelerated),
13184     * which is necessary when various parent-managed properties of the view change, such as
13185     * alpha, translationX/Y, scrollX/Y, scaleX/Y, and rotation/X/Y. This method will propagate
13186     * an invalidation event to the parent.
13187     *
13188     * @hide
13189     */
13190    protected void invalidateParentIfNeeded() {
13191        if (isHardwareAccelerated() && mParent instanceof View) {
13192            ((View) mParent).invalidate(true);
13193        }
13194    }
13195
13196    /**
13197     * @hide
13198     */
13199    protected void invalidateParentIfNeededAndWasQuickRejected() {
13200        if ((mPrivateFlags2 & PFLAG2_VIEW_QUICK_REJECTED) != 0) {
13201            // View was rejected last time it was drawn by its parent; this may have changed
13202            invalidateParentIfNeeded();
13203        }
13204    }
13205
13206    /**
13207     * Indicates whether this View is opaque. An opaque View guarantees that it will
13208     * draw all the pixels overlapping its bounds using a fully opaque color.
13209     *
13210     * Subclasses of View should override this method whenever possible to indicate
13211     * whether an instance is opaque. Opaque Views are treated in a special way by
13212     * the View hierarchy, possibly allowing it to perform optimizations during
13213     * invalidate/draw passes.
13214     *
13215     * @return True if this View is guaranteed to be fully opaque, false otherwise.
13216     */
13217    @ViewDebug.ExportedProperty(category = "drawing")
13218    public boolean isOpaque() {
13219        return (mPrivateFlags & PFLAG_OPAQUE_MASK) == PFLAG_OPAQUE_MASK &&
13220                getFinalAlpha() >= 1.0f;
13221    }
13222
13223    /**
13224     * @hide
13225     */
13226    protected void computeOpaqueFlags() {
13227        // Opaque if:
13228        //   - Has a background
13229        //   - Background is opaque
13230        //   - Doesn't have scrollbars or scrollbars overlay
13231
13232        if (mBackground != null && mBackground.getOpacity() == PixelFormat.OPAQUE) {
13233            mPrivateFlags |= PFLAG_OPAQUE_BACKGROUND;
13234        } else {
13235            mPrivateFlags &= ~PFLAG_OPAQUE_BACKGROUND;
13236        }
13237
13238        final int flags = mViewFlags;
13239        if (((flags & SCROLLBARS_VERTICAL) == 0 && (flags & SCROLLBARS_HORIZONTAL) == 0) ||
13240                (flags & SCROLLBARS_STYLE_MASK) == SCROLLBARS_INSIDE_OVERLAY ||
13241                (flags & SCROLLBARS_STYLE_MASK) == SCROLLBARS_OUTSIDE_OVERLAY) {
13242            mPrivateFlags |= PFLAG_OPAQUE_SCROLLBARS;
13243        } else {
13244            mPrivateFlags &= ~PFLAG_OPAQUE_SCROLLBARS;
13245        }
13246    }
13247
13248    /**
13249     * @hide
13250     */
13251    protected boolean hasOpaqueScrollbars() {
13252        return (mPrivateFlags & PFLAG_OPAQUE_SCROLLBARS) == PFLAG_OPAQUE_SCROLLBARS;
13253    }
13254
13255    /**
13256     * @return A handler associated with the thread running the View. This
13257     * handler can be used to pump events in the UI events queue.
13258     */
13259    public Handler getHandler() {
13260        final AttachInfo attachInfo = mAttachInfo;
13261        if (attachInfo != null) {
13262            return attachInfo.mHandler;
13263        }
13264        return null;
13265    }
13266
13267    /**
13268     * Returns the queue of runnable for this view.
13269     *
13270     * @return the queue of runnables for this view
13271     */
13272    private HandlerActionQueue getRunQueue() {
13273        if (mRunQueue == null) {
13274            mRunQueue = new HandlerActionQueue();
13275        }
13276        return mRunQueue;
13277    }
13278
13279    /**
13280     * Gets the view root associated with the View.
13281     * @return The view root, or null if none.
13282     * @hide
13283     */
13284    public ViewRootImpl getViewRootImpl() {
13285        if (mAttachInfo != null) {
13286            return mAttachInfo.mViewRootImpl;
13287        }
13288        return null;
13289    }
13290
13291    /**
13292     * @hide
13293     */
13294    public ThreadedRenderer getHardwareRenderer() {
13295        return mAttachInfo != null ? mAttachInfo.mHardwareRenderer : null;
13296    }
13297
13298    /**
13299     * <p>Causes the Runnable to be added to the message queue.
13300     * The runnable will be run on the user interface thread.</p>
13301     *
13302     * @param action The Runnable that will be executed.
13303     *
13304     * @return Returns true if the Runnable was successfully placed in to the
13305     *         message queue.  Returns false on failure, usually because the
13306     *         looper processing the message queue is exiting.
13307     *
13308     * @see #postDelayed
13309     * @see #removeCallbacks
13310     */
13311    public boolean post(Runnable action) {
13312        final AttachInfo attachInfo = mAttachInfo;
13313        if (attachInfo != null) {
13314            return attachInfo.mHandler.post(action);
13315        }
13316
13317        // Postpone the runnable until we know on which thread it needs to run.
13318        // Assume that the runnable will be successfully placed after attach.
13319        getRunQueue().post(action);
13320        return true;
13321    }
13322
13323    /**
13324     * <p>Causes the Runnable to be added to the message queue, to be run
13325     * after the specified amount of time elapses.
13326     * The runnable will be run on the user interface thread.</p>
13327     *
13328     * @param action The Runnable that will be executed.
13329     * @param delayMillis The delay (in milliseconds) until the Runnable
13330     *        will be executed.
13331     *
13332     * @return true if the Runnable was successfully placed in to the
13333     *         message queue.  Returns false on failure, usually because the
13334     *         looper processing the message queue is exiting.  Note that a
13335     *         result of true does not mean the Runnable will be processed --
13336     *         if the looper is quit before the delivery time of the message
13337     *         occurs then the message will be dropped.
13338     *
13339     * @see #post
13340     * @see #removeCallbacks
13341     */
13342    public boolean postDelayed(Runnable action, long delayMillis) {
13343        final AttachInfo attachInfo = mAttachInfo;
13344        if (attachInfo != null) {
13345            return attachInfo.mHandler.postDelayed(action, delayMillis);
13346        }
13347
13348        // Postpone the runnable until we know on which thread it needs to run.
13349        // Assume that the runnable will be successfully placed after attach.
13350        getRunQueue().postDelayed(action, delayMillis);
13351        return true;
13352    }
13353
13354    /**
13355     * <p>Causes the Runnable to execute on the next animation time step.
13356     * The runnable will be run on the user interface thread.</p>
13357     *
13358     * @param action The Runnable that will be executed.
13359     *
13360     * @see #postOnAnimationDelayed
13361     * @see #removeCallbacks
13362     */
13363    public void postOnAnimation(Runnable action) {
13364        final AttachInfo attachInfo = mAttachInfo;
13365        if (attachInfo != null) {
13366            attachInfo.mViewRootImpl.mChoreographer.postCallback(
13367                    Choreographer.CALLBACK_ANIMATION, action, null);
13368        } else {
13369            // Postpone the runnable until we know
13370            // on which thread it needs to run.
13371            getRunQueue().post(action);
13372        }
13373    }
13374
13375    /**
13376     * <p>Causes the Runnable to execute on the next animation time step,
13377     * after the specified amount of time elapses.
13378     * The runnable will be run on the user interface thread.</p>
13379     *
13380     * @param action The Runnable that will be executed.
13381     * @param delayMillis The delay (in milliseconds) until the Runnable
13382     *        will be executed.
13383     *
13384     * @see #postOnAnimation
13385     * @see #removeCallbacks
13386     */
13387    public void postOnAnimationDelayed(Runnable action, long delayMillis) {
13388        final AttachInfo attachInfo = mAttachInfo;
13389        if (attachInfo != null) {
13390            attachInfo.mViewRootImpl.mChoreographer.postCallbackDelayed(
13391                    Choreographer.CALLBACK_ANIMATION, action, null, delayMillis);
13392        } else {
13393            // Postpone the runnable until we know
13394            // on which thread it needs to run.
13395            getRunQueue().postDelayed(action, delayMillis);
13396        }
13397    }
13398
13399    /**
13400     * <p>Removes the specified Runnable from the message queue.</p>
13401     *
13402     * @param action The Runnable to remove from the message handling queue
13403     *
13404     * @return true if this view could ask the Handler to remove the Runnable,
13405     *         false otherwise. When the returned value is true, the Runnable
13406     *         may or may not have been actually removed from the message queue
13407     *         (for instance, if the Runnable was not in the queue already.)
13408     *
13409     * @see #post
13410     * @see #postDelayed
13411     * @see #postOnAnimation
13412     * @see #postOnAnimationDelayed
13413     */
13414    public boolean removeCallbacks(Runnable action) {
13415        if (action != null) {
13416            final AttachInfo attachInfo = mAttachInfo;
13417            if (attachInfo != null) {
13418                attachInfo.mHandler.removeCallbacks(action);
13419                attachInfo.mViewRootImpl.mChoreographer.removeCallbacks(
13420                        Choreographer.CALLBACK_ANIMATION, action, null);
13421            }
13422            getRunQueue().removeCallbacks(action);
13423        }
13424        return true;
13425    }
13426
13427    /**
13428     * <p>Cause an invalidate to happen on a subsequent cycle through the event loop.
13429     * Use this to invalidate the View from a non-UI thread.</p>
13430     *
13431     * <p>This method can be invoked from outside of the UI thread
13432     * only when this View is attached to a window.</p>
13433     *
13434     * @see #invalidate()
13435     * @see #postInvalidateDelayed(long)
13436     */
13437    public void postInvalidate() {
13438        postInvalidateDelayed(0);
13439    }
13440
13441    /**
13442     * <p>Cause an invalidate of the specified area to happen on a subsequent cycle
13443     * through the event loop. Use this to invalidate the View from a non-UI thread.</p>
13444     *
13445     * <p>This method can be invoked from outside of the UI thread
13446     * only when this View is attached to a window.</p>
13447     *
13448     * @param left The left coordinate of the rectangle to invalidate.
13449     * @param top The top coordinate of the rectangle to invalidate.
13450     * @param right The right coordinate of the rectangle to invalidate.
13451     * @param bottom The bottom coordinate of the rectangle to invalidate.
13452     *
13453     * @see #invalidate(int, int, int, int)
13454     * @see #invalidate(Rect)
13455     * @see #postInvalidateDelayed(long, int, int, int, int)
13456     */
13457    public void postInvalidate(int left, int top, int right, int bottom) {
13458        postInvalidateDelayed(0, left, top, right, bottom);
13459    }
13460
13461    /**
13462     * <p>Cause an invalidate to happen on a subsequent cycle through the event
13463     * loop. Waits for the specified amount of time.</p>
13464     *
13465     * <p>This method can be invoked from outside of the UI thread
13466     * only when this View is attached to a window.</p>
13467     *
13468     * @param delayMilliseconds the duration in milliseconds to delay the
13469     *         invalidation by
13470     *
13471     * @see #invalidate()
13472     * @see #postInvalidate()
13473     */
13474    public void postInvalidateDelayed(long delayMilliseconds) {
13475        // We try only with the AttachInfo because there's no point in invalidating
13476        // if we are not attached to our window
13477        final AttachInfo attachInfo = mAttachInfo;
13478        if (attachInfo != null) {
13479            attachInfo.mViewRootImpl.dispatchInvalidateDelayed(this, delayMilliseconds);
13480        }
13481    }
13482
13483    /**
13484     * <p>Cause an invalidate of the specified area to happen on a subsequent cycle
13485     * through the event loop. Waits for the specified amount of time.</p>
13486     *
13487     * <p>This method can be invoked from outside of the UI thread
13488     * only when this View is attached to a window.</p>
13489     *
13490     * @param delayMilliseconds the duration in milliseconds to delay the
13491     *         invalidation by
13492     * @param left The left coordinate of the rectangle to invalidate.
13493     * @param top The top coordinate of the rectangle to invalidate.
13494     * @param right The right coordinate of the rectangle to invalidate.
13495     * @param bottom The bottom coordinate of the rectangle to invalidate.
13496     *
13497     * @see #invalidate(int, int, int, int)
13498     * @see #invalidate(Rect)
13499     * @see #postInvalidate(int, int, int, int)
13500     */
13501    public void postInvalidateDelayed(long delayMilliseconds, int left, int top,
13502            int right, int bottom) {
13503
13504        // We try only with the AttachInfo because there's no point in invalidating
13505        // if we are not attached to our window
13506        final AttachInfo attachInfo = mAttachInfo;
13507        if (attachInfo != null) {
13508            final AttachInfo.InvalidateInfo info = AttachInfo.InvalidateInfo.obtain();
13509            info.target = this;
13510            info.left = left;
13511            info.top = top;
13512            info.right = right;
13513            info.bottom = bottom;
13514
13515            attachInfo.mViewRootImpl.dispatchInvalidateRectDelayed(info, delayMilliseconds);
13516        }
13517    }
13518
13519    /**
13520     * <p>Cause an invalidate to happen on the next animation time step, typically the
13521     * next display frame.</p>
13522     *
13523     * <p>This method can be invoked from outside of the UI thread
13524     * only when this View is attached to a window.</p>
13525     *
13526     * @see #invalidate()
13527     */
13528    public void postInvalidateOnAnimation() {
13529        // We try only with the AttachInfo because there's no point in invalidating
13530        // if we are not attached to our window
13531        final AttachInfo attachInfo = mAttachInfo;
13532        if (attachInfo != null) {
13533            attachInfo.mViewRootImpl.dispatchInvalidateOnAnimation(this);
13534        }
13535    }
13536
13537    /**
13538     * <p>Cause an invalidate of the specified area to happen on the next animation
13539     * time step, typically the next display frame.</p>
13540     *
13541     * <p>This method can be invoked from outside of the UI thread
13542     * only when this View is attached to a window.</p>
13543     *
13544     * @param left The left coordinate of the rectangle to invalidate.
13545     * @param top The top coordinate of the rectangle to invalidate.
13546     * @param right The right coordinate of the rectangle to invalidate.
13547     * @param bottom The bottom coordinate of the rectangle to invalidate.
13548     *
13549     * @see #invalidate(int, int, int, int)
13550     * @see #invalidate(Rect)
13551     */
13552    public void postInvalidateOnAnimation(int left, int top, int right, int bottom) {
13553        // We try only with the AttachInfo because there's no point in invalidating
13554        // if we are not attached to our window
13555        final AttachInfo attachInfo = mAttachInfo;
13556        if (attachInfo != null) {
13557            final AttachInfo.InvalidateInfo info = AttachInfo.InvalidateInfo.obtain();
13558            info.target = this;
13559            info.left = left;
13560            info.top = top;
13561            info.right = right;
13562            info.bottom = bottom;
13563
13564            attachInfo.mViewRootImpl.dispatchInvalidateRectOnAnimation(info);
13565        }
13566    }
13567
13568    /**
13569     * Post a callback to send a {@link AccessibilityEvent#TYPE_VIEW_SCROLLED} event.
13570     * This event is sent at most once every
13571     * {@link ViewConfiguration#getSendRecurringAccessibilityEventsInterval()}.
13572     */
13573    private void postSendViewScrolledAccessibilityEventCallback() {
13574        if (mSendViewScrolledAccessibilityEvent == null) {
13575            mSendViewScrolledAccessibilityEvent = new SendViewScrolledAccessibilityEvent();
13576        }
13577        if (!mSendViewScrolledAccessibilityEvent.mIsPending) {
13578            mSendViewScrolledAccessibilityEvent.mIsPending = true;
13579            postDelayed(mSendViewScrolledAccessibilityEvent,
13580                    ViewConfiguration.getSendRecurringAccessibilityEventsInterval());
13581        }
13582    }
13583
13584    /**
13585     * Called by a parent to request that a child update its values for mScrollX
13586     * and mScrollY if necessary. This will typically be done if the child is
13587     * animating a scroll using a {@link android.widget.Scroller Scroller}
13588     * object.
13589     */
13590    public void computeScroll() {
13591    }
13592
13593    /**
13594     * <p>Indicate whether the horizontal edges are faded when the view is
13595     * scrolled horizontally.</p>
13596     *
13597     * @return true if the horizontal edges should are faded on scroll, false
13598     *         otherwise
13599     *
13600     * @see #setHorizontalFadingEdgeEnabled(boolean)
13601     *
13602     * @attr ref android.R.styleable#View_requiresFadingEdge
13603     */
13604    public boolean isHorizontalFadingEdgeEnabled() {
13605        return (mViewFlags & FADING_EDGE_HORIZONTAL) == FADING_EDGE_HORIZONTAL;
13606    }
13607
13608    /**
13609     * <p>Define whether the horizontal edges should be faded when this view
13610     * is scrolled horizontally.</p>
13611     *
13612     * @param horizontalFadingEdgeEnabled true if the horizontal edges should
13613     *                                    be faded when the view is scrolled
13614     *                                    horizontally
13615     *
13616     * @see #isHorizontalFadingEdgeEnabled()
13617     *
13618     * @attr ref android.R.styleable#View_requiresFadingEdge
13619     */
13620    public void setHorizontalFadingEdgeEnabled(boolean horizontalFadingEdgeEnabled) {
13621        if (isHorizontalFadingEdgeEnabled() != horizontalFadingEdgeEnabled) {
13622            if (horizontalFadingEdgeEnabled) {
13623                initScrollCache();
13624            }
13625
13626            mViewFlags ^= FADING_EDGE_HORIZONTAL;
13627        }
13628    }
13629
13630    /**
13631     * <p>Indicate whether the vertical edges are faded when the view is
13632     * scrolled horizontally.</p>
13633     *
13634     * @return true if the vertical edges should are faded on scroll, false
13635     *         otherwise
13636     *
13637     * @see #setVerticalFadingEdgeEnabled(boolean)
13638     *
13639     * @attr ref android.R.styleable#View_requiresFadingEdge
13640     */
13641    public boolean isVerticalFadingEdgeEnabled() {
13642        return (mViewFlags & FADING_EDGE_VERTICAL) == FADING_EDGE_VERTICAL;
13643    }
13644
13645    /**
13646     * <p>Define whether the vertical edges should be faded when this view
13647     * is scrolled vertically.</p>
13648     *
13649     * @param verticalFadingEdgeEnabled true if the vertical edges should
13650     *                                  be faded when the view is scrolled
13651     *                                  vertically
13652     *
13653     * @see #isVerticalFadingEdgeEnabled()
13654     *
13655     * @attr ref android.R.styleable#View_requiresFadingEdge
13656     */
13657    public void setVerticalFadingEdgeEnabled(boolean verticalFadingEdgeEnabled) {
13658        if (isVerticalFadingEdgeEnabled() != verticalFadingEdgeEnabled) {
13659            if (verticalFadingEdgeEnabled) {
13660                initScrollCache();
13661            }
13662
13663            mViewFlags ^= FADING_EDGE_VERTICAL;
13664        }
13665    }
13666
13667    /**
13668     * Returns the strength, or intensity, of the top faded edge. The strength is
13669     * a value between 0.0 (no fade) and 1.0 (full fade). The default implementation
13670     * returns 0.0 or 1.0 but no value in between.
13671     *
13672     * Subclasses should override this method to provide a smoother fade transition
13673     * when scrolling occurs.
13674     *
13675     * @return the intensity of the top fade as a float between 0.0f and 1.0f
13676     */
13677    protected float getTopFadingEdgeStrength() {
13678        return computeVerticalScrollOffset() > 0 ? 1.0f : 0.0f;
13679    }
13680
13681    /**
13682     * Returns the strength, or intensity, of the bottom faded edge. The strength is
13683     * a value between 0.0 (no fade) and 1.0 (full fade). The default implementation
13684     * returns 0.0 or 1.0 but no value in between.
13685     *
13686     * Subclasses should override this method to provide a smoother fade transition
13687     * when scrolling occurs.
13688     *
13689     * @return the intensity of the bottom fade as a float between 0.0f and 1.0f
13690     */
13691    protected float getBottomFadingEdgeStrength() {
13692        return computeVerticalScrollOffset() + computeVerticalScrollExtent() <
13693                computeVerticalScrollRange() ? 1.0f : 0.0f;
13694    }
13695
13696    /**
13697     * Returns the strength, or intensity, of the left faded edge. The strength is
13698     * a value between 0.0 (no fade) and 1.0 (full fade). The default implementation
13699     * returns 0.0 or 1.0 but no value in between.
13700     *
13701     * Subclasses should override this method to provide a smoother fade transition
13702     * when scrolling occurs.
13703     *
13704     * @return the intensity of the left fade as a float between 0.0f and 1.0f
13705     */
13706    protected float getLeftFadingEdgeStrength() {
13707        return computeHorizontalScrollOffset() > 0 ? 1.0f : 0.0f;
13708    }
13709
13710    /**
13711     * Returns the strength, or intensity, of the right faded edge. The strength is
13712     * a value between 0.0 (no fade) and 1.0 (full fade). The default implementation
13713     * returns 0.0 or 1.0 but no value in between.
13714     *
13715     * Subclasses should override this method to provide a smoother fade transition
13716     * when scrolling occurs.
13717     *
13718     * @return the intensity of the right fade as a float between 0.0f and 1.0f
13719     */
13720    protected float getRightFadingEdgeStrength() {
13721        return computeHorizontalScrollOffset() + computeHorizontalScrollExtent() <
13722                computeHorizontalScrollRange() ? 1.0f : 0.0f;
13723    }
13724
13725    /**
13726     * <p>Indicate whether the horizontal scrollbar should be drawn or not. The
13727     * scrollbar is not drawn by default.</p>
13728     *
13729     * @return true if the horizontal scrollbar should be painted, false
13730     *         otherwise
13731     *
13732     * @see #setHorizontalScrollBarEnabled(boolean)
13733     */
13734    public boolean isHorizontalScrollBarEnabled() {
13735        return (mViewFlags & SCROLLBARS_HORIZONTAL) == SCROLLBARS_HORIZONTAL;
13736    }
13737
13738    /**
13739     * <p>Define whether the horizontal scrollbar should be drawn or not. The
13740     * scrollbar is not drawn by default.</p>
13741     *
13742     * @param horizontalScrollBarEnabled true if the horizontal scrollbar should
13743     *                                   be painted
13744     *
13745     * @see #isHorizontalScrollBarEnabled()
13746     */
13747    public void setHorizontalScrollBarEnabled(boolean horizontalScrollBarEnabled) {
13748        if (isHorizontalScrollBarEnabled() != horizontalScrollBarEnabled) {
13749            mViewFlags ^= SCROLLBARS_HORIZONTAL;
13750            computeOpaqueFlags();
13751            resolvePadding();
13752        }
13753    }
13754
13755    /**
13756     * <p>Indicate whether the vertical scrollbar should be drawn or not. The
13757     * scrollbar is not drawn by default.</p>
13758     *
13759     * @return true if the vertical scrollbar should be painted, false
13760     *         otherwise
13761     *
13762     * @see #setVerticalScrollBarEnabled(boolean)
13763     */
13764    public boolean isVerticalScrollBarEnabled() {
13765        return (mViewFlags & SCROLLBARS_VERTICAL) == SCROLLBARS_VERTICAL;
13766    }
13767
13768    /**
13769     * <p>Define whether the vertical scrollbar should be drawn or not. The
13770     * scrollbar is not drawn by default.</p>
13771     *
13772     * @param verticalScrollBarEnabled true if the vertical scrollbar should
13773     *                                 be painted
13774     *
13775     * @see #isVerticalScrollBarEnabled()
13776     */
13777    public void setVerticalScrollBarEnabled(boolean verticalScrollBarEnabled) {
13778        if (isVerticalScrollBarEnabled() != verticalScrollBarEnabled) {
13779            mViewFlags ^= SCROLLBARS_VERTICAL;
13780            computeOpaqueFlags();
13781            resolvePadding();
13782        }
13783    }
13784
13785    /**
13786     * @hide
13787     */
13788    protected void recomputePadding() {
13789        internalSetPadding(mUserPaddingLeft, mPaddingTop, mUserPaddingRight, mUserPaddingBottom);
13790    }
13791
13792    /**
13793     * Define whether scrollbars will fade when the view is not scrolling.
13794     *
13795     * @param fadeScrollbars whether to enable fading
13796     *
13797     * @attr ref android.R.styleable#View_fadeScrollbars
13798     */
13799    public void setScrollbarFadingEnabled(boolean fadeScrollbars) {
13800        initScrollCache();
13801        final ScrollabilityCache scrollabilityCache = mScrollCache;
13802        scrollabilityCache.fadeScrollBars = fadeScrollbars;
13803        if (fadeScrollbars) {
13804            scrollabilityCache.state = ScrollabilityCache.OFF;
13805        } else {
13806            scrollabilityCache.state = ScrollabilityCache.ON;
13807        }
13808    }
13809
13810    /**
13811     *
13812     * Returns true if scrollbars will fade when this view is not scrolling
13813     *
13814     * @return true if scrollbar fading is enabled
13815     *
13816     * @attr ref android.R.styleable#View_fadeScrollbars
13817     */
13818    public boolean isScrollbarFadingEnabled() {
13819        return mScrollCache != null && mScrollCache.fadeScrollBars;
13820    }
13821
13822    /**
13823     *
13824     * Returns the delay before scrollbars fade.
13825     *
13826     * @return the delay before scrollbars fade
13827     *
13828     * @attr ref android.R.styleable#View_scrollbarDefaultDelayBeforeFade
13829     */
13830    public int getScrollBarDefaultDelayBeforeFade() {
13831        return mScrollCache == null ? ViewConfiguration.getScrollDefaultDelay() :
13832                mScrollCache.scrollBarDefaultDelayBeforeFade;
13833    }
13834
13835    /**
13836     * Define the delay before scrollbars fade.
13837     *
13838     * @param scrollBarDefaultDelayBeforeFade - the delay before scrollbars fade
13839     *
13840     * @attr ref android.R.styleable#View_scrollbarDefaultDelayBeforeFade
13841     */
13842    public void setScrollBarDefaultDelayBeforeFade(int scrollBarDefaultDelayBeforeFade) {
13843        getScrollCache().scrollBarDefaultDelayBeforeFade = scrollBarDefaultDelayBeforeFade;
13844    }
13845
13846    /**
13847     *
13848     * Returns the scrollbar fade duration.
13849     *
13850     * @return the scrollbar fade duration
13851     *
13852     * @attr ref android.R.styleable#View_scrollbarFadeDuration
13853     */
13854    public int getScrollBarFadeDuration() {
13855        return mScrollCache == null ? ViewConfiguration.getScrollBarFadeDuration() :
13856                mScrollCache.scrollBarFadeDuration;
13857    }
13858
13859    /**
13860     * Define the scrollbar fade duration.
13861     *
13862     * @param scrollBarFadeDuration - the scrollbar fade duration
13863     *
13864     * @attr ref android.R.styleable#View_scrollbarFadeDuration
13865     */
13866    public void setScrollBarFadeDuration(int scrollBarFadeDuration) {
13867        getScrollCache().scrollBarFadeDuration = scrollBarFadeDuration;
13868    }
13869
13870    /**
13871     *
13872     * Returns the scrollbar size.
13873     *
13874     * @return the scrollbar size
13875     *
13876     * @attr ref android.R.styleable#View_scrollbarSize
13877     */
13878    public int getScrollBarSize() {
13879        return mScrollCache == null ? ViewConfiguration.get(mContext).getScaledScrollBarSize() :
13880                mScrollCache.scrollBarSize;
13881    }
13882
13883    /**
13884     * Define the scrollbar size.
13885     *
13886     * @param scrollBarSize - the scrollbar size
13887     *
13888     * @attr ref android.R.styleable#View_scrollbarSize
13889     */
13890    public void setScrollBarSize(int scrollBarSize) {
13891        getScrollCache().scrollBarSize = scrollBarSize;
13892    }
13893
13894    /**
13895     * <p>Specify the style of the scrollbars. The scrollbars can be overlaid or
13896     * inset. When inset, they add to the padding of the view. And the scrollbars
13897     * can be drawn inside the padding area or on the edge of the view. For example,
13898     * if a view has a background drawable and you want to draw the scrollbars
13899     * inside the padding specified by the drawable, you can use
13900     * SCROLLBARS_INSIDE_OVERLAY or SCROLLBARS_INSIDE_INSET. If you want them to
13901     * appear at the edge of the view, ignoring the padding, then you can use
13902     * SCROLLBARS_OUTSIDE_OVERLAY or SCROLLBARS_OUTSIDE_INSET.</p>
13903     * @param style the style of the scrollbars. Should be one of
13904     * SCROLLBARS_INSIDE_OVERLAY, SCROLLBARS_INSIDE_INSET,
13905     * SCROLLBARS_OUTSIDE_OVERLAY or SCROLLBARS_OUTSIDE_INSET.
13906     * @see #SCROLLBARS_INSIDE_OVERLAY
13907     * @see #SCROLLBARS_INSIDE_INSET
13908     * @see #SCROLLBARS_OUTSIDE_OVERLAY
13909     * @see #SCROLLBARS_OUTSIDE_INSET
13910     *
13911     * @attr ref android.R.styleable#View_scrollbarStyle
13912     */
13913    public void setScrollBarStyle(@ScrollBarStyle int style) {
13914        if (style != (mViewFlags & SCROLLBARS_STYLE_MASK)) {
13915            mViewFlags = (mViewFlags & ~SCROLLBARS_STYLE_MASK) | (style & SCROLLBARS_STYLE_MASK);
13916            computeOpaqueFlags();
13917            resolvePadding();
13918        }
13919    }
13920
13921    /**
13922     * <p>Returns the current scrollbar style.</p>
13923     * @return the current scrollbar style
13924     * @see #SCROLLBARS_INSIDE_OVERLAY
13925     * @see #SCROLLBARS_INSIDE_INSET
13926     * @see #SCROLLBARS_OUTSIDE_OVERLAY
13927     * @see #SCROLLBARS_OUTSIDE_INSET
13928     *
13929     * @attr ref android.R.styleable#View_scrollbarStyle
13930     */
13931    @ViewDebug.ExportedProperty(mapping = {
13932            @ViewDebug.IntToString(from = SCROLLBARS_INSIDE_OVERLAY, to = "INSIDE_OVERLAY"),
13933            @ViewDebug.IntToString(from = SCROLLBARS_INSIDE_INSET, to = "INSIDE_INSET"),
13934            @ViewDebug.IntToString(from = SCROLLBARS_OUTSIDE_OVERLAY, to = "OUTSIDE_OVERLAY"),
13935            @ViewDebug.IntToString(from = SCROLLBARS_OUTSIDE_INSET, to = "OUTSIDE_INSET")
13936    })
13937    @ScrollBarStyle
13938    public int getScrollBarStyle() {
13939        return mViewFlags & SCROLLBARS_STYLE_MASK;
13940    }
13941
13942    /**
13943     * <p>Compute the horizontal range that the horizontal scrollbar
13944     * represents.</p>
13945     *
13946     * <p>The range is expressed in arbitrary units that must be the same as the
13947     * units used by {@link #computeHorizontalScrollExtent()} and
13948     * {@link #computeHorizontalScrollOffset()}.</p>
13949     *
13950     * <p>The default range is the drawing width of this view.</p>
13951     *
13952     * @return the total horizontal range represented by the horizontal
13953     *         scrollbar
13954     *
13955     * @see #computeHorizontalScrollExtent()
13956     * @see #computeHorizontalScrollOffset()
13957     * @see android.widget.ScrollBarDrawable
13958     */
13959    protected int computeHorizontalScrollRange() {
13960        return getWidth();
13961    }
13962
13963    /**
13964     * <p>Compute the horizontal offset of the horizontal scrollbar's thumb
13965     * within the horizontal range. This value is used to compute the position
13966     * of the thumb within the scrollbar's track.</p>
13967     *
13968     * <p>The range is expressed in arbitrary units that must be the same as the
13969     * units used by {@link #computeHorizontalScrollRange()} and
13970     * {@link #computeHorizontalScrollExtent()}.</p>
13971     *
13972     * <p>The default offset is the scroll offset of this view.</p>
13973     *
13974     * @return the horizontal offset of the scrollbar's thumb
13975     *
13976     * @see #computeHorizontalScrollRange()
13977     * @see #computeHorizontalScrollExtent()
13978     * @see android.widget.ScrollBarDrawable
13979     */
13980    protected int computeHorizontalScrollOffset() {
13981        return mScrollX;
13982    }
13983
13984    /**
13985     * <p>Compute the horizontal extent of the horizontal scrollbar's thumb
13986     * within the horizontal range. This value is used to compute the length
13987     * of the thumb within the scrollbar's track.</p>
13988     *
13989     * <p>The range is expressed in arbitrary units that must be the same as the
13990     * units used by {@link #computeHorizontalScrollRange()} and
13991     * {@link #computeHorizontalScrollOffset()}.</p>
13992     *
13993     * <p>The default extent is the drawing width of this view.</p>
13994     *
13995     * @return the horizontal extent of the scrollbar's thumb
13996     *
13997     * @see #computeHorizontalScrollRange()
13998     * @see #computeHorizontalScrollOffset()
13999     * @see android.widget.ScrollBarDrawable
14000     */
14001    protected int computeHorizontalScrollExtent() {
14002        return getWidth();
14003    }
14004
14005    /**
14006     * <p>Compute the vertical range that the vertical scrollbar represents.</p>
14007     *
14008     * <p>The range is expressed in arbitrary units that must be the same as the
14009     * units used by {@link #computeVerticalScrollExtent()} and
14010     * {@link #computeVerticalScrollOffset()}.</p>
14011     *
14012     * @return the total vertical range represented by the vertical scrollbar
14013     *
14014     * <p>The default range is the drawing height of this view.</p>
14015     *
14016     * @see #computeVerticalScrollExtent()
14017     * @see #computeVerticalScrollOffset()
14018     * @see android.widget.ScrollBarDrawable
14019     */
14020    protected int computeVerticalScrollRange() {
14021        return getHeight();
14022    }
14023
14024    /**
14025     * <p>Compute the vertical offset of the vertical scrollbar's thumb
14026     * within the horizontal range. This value is used to compute the position
14027     * of the thumb within the scrollbar's track.</p>
14028     *
14029     * <p>The range is expressed in arbitrary units that must be the same as the
14030     * units used by {@link #computeVerticalScrollRange()} and
14031     * {@link #computeVerticalScrollExtent()}.</p>
14032     *
14033     * <p>The default offset is the scroll offset of this view.</p>
14034     *
14035     * @return the vertical offset of the scrollbar's thumb
14036     *
14037     * @see #computeVerticalScrollRange()
14038     * @see #computeVerticalScrollExtent()
14039     * @see android.widget.ScrollBarDrawable
14040     */
14041    protected int computeVerticalScrollOffset() {
14042        return mScrollY;
14043    }
14044
14045    /**
14046     * <p>Compute the vertical extent of the vertical scrollbar's thumb
14047     * within the vertical range. This value is used to compute the length
14048     * of the thumb within the scrollbar's track.</p>
14049     *
14050     * <p>The range is expressed in arbitrary units that must be the same as the
14051     * units used by {@link #computeVerticalScrollRange()} and
14052     * {@link #computeVerticalScrollOffset()}.</p>
14053     *
14054     * <p>The default extent is the drawing height of this view.</p>
14055     *
14056     * @return the vertical extent of the scrollbar's thumb
14057     *
14058     * @see #computeVerticalScrollRange()
14059     * @see #computeVerticalScrollOffset()
14060     * @see android.widget.ScrollBarDrawable
14061     */
14062    protected int computeVerticalScrollExtent() {
14063        return getHeight();
14064    }
14065
14066    /**
14067     * Check if this view can be scrolled horizontally in a certain direction.
14068     *
14069     * @param direction Negative to check scrolling left, positive to check scrolling right.
14070     * @return true if this view can be scrolled in the specified direction, false otherwise.
14071     */
14072    public boolean canScrollHorizontally(int direction) {
14073        final int offset = computeHorizontalScrollOffset();
14074        final int range = computeHorizontalScrollRange() - computeHorizontalScrollExtent();
14075        if (range == 0) return false;
14076        if (direction < 0) {
14077            return offset > 0;
14078        } else {
14079            return offset < range - 1;
14080        }
14081    }
14082
14083    /**
14084     * Check if this view can be scrolled vertically in a certain direction.
14085     *
14086     * @param direction Negative to check scrolling up, positive to check scrolling down.
14087     * @return true if this view can be scrolled in the specified direction, false otherwise.
14088     */
14089    public boolean canScrollVertically(int direction) {
14090        final int offset = computeVerticalScrollOffset();
14091        final int range = computeVerticalScrollRange() - computeVerticalScrollExtent();
14092        if (range == 0) return false;
14093        if (direction < 0) {
14094            return offset > 0;
14095        } else {
14096            return offset < range - 1;
14097        }
14098    }
14099
14100    void getScrollIndicatorBounds(@NonNull Rect out) {
14101        out.left = mScrollX;
14102        out.right = mScrollX + mRight - mLeft;
14103        out.top = mScrollY;
14104        out.bottom = mScrollY + mBottom - mTop;
14105    }
14106
14107    private void onDrawScrollIndicators(Canvas c) {
14108        if ((mPrivateFlags3 & SCROLL_INDICATORS_PFLAG3_MASK) == 0) {
14109            // No scroll indicators enabled.
14110            return;
14111        }
14112
14113        final Drawable dr = mScrollIndicatorDrawable;
14114        if (dr == null) {
14115            // Scroll indicators aren't supported here.
14116            return;
14117        }
14118
14119        final int h = dr.getIntrinsicHeight();
14120        final int w = dr.getIntrinsicWidth();
14121        final Rect rect = mAttachInfo.mTmpInvalRect;
14122        getScrollIndicatorBounds(rect);
14123
14124        if ((mPrivateFlags3 & PFLAG3_SCROLL_INDICATOR_TOP) != 0) {
14125            final boolean canScrollUp = canScrollVertically(-1);
14126            if (canScrollUp) {
14127                dr.setBounds(rect.left, rect.top, rect.right, rect.top + h);
14128                dr.draw(c);
14129            }
14130        }
14131
14132        if ((mPrivateFlags3 & PFLAG3_SCROLL_INDICATOR_BOTTOM) != 0) {
14133            final boolean canScrollDown = canScrollVertically(1);
14134            if (canScrollDown) {
14135                dr.setBounds(rect.left, rect.bottom - h, rect.right, rect.bottom);
14136                dr.draw(c);
14137            }
14138        }
14139
14140        final int leftRtl;
14141        final int rightRtl;
14142        if (getLayoutDirection() == LAYOUT_DIRECTION_RTL) {
14143            leftRtl = PFLAG3_SCROLL_INDICATOR_END;
14144            rightRtl = PFLAG3_SCROLL_INDICATOR_START;
14145        } else {
14146            leftRtl = PFLAG3_SCROLL_INDICATOR_START;
14147            rightRtl = PFLAG3_SCROLL_INDICATOR_END;
14148        }
14149
14150        final int leftMask = PFLAG3_SCROLL_INDICATOR_LEFT | leftRtl;
14151        if ((mPrivateFlags3 & leftMask) != 0) {
14152            final boolean canScrollLeft = canScrollHorizontally(-1);
14153            if (canScrollLeft) {
14154                dr.setBounds(rect.left, rect.top, rect.left + w, rect.bottom);
14155                dr.draw(c);
14156            }
14157        }
14158
14159        final int rightMask = PFLAG3_SCROLL_INDICATOR_RIGHT | rightRtl;
14160        if ((mPrivateFlags3 & rightMask) != 0) {
14161            final boolean canScrollRight = canScrollHorizontally(1);
14162            if (canScrollRight) {
14163                dr.setBounds(rect.right - w, rect.top, rect.right, rect.bottom);
14164                dr.draw(c);
14165            }
14166        }
14167    }
14168
14169    /**
14170     * <p>Request the drawing of the horizontal and the vertical scrollbar. The
14171     * scrollbars are painted only if they have been awakened first.</p>
14172     *
14173     * @param canvas the canvas on which to draw the scrollbars
14174     *
14175     * @see #awakenScrollBars(int)
14176     */
14177    protected final void onDrawScrollBars(Canvas canvas) {
14178        // scrollbars are drawn only when the animation is running
14179        final ScrollabilityCache cache = mScrollCache;
14180        if (cache != null) {
14181
14182            int state = cache.state;
14183
14184            if (state == ScrollabilityCache.OFF) {
14185                return;
14186            }
14187
14188            boolean invalidate = false;
14189
14190            if (state == ScrollabilityCache.FADING) {
14191                // We're fading -- get our fade interpolation
14192                if (cache.interpolatorValues == null) {
14193                    cache.interpolatorValues = new float[1];
14194                }
14195
14196                float[] values = cache.interpolatorValues;
14197
14198                // Stops the animation if we're done
14199                if (cache.scrollBarInterpolator.timeToValues(values) ==
14200                        Interpolator.Result.FREEZE_END) {
14201                    cache.state = ScrollabilityCache.OFF;
14202                } else {
14203                    cache.scrollBar.mutate().setAlpha(Math.round(values[0]));
14204                }
14205
14206                // This will make the scroll bars inval themselves after
14207                // drawing. We only want this when we're fading so that
14208                // we prevent excessive redraws
14209                invalidate = true;
14210            } else {
14211                // We're just on -- but we may have been fading before so
14212                // reset alpha
14213                cache.scrollBar.mutate().setAlpha(255);
14214            }
14215
14216
14217            final int viewFlags = mViewFlags;
14218
14219            final boolean drawHorizontalScrollBar =
14220                (viewFlags & SCROLLBARS_HORIZONTAL) == SCROLLBARS_HORIZONTAL;
14221            final boolean drawVerticalScrollBar =
14222                (viewFlags & SCROLLBARS_VERTICAL) == SCROLLBARS_VERTICAL
14223                && !isVerticalScrollBarHidden();
14224
14225            if (drawVerticalScrollBar || drawHorizontalScrollBar) {
14226                final int width = mRight - mLeft;
14227                final int height = mBottom - mTop;
14228
14229                final ScrollBarDrawable scrollBar = cache.scrollBar;
14230
14231                final int scrollX = mScrollX;
14232                final int scrollY = mScrollY;
14233                final int inside = (viewFlags & SCROLLBARS_OUTSIDE_MASK) == 0 ? ~0 : 0;
14234
14235                int left;
14236                int top;
14237                int right;
14238                int bottom;
14239
14240                if (drawHorizontalScrollBar) {
14241                    int size = scrollBar.getSize(false);
14242                    if (size <= 0) {
14243                        size = cache.scrollBarSize;
14244                    }
14245
14246                    scrollBar.setParameters(computeHorizontalScrollRange(),
14247                                            computeHorizontalScrollOffset(),
14248                                            computeHorizontalScrollExtent(), false);
14249                    final int verticalScrollBarGap = drawVerticalScrollBar ?
14250                            getVerticalScrollbarWidth() : 0;
14251                    top = scrollY + height - size - (mUserPaddingBottom & inside);
14252                    left = scrollX + (mPaddingLeft & inside);
14253                    right = scrollX + width - (mUserPaddingRight & inside) - verticalScrollBarGap;
14254                    bottom = top + size;
14255                    onDrawHorizontalScrollBar(canvas, scrollBar, left, top, right, bottom);
14256                    if (invalidate) {
14257                        invalidate(left, top, right, bottom);
14258                    }
14259                }
14260
14261                if (drawVerticalScrollBar) {
14262                    int size = scrollBar.getSize(true);
14263                    if (size <= 0) {
14264                        size = cache.scrollBarSize;
14265                    }
14266
14267                    scrollBar.setParameters(computeVerticalScrollRange(),
14268                                            computeVerticalScrollOffset(),
14269                                            computeVerticalScrollExtent(), true);
14270                    int verticalScrollbarPosition = mVerticalScrollbarPosition;
14271                    if (verticalScrollbarPosition == SCROLLBAR_POSITION_DEFAULT) {
14272                        verticalScrollbarPosition = isLayoutRtl() ?
14273                                SCROLLBAR_POSITION_LEFT : SCROLLBAR_POSITION_RIGHT;
14274                    }
14275                    switch (verticalScrollbarPosition) {
14276                        default:
14277                        case SCROLLBAR_POSITION_RIGHT:
14278                            left = scrollX + width - size - (mUserPaddingRight & inside);
14279                            break;
14280                        case SCROLLBAR_POSITION_LEFT:
14281                            left = scrollX + (mUserPaddingLeft & inside);
14282                            break;
14283                    }
14284                    top = scrollY + (mPaddingTop & inside);
14285                    right = left + size;
14286                    bottom = scrollY + height - (mUserPaddingBottom & inside);
14287                    onDrawVerticalScrollBar(canvas, scrollBar, left, top, right, bottom);
14288                    if (invalidate) {
14289                        invalidate(left, top, right, bottom);
14290                    }
14291                }
14292            }
14293        }
14294    }
14295
14296    /**
14297     * Override this if the vertical scrollbar needs to be hidden in a subclass, like when
14298     * FastScroller is visible.
14299     * @return whether to temporarily hide the vertical scrollbar
14300     * @hide
14301     */
14302    protected boolean isVerticalScrollBarHidden() {
14303        return false;
14304    }
14305
14306    /**
14307     * <p>Draw the horizontal scrollbar if
14308     * {@link #isHorizontalScrollBarEnabled()} returns true.</p>
14309     *
14310     * @param canvas the canvas on which to draw the scrollbar
14311     * @param scrollBar the scrollbar's drawable
14312     *
14313     * @see #isHorizontalScrollBarEnabled()
14314     * @see #computeHorizontalScrollRange()
14315     * @see #computeHorizontalScrollExtent()
14316     * @see #computeHorizontalScrollOffset()
14317     * @see android.widget.ScrollBarDrawable
14318     * @hide
14319     */
14320    protected void onDrawHorizontalScrollBar(Canvas canvas, Drawable scrollBar,
14321            int l, int t, int r, int b) {
14322        scrollBar.setBounds(l, t, r, b);
14323        scrollBar.draw(canvas);
14324    }
14325
14326    /**
14327     * <p>Draw the vertical scrollbar if {@link #isVerticalScrollBarEnabled()}
14328     * returns true.</p>
14329     *
14330     * @param canvas the canvas on which to draw the scrollbar
14331     * @param scrollBar the scrollbar's drawable
14332     *
14333     * @see #isVerticalScrollBarEnabled()
14334     * @see #computeVerticalScrollRange()
14335     * @see #computeVerticalScrollExtent()
14336     * @see #computeVerticalScrollOffset()
14337     * @see android.widget.ScrollBarDrawable
14338     * @hide
14339     */
14340    protected void onDrawVerticalScrollBar(Canvas canvas, Drawable scrollBar,
14341            int l, int t, int r, int b) {
14342        scrollBar.setBounds(l, t, r, b);
14343        scrollBar.draw(canvas);
14344    }
14345
14346    /**
14347     * Implement this to do your drawing.
14348     *
14349     * @param canvas the canvas on which the background will be drawn
14350     */
14351    protected void onDraw(Canvas canvas) {
14352    }
14353
14354    /*
14355     * Caller is responsible for calling requestLayout if necessary.
14356     * (This allows addViewInLayout to not request a new layout.)
14357     */
14358    void assignParent(ViewParent parent) {
14359        if (mParent == null) {
14360            mParent = parent;
14361        } else if (parent == null) {
14362            mParent = null;
14363        } else {
14364            throw new RuntimeException("view " + this + " being added, but"
14365                    + " it already has a parent");
14366        }
14367    }
14368
14369    /**
14370     * This is called when the view is attached to a window.  At this point it
14371     * has a Surface and will start drawing.  Note that this function is
14372     * guaranteed to be called before {@link #onDraw(android.graphics.Canvas)},
14373     * however it may be called any time before the first onDraw -- including
14374     * before or after {@link #onMeasure(int, int)}.
14375     *
14376     * @see #onDetachedFromWindow()
14377     */
14378    @CallSuper
14379    protected void onAttachedToWindow() {
14380        if ((mPrivateFlags & PFLAG_REQUEST_TRANSPARENT_REGIONS) != 0) {
14381            mParent.requestTransparentRegion(this);
14382        }
14383
14384        if ((mPrivateFlags & PFLAG_AWAKEN_SCROLL_BARS_ON_ATTACH) != 0) {
14385            initialAwakenScrollBars();
14386            mPrivateFlags &= ~PFLAG_AWAKEN_SCROLL_BARS_ON_ATTACH;
14387        }
14388
14389        mPrivateFlags3 &= ~(PFLAG3_IS_LAID_OUT | PFLAG3_PARTIAL_LAYOUT_REQUESTED);
14390
14391        jumpDrawablesToCurrentState();
14392
14393        resetSubtreeAccessibilityStateChanged();
14394
14395        // rebuild, since Outline not maintained while View is detached
14396        rebuildOutline();
14397
14398        if (isFocused()) {
14399            InputMethodManager imm = InputMethodManager.peekInstance();
14400            if (imm != null) {
14401                imm.focusIn(this);
14402            }
14403        }
14404    }
14405
14406    /**
14407     * Resolve all RTL related properties.
14408     *
14409     * @return true if resolution of RTL properties has been done
14410     *
14411     * @hide
14412     */
14413    public boolean resolveRtlPropertiesIfNeeded() {
14414        if (!needRtlPropertiesResolution()) return false;
14415
14416        // Order is important here: LayoutDirection MUST be resolved first
14417        if (!isLayoutDirectionResolved()) {
14418            resolveLayoutDirection();
14419            resolveLayoutParams();
14420        }
14421        // ... then we can resolve the others properties depending on the resolved LayoutDirection.
14422        if (!isTextDirectionResolved()) {
14423            resolveTextDirection();
14424        }
14425        if (!isTextAlignmentResolved()) {
14426            resolveTextAlignment();
14427        }
14428        // Should resolve Drawables before Padding because we need the layout direction of the
14429        // Drawable to correctly resolve Padding.
14430        if (!areDrawablesResolved()) {
14431            resolveDrawables();
14432        }
14433        if (!isPaddingResolved()) {
14434            resolvePadding();
14435        }
14436        onRtlPropertiesChanged(getLayoutDirection());
14437        return true;
14438    }
14439
14440    /**
14441     * Reset resolution of all RTL related properties.
14442     *
14443     * @hide
14444     */
14445    public void resetRtlProperties() {
14446        resetResolvedLayoutDirection();
14447        resetResolvedTextDirection();
14448        resetResolvedTextAlignment();
14449        resetResolvedPadding();
14450        resetResolvedDrawables();
14451    }
14452
14453    /**
14454     * @see #onScreenStateChanged(int)
14455     */
14456    void dispatchScreenStateChanged(int screenState) {
14457        onScreenStateChanged(screenState);
14458    }
14459
14460    /**
14461     * This method is called whenever the state of the screen this view is
14462     * attached to changes. A state change will usually occurs when the screen
14463     * turns on or off (whether it happens automatically or the user does it
14464     * manually.)
14465     *
14466     * @param screenState The new state of the screen. Can be either
14467     *                    {@link #SCREEN_STATE_ON} or {@link #SCREEN_STATE_OFF}
14468     */
14469    public void onScreenStateChanged(int screenState) {
14470    }
14471
14472    /**
14473     * Return true if the application tag in the AndroidManifest has set "supportRtl" to true
14474     */
14475    private boolean hasRtlSupport() {
14476        return mContext.getApplicationInfo().hasRtlSupport();
14477    }
14478
14479    /**
14480     * Return true if we are in RTL compatibility mode (either before Jelly Bean MR1 or
14481     * RTL not supported)
14482     */
14483    private boolean isRtlCompatibilityMode() {
14484        final int targetSdkVersion = getContext().getApplicationInfo().targetSdkVersion;
14485        return targetSdkVersion < JELLY_BEAN_MR1 || !hasRtlSupport();
14486    }
14487
14488    /**
14489     * @return true if RTL properties need resolution.
14490     *
14491     */
14492    private boolean needRtlPropertiesResolution() {
14493        return (mPrivateFlags2 & ALL_RTL_PROPERTIES_RESOLVED) != ALL_RTL_PROPERTIES_RESOLVED;
14494    }
14495
14496    /**
14497     * Called when any RTL property (layout direction or text direction or text alignment) has
14498     * been changed.
14499     *
14500     * Subclasses need to override this method to take care of cached information that depends on the
14501     * resolved layout direction, or to inform child views that inherit their layout direction.
14502     *
14503     * The default implementation does nothing.
14504     *
14505     * @param layoutDirection the direction of the layout
14506     *
14507     * @see #LAYOUT_DIRECTION_LTR
14508     * @see #LAYOUT_DIRECTION_RTL
14509     */
14510    public void onRtlPropertiesChanged(@ResolvedLayoutDir int layoutDirection) {
14511    }
14512
14513    /**
14514     * Resolve and cache the layout direction. LTR is set initially. This is implicitly supposing
14515     * that the parent directionality can and will be resolved before its children.
14516     *
14517     * @return true if resolution has been done, false otherwise.
14518     *
14519     * @hide
14520     */
14521    public boolean resolveLayoutDirection() {
14522        // Clear any previous layout direction resolution
14523        mPrivateFlags2 &= ~PFLAG2_LAYOUT_DIRECTION_RESOLVED_MASK;
14524
14525        if (hasRtlSupport()) {
14526            // Set resolved depending on layout direction
14527            switch ((mPrivateFlags2 & PFLAG2_LAYOUT_DIRECTION_MASK) >>
14528                    PFLAG2_LAYOUT_DIRECTION_MASK_SHIFT) {
14529                case LAYOUT_DIRECTION_INHERIT:
14530                    // We cannot resolve yet. LTR is by default and let the resolution happen again
14531                    // later to get the correct resolved value
14532                    if (!canResolveLayoutDirection()) return false;
14533
14534                    // Parent has not yet resolved, LTR is still the default
14535                    try {
14536                        if (!mParent.isLayoutDirectionResolved()) return false;
14537
14538                        if (mParent.getLayoutDirection() == LAYOUT_DIRECTION_RTL) {
14539                            mPrivateFlags2 |= PFLAG2_LAYOUT_DIRECTION_RESOLVED_RTL;
14540                        }
14541                    } catch (AbstractMethodError e) {
14542                        Log.e(VIEW_LOG_TAG, mParent.getClass().getSimpleName() +
14543                                " does not fully implement ViewParent", e);
14544                    }
14545                    break;
14546                case LAYOUT_DIRECTION_RTL:
14547                    mPrivateFlags2 |= PFLAG2_LAYOUT_DIRECTION_RESOLVED_RTL;
14548                    break;
14549                case LAYOUT_DIRECTION_LOCALE:
14550                    if((LAYOUT_DIRECTION_RTL ==
14551                            TextUtils.getLayoutDirectionFromLocale(Locale.getDefault()))) {
14552                        mPrivateFlags2 |= PFLAG2_LAYOUT_DIRECTION_RESOLVED_RTL;
14553                    }
14554                    break;
14555                default:
14556                    // Nothing to do, LTR by default
14557            }
14558        }
14559
14560        // Set to resolved
14561        mPrivateFlags2 |= PFLAG2_LAYOUT_DIRECTION_RESOLVED;
14562        return true;
14563    }
14564
14565    /**
14566     * Check if layout direction resolution can be done.
14567     *
14568     * @return true if layout direction resolution can be done otherwise return false.
14569     */
14570    public boolean canResolveLayoutDirection() {
14571        switch (getRawLayoutDirection()) {
14572            case LAYOUT_DIRECTION_INHERIT:
14573                if (mParent != null) {
14574                    try {
14575                        return mParent.canResolveLayoutDirection();
14576                    } catch (AbstractMethodError e) {
14577                        Log.e(VIEW_LOG_TAG, mParent.getClass().getSimpleName() +
14578                                " does not fully implement ViewParent", e);
14579                    }
14580                }
14581                return false;
14582
14583            default:
14584                return true;
14585        }
14586    }
14587
14588    /**
14589     * Reset the resolved layout direction. Layout direction will be resolved during a call to
14590     * {@link #onMeasure(int, int)}.
14591     *
14592     * @hide
14593     */
14594    public void resetResolvedLayoutDirection() {
14595        // Reset the current resolved bits
14596        mPrivateFlags2 &= ~PFLAG2_LAYOUT_DIRECTION_RESOLVED_MASK;
14597    }
14598
14599    /**
14600     * @return true if the layout direction is inherited.
14601     *
14602     * @hide
14603     */
14604    public boolean isLayoutDirectionInherited() {
14605        return (getRawLayoutDirection() == LAYOUT_DIRECTION_INHERIT);
14606    }
14607
14608    /**
14609     * @return true if layout direction has been resolved.
14610     */
14611    public boolean isLayoutDirectionResolved() {
14612        return (mPrivateFlags2 & PFLAG2_LAYOUT_DIRECTION_RESOLVED) == PFLAG2_LAYOUT_DIRECTION_RESOLVED;
14613    }
14614
14615    /**
14616     * Return if padding has been resolved
14617     *
14618     * @hide
14619     */
14620    boolean isPaddingResolved() {
14621        return (mPrivateFlags2 & PFLAG2_PADDING_RESOLVED) == PFLAG2_PADDING_RESOLVED;
14622    }
14623
14624    /**
14625     * Resolves padding depending on layout direction, if applicable, and
14626     * recomputes internal padding values to adjust for scroll bars.
14627     *
14628     * @hide
14629     */
14630    public void resolvePadding() {
14631        final int resolvedLayoutDirection = getLayoutDirection();
14632
14633        if (!isRtlCompatibilityMode()) {
14634            // Post Jelly Bean MR1 case: we need to take the resolved layout direction into account.
14635            // If start / end padding are defined, they will be resolved (hence overriding) to
14636            // left / right or right / left depending on the resolved layout direction.
14637            // If start / end padding are not defined, use the left / right ones.
14638            if (mBackground != null && (!mLeftPaddingDefined || !mRightPaddingDefined)) {
14639                Rect padding = sThreadLocal.get();
14640                if (padding == null) {
14641                    padding = new Rect();
14642                    sThreadLocal.set(padding);
14643                }
14644                mBackground.getPadding(padding);
14645                if (!mLeftPaddingDefined) {
14646                    mUserPaddingLeftInitial = padding.left;
14647                }
14648                if (!mRightPaddingDefined) {
14649                    mUserPaddingRightInitial = padding.right;
14650                }
14651            }
14652            switch (resolvedLayoutDirection) {
14653                case LAYOUT_DIRECTION_RTL:
14654                    if (mUserPaddingStart != UNDEFINED_PADDING) {
14655                        mUserPaddingRight = mUserPaddingStart;
14656                    } else {
14657                        mUserPaddingRight = mUserPaddingRightInitial;
14658                    }
14659                    if (mUserPaddingEnd != UNDEFINED_PADDING) {
14660                        mUserPaddingLeft = mUserPaddingEnd;
14661                    } else {
14662                        mUserPaddingLeft = mUserPaddingLeftInitial;
14663                    }
14664                    break;
14665                case LAYOUT_DIRECTION_LTR:
14666                default:
14667                    if (mUserPaddingStart != UNDEFINED_PADDING) {
14668                        mUserPaddingLeft = mUserPaddingStart;
14669                    } else {
14670                        mUserPaddingLeft = mUserPaddingLeftInitial;
14671                    }
14672                    if (mUserPaddingEnd != UNDEFINED_PADDING) {
14673                        mUserPaddingRight = mUserPaddingEnd;
14674                    } else {
14675                        mUserPaddingRight = mUserPaddingRightInitial;
14676                    }
14677            }
14678
14679            mUserPaddingBottom = (mUserPaddingBottom >= 0) ? mUserPaddingBottom : mPaddingBottom;
14680        }
14681
14682        internalSetPadding(mUserPaddingLeft, mPaddingTop, mUserPaddingRight, mUserPaddingBottom);
14683        onRtlPropertiesChanged(resolvedLayoutDirection);
14684
14685        mPrivateFlags2 |= PFLAG2_PADDING_RESOLVED;
14686    }
14687
14688    /**
14689     * Reset the resolved layout direction.
14690     *
14691     * @hide
14692     */
14693    public void resetResolvedPadding() {
14694        resetResolvedPaddingInternal();
14695    }
14696
14697    /**
14698     * Used when we only want to reset *this* view's padding and not trigger overrides
14699     * in ViewGroup that reset children too.
14700     */
14701    void resetResolvedPaddingInternal() {
14702        mPrivateFlags2 &= ~PFLAG2_PADDING_RESOLVED;
14703    }
14704
14705    /**
14706     * This is called when the view is detached from a window.  At this point it
14707     * no longer has a surface for drawing.
14708     *
14709     * @see #onAttachedToWindow()
14710     */
14711    @CallSuper
14712    protected void onDetachedFromWindow() {
14713    }
14714
14715    /**
14716     * This is a framework-internal mirror of onDetachedFromWindow() that's called
14717     * after onDetachedFromWindow().
14718     *
14719     * If you override this you *MUST* call super.onDetachedFromWindowInternal()!
14720     * The super method should be called at the end of the overridden method to ensure
14721     * subclasses are destroyed first
14722     *
14723     * @hide
14724     */
14725    @CallSuper
14726    protected void onDetachedFromWindowInternal() {
14727        if (mAttachInfo != null && isPartialLayoutRequested()) {
14728            mAttachInfo.mPartialLayoutViews.remove(this);
14729        }
14730
14731        mPrivateFlags &= ~PFLAG_CANCEL_NEXT_UP_EVENT;
14732        mPrivateFlags3 &= ~(PFLAG3_IS_LAID_OUT | PFLAG3_PARTIAL_LAYOUT_REQUESTED
14733                | PFLAG3_LAYOUT_PARAMS_CHANGED);
14734
14735        removeUnsetPressCallback();
14736        removeLongPressCallback();
14737        removePerformClickCallback();
14738        removeSendViewScrolledAccessibilityEventCallback();
14739        stopNestedScroll();
14740
14741        // Anything that started animating right before detach should already
14742        // be in its final state when re-attached.
14743        jumpDrawablesToCurrentState();
14744
14745        destroyDrawingCache();
14746
14747        cleanupDraw();
14748        mCurrentAnimation = null;
14749    }
14750
14751    private void cleanupDraw() {
14752        resetDisplayList();
14753        if (mAttachInfo != null) {
14754            mAttachInfo.mViewRootImpl.cancelInvalidate(this);
14755        }
14756    }
14757
14758    void invalidateInheritedLayoutMode(int layoutModeOfRoot) {
14759    }
14760
14761    /**
14762     * @return The number of times this view has been attached to a window
14763     */
14764    protected int getWindowAttachCount() {
14765        return mWindowAttachCount;
14766    }
14767
14768    /**
14769     * Retrieve a unique token identifying the window this view is attached to.
14770     * @return Return the window's token for use in
14771     * {@link WindowManager.LayoutParams#token WindowManager.LayoutParams.token}.
14772     */
14773    public IBinder getWindowToken() {
14774        return mAttachInfo != null ? mAttachInfo.mWindowToken : null;
14775    }
14776
14777    /**
14778     * Retrieve the {@link WindowId} for the window this view is
14779     * currently attached to.
14780     */
14781    public WindowId getWindowId() {
14782        if (mAttachInfo == null) {
14783            return null;
14784        }
14785        if (mAttachInfo.mWindowId == null) {
14786            try {
14787                mAttachInfo.mIWindowId = mAttachInfo.mSession.getWindowId(
14788                        mAttachInfo.mWindowToken);
14789                mAttachInfo.mWindowId = new WindowId(
14790                        mAttachInfo.mIWindowId);
14791            } catch (RemoteException e) {
14792            }
14793        }
14794        return mAttachInfo.mWindowId;
14795    }
14796
14797    /**
14798     * Retrieve a unique token identifying the top-level "real" window of
14799     * the window that this view is attached to.  That is, this is like
14800     * {@link #getWindowToken}, except if the window this view in is a panel
14801     * window (attached to another containing window), then the token of
14802     * the containing window is returned instead.
14803     *
14804     * @return Returns the associated window token, either
14805     * {@link #getWindowToken()} or the containing window's token.
14806     */
14807    public IBinder getApplicationWindowToken() {
14808        AttachInfo ai = mAttachInfo;
14809        if (ai != null) {
14810            IBinder appWindowToken = ai.mPanelParentWindowToken;
14811            if (appWindowToken == null) {
14812                appWindowToken = ai.mWindowToken;
14813            }
14814            return appWindowToken;
14815        }
14816        return null;
14817    }
14818
14819    /**
14820     * Gets the logical display to which the view's window has been attached.
14821     *
14822     * @return The logical display, or null if the view is not currently attached to a window.
14823     */
14824    public Display getDisplay() {
14825        return mAttachInfo != null ? mAttachInfo.mDisplay : null;
14826    }
14827
14828    /**
14829     * Retrieve private session object this view hierarchy is using to
14830     * communicate with the window manager.
14831     * @return the session object to communicate with the window manager
14832     */
14833    /*package*/ IWindowSession getWindowSession() {
14834        return mAttachInfo != null ? mAttachInfo.mSession : null;
14835    }
14836
14837    /**
14838     * Return the visibility value of the least visible component passed.
14839     */
14840    int combineVisibility(int vis1, int vis2) {
14841        // This works because VISIBLE < INVISIBLE < GONE.
14842        return Math.max(vis1, vis2);
14843    }
14844
14845    /**
14846     * @param info the {@link android.view.View.AttachInfo} to associated with
14847     *        this view
14848     */
14849    void dispatchAttachedToWindow(AttachInfo info, int visibility) {
14850        mAttachInfo = info;
14851        if (mOverlay != null) {
14852            mOverlay.getOverlayView().dispatchAttachedToWindow(info, visibility);
14853        }
14854        mWindowAttachCount++;
14855        // We will need to evaluate the drawable state at least once.
14856        mPrivateFlags |= PFLAG_DRAWABLE_STATE_DIRTY;
14857        if (mFloatingTreeObserver != null) {
14858            info.mTreeObserver.merge(mFloatingTreeObserver);
14859            mFloatingTreeObserver = null;
14860        }
14861        if ((mPrivateFlags&PFLAG_SCROLL_CONTAINER) != 0) {
14862            mAttachInfo.mScrollContainers.add(this);
14863            mPrivateFlags |= PFLAG_SCROLL_CONTAINER_ADDED;
14864        }
14865        // Transfer all pending runnables.
14866        if (mRunQueue != null) {
14867            mRunQueue.executeActions(info.mHandler);
14868            mRunQueue = null;
14869        }
14870        performCollectViewAttributes(mAttachInfo, visibility);
14871        onAttachedToWindow();
14872
14873        ListenerInfo li = mListenerInfo;
14874        final CopyOnWriteArrayList<OnAttachStateChangeListener> listeners =
14875                li != null ? li.mOnAttachStateChangeListeners : null;
14876        if (listeners != null && listeners.size() > 0) {
14877            // NOTE: because of the use of CopyOnWriteArrayList, we *must* use an iterator to
14878            // perform the dispatching. The iterator is a safe guard against listeners that
14879            // could mutate the list by calling the various add/remove methods. This prevents
14880            // the array from being modified while we iterate it.
14881            for (OnAttachStateChangeListener listener : listeners) {
14882                listener.onViewAttachedToWindow(this);
14883            }
14884        }
14885
14886        int vis = info.mWindowVisibility;
14887        if (vis != GONE) {
14888            onWindowVisibilityChanged(vis);
14889        }
14890
14891        // Send onVisibilityChanged directly instead of dispatchVisibilityChanged.
14892        // As all views in the subtree will already receive dispatchAttachedToWindow
14893        // traversing the subtree again here is not desired.
14894        onVisibilityChanged(this, visibility);
14895
14896        if ((mPrivateFlags&PFLAG_DRAWABLE_STATE_DIRTY) != 0) {
14897            // If nobody has evaluated the drawable state yet, then do it now.
14898            refreshDrawableState();
14899        }
14900        needGlobalAttributesUpdate(false);
14901    }
14902
14903    void dispatchDetachedFromWindow() {
14904        AttachInfo info = mAttachInfo;
14905        if (info != null) {
14906            int vis = info.mWindowVisibility;
14907            if (vis != GONE) {
14908                onWindowVisibilityChanged(GONE);
14909            }
14910        }
14911
14912        onDetachedFromWindow();
14913        onDetachedFromWindowInternal();
14914
14915        InputMethodManager imm = InputMethodManager.peekInstance();
14916        if (imm != null) {
14917            imm.onViewDetachedFromWindow(this);
14918        }
14919
14920        ListenerInfo li = mListenerInfo;
14921        final CopyOnWriteArrayList<OnAttachStateChangeListener> listeners =
14922                li != null ? li.mOnAttachStateChangeListeners : null;
14923        if (listeners != null && listeners.size() > 0) {
14924            // NOTE: because of the use of CopyOnWriteArrayList, we *must* use an iterator to
14925            // perform the dispatching. The iterator is a safe guard against listeners that
14926            // could mutate the list by calling the various add/remove methods. This prevents
14927            // the array from being modified while we iterate it.
14928            for (OnAttachStateChangeListener listener : listeners) {
14929                listener.onViewDetachedFromWindow(this);
14930            }
14931        }
14932
14933        if ((mPrivateFlags & PFLAG_SCROLL_CONTAINER_ADDED) != 0) {
14934            mAttachInfo.mScrollContainers.remove(this);
14935            mPrivateFlags &= ~PFLAG_SCROLL_CONTAINER_ADDED;
14936        }
14937
14938        mAttachInfo = null;
14939        if (mOverlay != null) {
14940            mOverlay.getOverlayView().dispatchDetachedFromWindow();
14941        }
14942    }
14943
14944    /**
14945     * Cancel any deferred high-level input events that were previously posted to the event queue.
14946     *
14947     * <p>Many views post high-level events such as click handlers to the event queue
14948     * to run deferred in order to preserve a desired user experience - clearing visible
14949     * pressed states before executing, etc. This method will abort any events of this nature
14950     * that are currently in flight.</p>
14951     *
14952     * <p>Custom views that generate their own high-level deferred input events should override
14953     * {@link #onCancelPendingInputEvents()} and remove those pending events from the queue.</p>
14954     *
14955     * <p>This will also cancel pending input events for any child views.</p>
14956     *
14957     * <p>Note that this may not be sufficient as a debouncing strategy for clicks in all cases.
14958     * This will not impact newer events posted after this call that may occur as a result of
14959     * lower-level input events still waiting in the queue. If you are trying to prevent
14960     * double-submitted  events for the duration of some sort of asynchronous transaction
14961     * you should also take other steps to protect against unexpected double inputs e.g. calling
14962     * {@link #setEnabled(boolean) setEnabled(false)} and re-enabling the view when
14963     * the transaction completes, tracking already submitted transaction IDs, etc.</p>
14964     */
14965    public final void cancelPendingInputEvents() {
14966        dispatchCancelPendingInputEvents();
14967    }
14968
14969    /**
14970     * Called by {@link #cancelPendingInputEvents()} to cancel input events in flight.
14971     * Overridden by ViewGroup to dispatch. Package scoped to prevent app-side meddling.
14972     */
14973    void dispatchCancelPendingInputEvents() {
14974        mPrivateFlags3 &= ~PFLAG3_CALLED_SUPER;
14975        onCancelPendingInputEvents();
14976        if ((mPrivateFlags3 & PFLAG3_CALLED_SUPER) != PFLAG3_CALLED_SUPER) {
14977            throw new SuperNotCalledException("View " + getClass().getSimpleName() +
14978                    " did not call through to super.onCancelPendingInputEvents()");
14979        }
14980    }
14981
14982    /**
14983     * Called as the result of a call to {@link #cancelPendingInputEvents()} on this view or
14984     * a parent view.
14985     *
14986     * <p>This method is responsible for removing any pending high-level input events that were
14987     * posted to the event queue to run later. Custom view classes that post their own deferred
14988     * high-level events via {@link #post(Runnable)}, {@link #postDelayed(Runnable, long)} or
14989     * {@link android.os.Handler} should override this method, call
14990     * <code>super.onCancelPendingInputEvents()</code> and remove those callbacks as appropriate.
14991     * </p>
14992     */
14993    public void onCancelPendingInputEvents() {
14994        removePerformClickCallback();
14995        cancelLongPress();
14996        mPrivateFlags3 |= PFLAG3_CALLED_SUPER;
14997    }
14998
14999    /**
15000     * Store this view hierarchy's frozen state into the given container.
15001     *
15002     * @param container The SparseArray in which to save the view's state.
15003     *
15004     * @see #restoreHierarchyState(android.util.SparseArray)
15005     * @see #dispatchSaveInstanceState(android.util.SparseArray)
15006     * @see #onSaveInstanceState()
15007     */
15008    public void saveHierarchyState(SparseArray<Parcelable> container) {
15009        dispatchSaveInstanceState(container);
15010    }
15011
15012    /**
15013     * Called by {@link #saveHierarchyState(android.util.SparseArray)} to store the state for
15014     * this view and its children. May be overridden to modify how freezing happens to a
15015     * view's children; for example, some views may want to not store state for their children.
15016     *
15017     * @param container The SparseArray in which to save the view's state.
15018     *
15019     * @see #dispatchRestoreInstanceState(android.util.SparseArray)
15020     * @see #saveHierarchyState(android.util.SparseArray)
15021     * @see #onSaveInstanceState()
15022     */
15023    protected void dispatchSaveInstanceState(SparseArray<Parcelable> container) {
15024        if (mID != NO_ID && (mViewFlags & SAVE_DISABLED_MASK) == 0) {
15025            mPrivateFlags &= ~PFLAG_SAVE_STATE_CALLED;
15026            Parcelable state = onSaveInstanceState();
15027            if ((mPrivateFlags & PFLAG_SAVE_STATE_CALLED) == 0) {
15028                throw new IllegalStateException(
15029                        "Derived class did not call super.onSaveInstanceState()");
15030            }
15031            if (state != null) {
15032                // Log.i("View", "Freezing #" + Integer.toHexString(mID)
15033                // + ": " + state);
15034                container.put(mID, state);
15035            }
15036        }
15037    }
15038
15039    /**
15040     * Hook allowing a view to generate a representation of its internal state
15041     * that can later be used to create a new instance with that same state.
15042     * This state should only contain information that is not persistent or can
15043     * not be reconstructed later. For example, you will never store your
15044     * current position on screen because that will be computed again when a
15045     * new instance of the view is placed in its view hierarchy.
15046     * <p>
15047     * Some examples of things you may store here: the current cursor position
15048     * in a text view (but usually not the text itself since that is stored in a
15049     * content provider or other persistent storage), the currently selected
15050     * item in a list view.
15051     *
15052     * @return Returns a Parcelable object containing the view's current dynamic
15053     *         state, or null if there is nothing interesting to save. The
15054     *         default implementation returns null.
15055     * @see #onRestoreInstanceState(android.os.Parcelable)
15056     * @see #saveHierarchyState(android.util.SparseArray)
15057     * @see #dispatchSaveInstanceState(android.util.SparseArray)
15058     * @see #setSaveEnabled(boolean)
15059     */
15060    @CallSuper
15061    protected Parcelable onSaveInstanceState() {
15062        mPrivateFlags |= PFLAG_SAVE_STATE_CALLED;
15063        if (mStartActivityRequestWho != null) {
15064            BaseSavedState state = new BaseSavedState(AbsSavedState.EMPTY_STATE);
15065            state.mStartActivityRequestWhoSaved = mStartActivityRequestWho;
15066            return state;
15067        }
15068        return BaseSavedState.EMPTY_STATE;
15069    }
15070
15071    /**
15072     * Restore this view hierarchy's frozen state from the given container.
15073     *
15074     * @param container The SparseArray which holds previously frozen states.
15075     *
15076     * @see #saveHierarchyState(android.util.SparseArray)
15077     * @see #dispatchRestoreInstanceState(android.util.SparseArray)
15078     * @see #onRestoreInstanceState(android.os.Parcelable)
15079     */
15080    public void restoreHierarchyState(SparseArray<Parcelable> container) {
15081        dispatchRestoreInstanceState(container);
15082    }
15083
15084    /**
15085     * Called by {@link #restoreHierarchyState(android.util.SparseArray)} to retrieve the
15086     * state for this view and its children. May be overridden to modify how restoring
15087     * happens to a view's children; for example, some views may want to not store state
15088     * for their children.
15089     *
15090     * @param container The SparseArray which holds previously saved state.
15091     *
15092     * @see #dispatchSaveInstanceState(android.util.SparseArray)
15093     * @see #restoreHierarchyState(android.util.SparseArray)
15094     * @see #onRestoreInstanceState(android.os.Parcelable)
15095     */
15096    protected void dispatchRestoreInstanceState(SparseArray<Parcelable> container) {
15097        if (mID != NO_ID) {
15098            Parcelable state = container.get(mID);
15099            if (state != null) {
15100                // Log.i("View", "Restoreing #" + Integer.toHexString(mID)
15101                // + ": " + state);
15102                mPrivateFlags &= ~PFLAG_SAVE_STATE_CALLED;
15103                onRestoreInstanceState(state);
15104                if ((mPrivateFlags & PFLAG_SAVE_STATE_CALLED) == 0) {
15105                    throw new IllegalStateException(
15106                            "Derived class did not call super.onRestoreInstanceState()");
15107                }
15108            }
15109        }
15110    }
15111
15112    /**
15113     * Hook allowing a view to re-apply a representation of its internal state that had previously
15114     * been generated by {@link #onSaveInstanceState}. This function will never be called with a
15115     * null state.
15116     *
15117     * @param state The frozen state that had previously been returned by
15118     *        {@link #onSaveInstanceState}.
15119     *
15120     * @see #onSaveInstanceState()
15121     * @see #restoreHierarchyState(android.util.SparseArray)
15122     * @see #dispatchRestoreInstanceState(android.util.SparseArray)
15123     */
15124    @CallSuper
15125    protected void onRestoreInstanceState(Parcelable state) {
15126        mPrivateFlags |= PFLAG_SAVE_STATE_CALLED;
15127        if (state != null && !(state instanceof AbsSavedState)) {
15128            throw new IllegalArgumentException("Wrong state class, expecting View State but "
15129                    + "received " + state.getClass().toString() + " instead. This usually happens "
15130                    + "when two views of different type have the same id in the same hierarchy. "
15131                    + "This view's id is " + ViewDebug.resolveId(mContext, getId()) + ". Make sure "
15132                    + "other views do not use the same id.");
15133        }
15134        if (state != null && state instanceof BaseSavedState) {
15135            mStartActivityRequestWho = ((BaseSavedState) state).mStartActivityRequestWhoSaved;
15136        }
15137    }
15138
15139    /**
15140     * <p>Return the time at which the drawing of the view hierarchy started.</p>
15141     *
15142     * @return the drawing start time in milliseconds
15143     */
15144    public long getDrawingTime() {
15145        return mAttachInfo != null ? mAttachInfo.mDrawingTime : 0;
15146    }
15147
15148    /**
15149     * <p>Enables or disables the duplication of the parent's state into this view. When
15150     * duplication is enabled, this view gets its drawable state from its parent rather
15151     * than from its own internal properties.</p>
15152     *
15153     * <p>Note: in the current implementation, setting this property to true after the
15154     * view was added to a ViewGroup might have no effect at all. This property should
15155     * always be used from XML or set to true before adding this view to a ViewGroup.</p>
15156     *
15157     * <p>Note: if this view's parent addStateFromChildren property is enabled and this
15158     * property is enabled, an exception will be thrown.</p>
15159     *
15160     * <p>Note: if the child view uses and updates additional states which are unknown to the
15161     * parent, these states should not be affected by this method.</p>
15162     *
15163     * @param enabled True to enable duplication of the parent's drawable state, false
15164     *                to disable it.
15165     *
15166     * @see #getDrawableState()
15167     * @see #isDuplicateParentStateEnabled()
15168     */
15169    public void setDuplicateParentStateEnabled(boolean enabled) {
15170        setFlags(enabled ? DUPLICATE_PARENT_STATE : 0, DUPLICATE_PARENT_STATE);
15171    }
15172
15173    /**
15174     * <p>Indicates whether this duplicates its drawable state from its parent.</p>
15175     *
15176     * @return True if this view's drawable state is duplicated from the parent,
15177     *         false otherwise
15178     *
15179     * @see #getDrawableState()
15180     * @see #setDuplicateParentStateEnabled(boolean)
15181     */
15182    public boolean isDuplicateParentStateEnabled() {
15183        return (mViewFlags & DUPLICATE_PARENT_STATE) == DUPLICATE_PARENT_STATE;
15184    }
15185
15186    /**
15187     * <p>Specifies the type of layer backing this view. The layer can be
15188     * {@link #LAYER_TYPE_NONE}, {@link #LAYER_TYPE_SOFTWARE} or
15189     * {@link #LAYER_TYPE_HARDWARE}.</p>
15190     *
15191     * <p>A layer is associated with an optional {@link android.graphics.Paint}
15192     * instance that controls how the layer is composed on screen. The following
15193     * properties of the paint are taken into account when composing the layer:</p>
15194     * <ul>
15195     * <li>{@link android.graphics.Paint#getAlpha() Translucency (alpha)}</li>
15196     * <li>{@link android.graphics.Paint#getXfermode() Blending mode}</li>
15197     * <li>{@link android.graphics.Paint#getColorFilter() Color filter}</li>
15198     * </ul>
15199     *
15200     * <p>If this view has an alpha value set to < 1.0 by calling
15201     * {@link #setAlpha(float)}, the alpha value of the layer's paint is superseded
15202     * by this view's alpha value.</p>
15203     *
15204     * <p>Refer to the documentation of {@link #LAYER_TYPE_NONE},
15205     * {@link #LAYER_TYPE_SOFTWARE} and {@link #LAYER_TYPE_HARDWARE}
15206     * for more information on when and how to use layers.</p>
15207     *
15208     * @param layerType The type of layer to use with this view, must be one of
15209     *        {@link #LAYER_TYPE_NONE}, {@link #LAYER_TYPE_SOFTWARE} or
15210     *        {@link #LAYER_TYPE_HARDWARE}
15211     * @param paint The paint used to compose the layer. This argument is optional
15212     *        and can be null. It is ignored when the layer type is
15213     *        {@link #LAYER_TYPE_NONE}
15214     *
15215     * @see #getLayerType()
15216     * @see #LAYER_TYPE_NONE
15217     * @see #LAYER_TYPE_SOFTWARE
15218     * @see #LAYER_TYPE_HARDWARE
15219     * @see #setAlpha(float)
15220     *
15221     * @attr ref android.R.styleable#View_layerType
15222     */
15223    public void setLayerType(int layerType, Paint paint) {
15224        if (layerType < LAYER_TYPE_NONE || layerType > LAYER_TYPE_HARDWARE) {
15225            throw new IllegalArgumentException("Layer type can only be one of: LAYER_TYPE_NONE, "
15226                    + "LAYER_TYPE_SOFTWARE or LAYER_TYPE_HARDWARE");
15227        }
15228
15229        boolean typeChanged = mRenderNode.setLayerType(layerType);
15230
15231        if (!typeChanged) {
15232            setLayerPaint(paint);
15233            return;
15234        }
15235
15236        // Destroy any previous software drawing cache if needed
15237        if (mLayerType == LAYER_TYPE_SOFTWARE) {
15238            destroyDrawingCache();
15239        }
15240
15241        mLayerType = layerType;
15242        final boolean layerDisabled = (mLayerType == LAYER_TYPE_NONE);
15243        mLayerPaint = layerDisabled ? null : (paint == null ? new Paint() : paint);
15244        mRenderNode.setLayerPaint(mLayerPaint);
15245
15246        // draw() behaves differently if we are on a layer, so we need to
15247        // invalidate() here
15248        invalidateParentCaches();
15249        invalidate(true);
15250    }
15251
15252    /**
15253     * Updates the {@link Paint} object used with the current layer (used only if the current
15254     * layer type is not set to {@link #LAYER_TYPE_NONE}). Changed properties of the Paint
15255     * provided to {@link #setLayerType(int, android.graphics.Paint)} will be used the next time
15256     * the View is redrawn, but {@link #setLayerPaint(android.graphics.Paint)} must be called to
15257     * ensure that the view gets redrawn immediately.
15258     *
15259     * <p>A layer is associated with an optional {@link android.graphics.Paint}
15260     * instance that controls how the layer is composed on screen. The following
15261     * properties of the paint are taken into account when composing the layer:</p>
15262     * <ul>
15263     * <li>{@link android.graphics.Paint#getAlpha() Translucency (alpha)}</li>
15264     * <li>{@link android.graphics.Paint#getXfermode() Blending mode}</li>
15265     * <li>{@link android.graphics.Paint#getColorFilter() Color filter}</li>
15266     * </ul>
15267     *
15268     * <p>If this view has an alpha value set to < 1.0 by calling {@link #setAlpha(float)}, the
15269     * alpha value of the layer's paint is superseded by this view's alpha value.</p>
15270     *
15271     * @param paint The paint used to compose the layer. This argument is optional
15272     *        and can be null. It is ignored when the layer type is
15273     *        {@link #LAYER_TYPE_NONE}
15274     *
15275     * @see #setLayerType(int, android.graphics.Paint)
15276     */
15277    public void setLayerPaint(Paint paint) {
15278        int layerType = getLayerType();
15279        if (layerType != LAYER_TYPE_NONE) {
15280            mLayerPaint = paint == null ? new Paint() : paint;
15281            if (layerType == LAYER_TYPE_HARDWARE) {
15282                if (mRenderNode.setLayerPaint(mLayerPaint)) {
15283                    invalidateViewProperty(false, false);
15284                }
15285            } else {
15286                invalidate();
15287            }
15288        }
15289    }
15290
15291    /**
15292     * Indicates what type of layer is currently associated with this view. By default
15293     * a view does not have a layer, and the layer type is {@link #LAYER_TYPE_NONE}.
15294     * Refer to the documentation of {@link #setLayerType(int, android.graphics.Paint)}
15295     * for more information on the different types of layers.
15296     *
15297     * @return {@link #LAYER_TYPE_NONE}, {@link #LAYER_TYPE_SOFTWARE} or
15298     *         {@link #LAYER_TYPE_HARDWARE}
15299     *
15300     * @see #setLayerType(int, android.graphics.Paint)
15301     * @see #buildLayer()
15302     * @see #LAYER_TYPE_NONE
15303     * @see #LAYER_TYPE_SOFTWARE
15304     * @see #LAYER_TYPE_HARDWARE
15305     */
15306    public int getLayerType() {
15307        return mLayerType;
15308    }
15309
15310    /**
15311     * Forces this view's layer to be created and this view to be rendered
15312     * into its layer. If this view's layer type is set to {@link #LAYER_TYPE_NONE},
15313     * invoking this method will have no effect.
15314     *
15315     * This method can for instance be used to render a view into its layer before
15316     * starting an animation. If this view is complex, rendering into the layer
15317     * before starting the animation will avoid skipping frames.
15318     *
15319     * @throws IllegalStateException If this view is not attached to a window
15320     *
15321     * @see #setLayerType(int, android.graphics.Paint)
15322     */
15323    public void buildLayer() {
15324        if (mLayerType == LAYER_TYPE_NONE) return;
15325
15326        final AttachInfo attachInfo = mAttachInfo;
15327        if (attachInfo == null) {
15328            throw new IllegalStateException("This view must be attached to a window first");
15329        }
15330
15331        if (getWidth() == 0 || getHeight() == 0) {
15332            return;
15333        }
15334
15335        switch (mLayerType) {
15336            case LAYER_TYPE_HARDWARE:
15337                updateDisplayListIfDirty();
15338                if (attachInfo.mHardwareRenderer != null && mRenderNode.isValid()) {
15339                    attachInfo.mHardwareRenderer.buildLayer(mRenderNode);
15340                }
15341                break;
15342            case LAYER_TYPE_SOFTWARE:
15343                buildDrawingCache(true);
15344                break;
15345        }
15346    }
15347
15348    /**
15349     * Destroys all hardware rendering resources. This method is invoked
15350     * when the system needs to reclaim resources. Upon execution of this
15351     * method, you should free any OpenGL resources created by the view.
15352     *
15353     * Note: you <strong>must</strong> call
15354     * <code>super.destroyHardwareResources()</code> when overriding
15355     * this method.
15356     *
15357     * @hide
15358     */
15359    @CallSuper
15360    protected void destroyHardwareResources() {
15361        // Although the Layer will be destroyed by RenderNode, we want to release
15362        // the staging display list, which is also a signal to RenderNode that it's
15363        // safe to free its copy of the display list as it knows that we will
15364        // push an updated DisplayList if we try to draw again
15365        resetDisplayList();
15366    }
15367
15368    /**
15369     * <p>Enables or disables the drawing cache. When the drawing cache is enabled, the next call
15370     * to {@link #getDrawingCache()} or {@link #buildDrawingCache()} will draw the view in a
15371     * bitmap. Calling {@link #draw(android.graphics.Canvas)} will not draw from the cache when
15372     * the cache is enabled. To benefit from the cache, you must request the drawing cache by
15373     * calling {@link #getDrawingCache()} and draw it on screen if the returned bitmap is not
15374     * null.</p>
15375     *
15376     * <p>Enabling the drawing cache is similar to
15377     * {@link #setLayerType(int, android.graphics.Paint) setting a layer} when hardware
15378     * acceleration is turned off. When hardware acceleration is turned on, enabling the
15379     * drawing cache has no effect on rendering because the system uses a different mechanism
15380     * for acceleration which ignores the flag. If you want to use a Bitmap for the view, even
15381     * when hardware acceleration is enabled, see {@link #setLayerType(int, android.graphics.Paint)}
15382     * for information on how to enable software and hardware layers.</p>
15383     *
15384     * <p>This API can be used to manually generate
15385     * a bitmap copy of this view, by setting the flag to <code>true</code> and calling
15386     * {@link #getDrawingCache()}.</p>
15387     *
15388     * @param enabled true to enable the drawing cache, false otherwise
15389     *
15390     * @see #isDrawingCacheEnabled()
15391     * @see #getDrawingCache()
15392     * @see #buildDrawingCache()
15393     * @see #setLayerType(int, android.graphics.Paint)
15394     */
15395    public void setDrawingCacheEnabled(boolean enabled) {
15396        mCachingFailed = false;
15397        setFlags(enabled ? DRAWING_CACHE_ENABLED : 0, DRAWING_CACHE_ENABLED);
15398    }
15399
15400    /**
15401     * <p>Indicates whether the drawing cache is enabled for this view.</p>
15402     *
15403     * @return true if the drawing cache is enabled
15404     *
15405     * @see #setDrawingCacheEnabled(boolean)
15406     * @see #getDrawingCache()
15407     */
15408    @ViewDebug.ExportedProperty(category = "drawing")
15409    public boolean isDrawingCacheEnabled() {
15410        return (mViewFlags & DRAWING_CACHE_ENABLED) == DRAWING_CACHE_ENABLED;
15411    }
15412
15413    /**
15414     * Debugging utility which recursively outputs the dirty state of a view and its
15415     * descendants.
15416     *
15417     * @hide
15418     */
15419    @SuppressWarnings({"UnusedDeclaration"})
15420    public void outputDirtyFlags(String indent, boolean clear, int clearMask) {
15421        Log.d("View", indent + this + "             DIRTY(" + (mPrivateFlags & View.PFLAG_DIRTY_MASK) +
15422                ") DRAWN(" + (mPrivateFlags & PFLAG_DRAWN) + ")" + " CACHE_VALID(" +
15423                (mPrivateFlags & View.PFLAG_DRAWING_CACHE_VALID) +
15424                ") INVALIDATED(" + (mPrivateFlags & PFLAG_INVALIDATED) + ")");
15425        if (clear) {
15426            mPrivateFlags &= clearMask;
15427        }
15428        if (this instanceof ViewGroup) {
15429            ViewGroup parent = (ViewGroup) this;
15430            final int count = parent.getChildCount();
15431            for (int i = 0; i < count; i++) {
15432                final View child = parent.getChildAt(i);
15433                child.outputDirtyFlags(indent + "  ", clear, clearMask);
15434            }
15435        }
15436    }
15437
15438    /**
15439     * This method is used by ViewGroup to cause its children to restore or recreate their
15440     * display lists. It is called by getDisplayList() when the parent ViewGroup does not need
15441     * to recreate its own display list, which would happen if it went through the normal
15442     * draw/dispatchDraw mechanisms.
15443     *
15444     * @hide
15445     */
15446    protected void dispatchGetDisplayList() {}
15447
15448    /**
15449     * A view that is not attached or hardware accelerated cannot create a display list.
15450     * This method checks these conditions and returns the appropriate result.
15451     *
15452     * @return true if view has the ability to create a display list, false otherwise.
15453     *
15454     * @hide
15455     */
15456    public boolean canHaveDisplayList() {
15457        return !(mAttachInfo == null || mAttachInfo.mHardwareRenderer == null);
15458    }
15459
15460    /**
15461     * Gets the RenderNode for the view, and updates its DisplayList (if needed and supported)
15462     * @hide
15463     */
15464    @NonNull
15465    public RenderNode updateDisplayListIfDirty() {
15466        final RenderNode renderNode = mRenderNode;
15467        if (!canHaveDisplayList()) {
15468            // can't populate RenderNode, don't try
15469            return renderNode;
15470        }
15471
15472        if ((mPrivateFlags & PFLAG_DRAWING_CACHE_VALID) == 0
15473                || !renderNode.isValid()
15474                || (mRecreateDisplayList)) {
15475            // Don't need to recreate the display list, just need to tell our
15476            // children to restore/recreate theirs
15477            if (renderNode.isValid()
15478                    && !mRecreateDisplayList) {
15479                mPrivateFlags |= PFLAG_DRAWN | PFLAG_DRAWING_CACHE_VALID;
15480                mPrivateFlags &= ~PFLAG_DIRTY_MASK;
15481                dispatchGetDisplayList();
15482
15483                return renderNode; // no work needed
15484            }
15485
15486            // If we got here, we're recreating it. Mark it as such to ensure that
15487            // we copy in child display lists into ours in drawChild()
15488            mRecreateDisplayList = true;
15489
15490            int width = mRight - mLeft;
15491            int height = mBottom - mTop;
15492            int layerType = getLayerType();
15493
15494            final DisplayListCanvas canvas = renderNode.start(width, height);
15495            canvas.setHighContrastText(mAttachInfo.mHighContrastText);
15496
15497            try {
15498                if (layerType == LAYER_TYPE_SOFTWARE) {
15499                    buildDrawingCache(true);
15500                    Bitmap cache = getDrawingCache(true);
15501                    if (cache != null) {
15502                        canvas.drawBitmap(cache, 0, 0, mLayerPaint);
15503                    }
15504                } else {
15505                    computeScroll();
15506
15507                    canvas.translate(-mScrollX, -mScrollY);
15508                    mPrivateFlags |= PFLAG_DRAWN | PFLAG_DRAWING_CACHE_VALID;
15509                    mPrivateFlags &= ~PFLAG_DIRTY_MASK;
15510
15511                    // Fast path for layouts with no backgrounds
15512                    if ((mPrivateFlags & PFLAG_SKIP_DRAW) == PFLAG_SKIP_DRAW) {
15513                        dispatchDraw(canvas);
15514                        if (mOverlay != null && !mOverlay.isEmpty()) {
15515                            mOverlay.getOverlayView().draw(canvas);
15516                        }
15517                    } else {
15518                        draw(canvas);
15519                    }
15520                }
15521            } finally {
15522                renderNode.end(canvas);
15523                setDisplayListProperties(renderNode);
15524            }
15525        } else {
15526            mPrivateFlags |= PFLAG_DRAWN | PFLAG_DRAWING_CACHE_VALID;
15527            mPrivateFlags &= ~PFLAG_DIRTY_MASK;
15528        }
15529        return renderNode;
15530    }
15531
15532    private void resetDisplayList() {
15533        if (mRenderNode.isValid()) {
15534            mRenderNode.discardDisplayList();
15535        }
15536
15537        if (mBackgroundRenderNode != null && mBackgroundRenderNode.isValid()) {
15538            mBackgroundRenderNode.discardDisplayList();
15539        }
15540    }
15541
15542    /**
15543     * <p>Calling this method is equivalent to calling <code>getDrawingCache(false)</code>.</p>
15544     *
15545     * @return A non-scaled bitmap representing this view or null if cache is disabled.
15546     *
15547     * @see #getDrawingCache(boolean)
15548     */
15549    public Bitmap getDrawingCache() {
15550        return getDrawingCache(false);
15551    }
15552
15553    /**
15554     * <p>Returns the bitmap in which this view drawing is cached. The returned bitmap
15555     * is null when caching is disabled. If caching is enabled and the cache is not ready,
15556     * this method will create it. Calling {@link #draw(android.graphics.Canvas)} will not
15557     * draw from the cache when the cache is enabled. To benefit from the cache, you must
15558     * request the drawing cache by calling this method and draw it on screen if the
15559     * returned bitmap is not null.</p>
15560     *
15561     * <p>Note about auto scaling in compatibility mode: When auto scaling is not enabled,
15562     * this method will create a bitmap of the same size as this view. Because this bitmap
15563     * will be drawn scaled by the parent ViewGroup, the result on screen might show
15564     * scaling artifacts. To avoid such artifacts, you should call this method by setting
15565     * the auto scaling to true. Doing so, however, will generate a bitmap of a different
15566     * size than the view. This implies that your application must be able to handle this
15567     * size.</p>
15568     *
15569     * @param autoScale Indicates whether the generated bitmap should be scaled based on
15570     *        the current density of the screen when the application is in compatibility
15571     *        mode.
15572     *
15573     * @return A bitmap representing this view or null if cache is disabled.
15574     *
15575     * @see #setDrawingCacheEnabled(boolean)
15576     * @see #isDrawingCacheEnabled()
15577     * @see #buildDrawingCache(boolean)
15578     * @see #destroyDrawingCache()
15579     */
15580    public Bitmap getDrawingCache(boolean autoScale) {
15581        if ((mViewFlags & WILL_NOT_CACHE_DRAWING) == WILL_NOT_CACHE_DRAWING) {
15582            return null;
15583        }
15584        if ((mViewFlags & DRAWING_CACHE_ENABLED) == DRAWING_CACHE_ENABLED) {
15585            buildDrawingCache(autoScale);
15586        }
15587        return autoScale ? mDrawingCache : mUnscaledDrawingCache;
15588    }
15589
15590    /**
15591     * <p>Frees the resources used by the drawing cache. If you call
15592     * {@link #buildDrawingCache()} manually without calling
15593     * {@link #setDrawingCacheEnabled(boolean) setDrawingCacheEnabled(true)}, you
15594     * should cleanup the cache with this method afterwards.</p>
15595     *
15596     * @see #setDrawingCacheEnabled(boolean)
15597     * @see #buildDrawingCache()
15598     * @see #getDrawingCache()
15599     */
15600    public void destroyDrawingCache() {
15601        if (mDrawingCache != null) {
15602            mDrawingCache.recycle();
15603            mDrawingCache = null;
15604        }
15605        if (mUnscaledDrawingCache != null) {
15606            mUnscaledDrawingCache.recycle();
15607            mUnscaledDrawingCache = null;
15608        }
15609    }
15610
15611    /**
15612     * Setting a solid background color for the drawing cache's bitmaps will improve
15613     * performance and memory usage. Note, though that this should only be used if this
15614     * view will always be drawn on top of a solid color.
15615     *
15616     * @param color The background color to use for the drawing cache's bitmap
15617     *
15618     * @see #setDrawingCacheEnabled(boolean)
15619     * @see #buildDrawingCache()
15620     * @see #getDrawingCache()
15621     */
15622    public void setDrawingCacheBackgroundColor(@ColorInt int color) {
15623        if (color != mDrawingCacheBackgroundColor) {
15624            mDrawingCacheBackgroundColor = color;
15625            mPrivateFlags &= ~PFLAG_DRAWING_CACHE_VALID;
15626        }
15627    }
15628
15629    /**
15630     * @see #setDrawingCacheBackgroundColor(int)
15631     *
15632     * @return The background color to used for the drawing cache's bitmap
15633     */
15634    @ColorInt
15635    public int getDrawingCacheBackgroundColor() {
15636        return mDrawingCacheBackgroundColor;
15637    }
15638
15639    /**
15640     * <p>Calling this method is equivalent to calling <code>buildDrawingCache(false)</code>.</p>
15641     *
15642     * @see #buildDrawingCache(boolean)
15643     */
15644    public void buildDrawingCache() {
15645        buildDrawingCache(false);
15646    }
15647
15648    /**
15649     * <p>Forces the drawing cache to be built if the drawing cache is invalid.</p>
15650     *
15651     * <p>If you call {@link #buildDrawingCache()} manually without calling
15652     * {@link #setDrawingCacheEnabled(boolean) setDrawingCacheEnabled(true)}, you
15653     * should cleanup the cache by calling {@link #destroyDrawingCache()} afterwards.</p>
15654     *
15655     * <p>Note about auto scaling in compatibility mode: When auto scaling is not enabled,
15656     * this method will create a bitmap of the same size as this view. Because this bitmap
15657     * will be drawn scaled by the parent ViewGroup, the result on screen might show
15658     * scaling artifacts. To avoid such artifacts, you should call this method by setting
15659     * the auto scaling to true. Doing so, however, will generate a bitmap of a different
15660     * size than the view. This implies that your application must be able to handle this
15661     * size.</p>
15662     *
15663     * <p>You should avoid calling this method when hardware acceleration is enabled. If
15664     * you do not need the drawing cache bitmap, calling this method will increase memory
15665     * usage and cause the view to be rendered in software once, thus negatively impacting
15666     * performance.</p>
15667     *
15668     * @see #getDrawingCache()
15669     * @see #destroyDrawingCache()
15670     */
15671    public void buildDrawingCache(boolean autoScale) {
15672        if ((mPrivateFlags & PFLAG_DRAWING_CACHE_VALID) == 0 || (autoScale ?
15673                mDrawingCache == null : mUnscaledDrawingCache == null)) {
15674            if (Trace.isTagEnabled(Trace.TRACE_TAG_VIEW)) {
15675                Trace.traceBegin(Trace.TRACE_TAG_VIEW,
15676                        "buildDrawingCache/SW Layer for " + getClass().getSimpleName());
15677            }
15678            try {
15679                buildDrawingCacheImpl(autoScale);
15680            } finally {
15681                Trace.traceEnd(Trace.TRACE_TAG_VIEW);
15682            }
15683        }
15684    }
15685
15686    /**
15687     * private, internal implementation of buildDrawingCache, used to enable tracing
15688     */
15689    private void buildDrawingCacheImpl(boolean autoScale) {
15690        mCachingFailed = false;
15691
15692        int width = mRight - mLeft;
15693        int height = mBottom - mTop;
15694
15695        final AttachInfo attachInfo = mAttachInfo;
15696        final boolean scalingRequired = attachInfo != null && attachInfo.mScalingRequired;
15697
15698        if (autoScale && scalingRequired) {
15699            width = (int) ((width * attachInfo.mApplicationScale) + 0.5f);
15700            height = (int) ((height * attachInfo.mApplicationScale) + 0.5f);
15701        }
15702
15703        final int drawingCacheBackgroundColor = mDrawingCacheBackgroundColor;
15704        final boolean opaque = drawingCacheBackgroundColor != 0 || isOpaque();
15705        final boolean use32BitCache = attachInfo != null && attachInfo.mUse32BitDrawingCache;
15706
15707        final long projectedBitmapSize = width * height * (opaque && !use32BitCache ? 2 : 4);
15708        final long drawingCacheSize =
15709                ViewConfiguration.get(mContext).getScaledMaximumDrawingCacheSize();
15710        if (width <= 0 || height <= 0 || projectedBitmapSize > drawingCacheSize) {
15711            if (width > 0 && height > 0) {
15712                Log.w(VIEW_LOG_TAG, getClass().getSimpleName() + " not displayed because it is"
15713                        + " too large to fit into a software layer (or drawing cache), needs "
15714                        + projectedBitmapSize + " bytes, only "
15715                        + drawingCacheSize + " available");
15716            }
15717            destroyDrawingCache();
15718            mCachingFailed = true;
15719            return;
15720        }
15721
15722        boolean clear = true;
15723        Bitmap bitmap = autoScale ? mDrawingCache : mUnscaledDrawingCache;
15724
15725        if (bitmap == null || bitmap.getWidth() != width || bitmap.getHeight() != height) {
15726            Bitmap.Config quality;
15727            if (!opaque) {
15728                // Never pick ARGB_4444 because it looks awful
15729                // Keep the DRAWING_CACHE_QUALITY_LOW flag just in case
15730                switch (mViewFlags & DRAWING_CACHE_QUALITY_MASK) {
15731                    case DRAWING_CACHE_QUALITY_AUTO:
15732                    case DRAWING_CACHE_QUALITY_LOW:
15733                    case DRAWING_CACHE_QUALITY_HIGH:
15734                    default:
15735                        quality = Bitmap.Config.ARGB_8888;
15736                        break;
15737                }
15738            } else {
15739                // Optimization for translucent windows
15740                // If the window is translucent, use a 32 bits bitmap to benefit from memcpy()
15741                quality = use32BitCache ? Bitmap.Config.ARGB_8888 : Bitmap.Config.RGB_565;
15742            }
15743
15744            // Try to cleanup memory
15745            if (bitmap != null) bitmap.recycle();
15746
15747            try {
15748                bitmap = Bitmap.createBitmap(mResources.getDisplayMetrics(),
15749                        width, height, quality);
15750                bitmap.setDensity(getResources().getDisplayMetrics().densityDpi);
15751                if (autoScale) {
15752                    mDrawingCache = bitmap;
15753                } else {
15754                    mUnscaledDrawingCache = bitmap;
15755                }
15756                if (opaque && use32BitCache) bitmap.setHasAlpha(false);
15757            } catch (OutOfMemoryError e) {
15758                // If there is not enough memory to create the bitmap cache, just
15759                // ignore the issue as bitmap caches are not required to draw the
15760                // view hierarchy
15761                if (autoScale) {
15762                    mDrawingCache = null;
15763                } else {
15764                    mUnscaledDrawingCache = null;
15765                }
15766                mCachingFailed = true;
15767                return;
15768            }
15769
15770            clear = drawingCacheBackgroundColor != 0;
15771        }
15772
15773        Canvas canvas;
15774        if (attachInfo != null) {
15775            canvas = attachInfo.mCanvas;
15776            if (canvas == null) {
15777                canvas = new Canvas();
15778            }
15779            canvas.setBitmap(bitmap);
15780            // Temporarily clobber the cached Canvas in case one of our children
15781            // is also using a drawing cache. Without this, the children would
15782            // steal the canvas by attaching their own bitmap to it and bad, bad
15783            // thing would happen (invisible views, corrupted drawings, etc.)
15784            attachInfo.mCanvas = null;
15785        } else {
15786            // This case should hopefully never or seldom happen
15787            canvas = new Canvas(bitmap);
15788        }
15789
15790        if (clear) {
15791            bitmap.eraseColor(drawingCacheBackgroundColor);
15792        }
15793
15794        computeScroll();
15795        final int restoreCount = canvas.save();
15796
15797        if (autoScale && scalingRequired) {
15798            final float scale = attachInfo.mApplicationScale;
15799            canvas.scale(scale, scale);
15800        }
15801
15802        canvas.translate(-mScrollX, -mScrollY);
15803
15804        mPrivateFlags |= PFLAG_DRAWN;
15805        if (mAttachInfo == null || !mAttachInfo.mHardwareAccelerated ||
15806                mLayerType != LAYER_TYPE_NONE) {
15807            mPrivateFlags |= PFLAG_DRAWING_CACHE_VALID;
15808        }
15809
15810        // Fast path for layouts with no backgrounds
15811        if ((mPrivateFlags & PFLAG_SKIP_DRAW) == PFLAG_SKIP_DRAW) {
15812            mPrivateFlags &= ~PFLAG_DIRTY_MASK;
15813            dispatchDraw(canvas);
15814            if (mOverlay != null && !mOverlay.isEmpty()) {
15815                mOverlay.getOverlayView().draw(canvas);
15816            }
15817        } else {
15818            draw(canvas);
15819        }
15820
15821        canvas.restoreToCount(restoreCount);
15822        canvas.setBitmap(null);
15823
15824        if (attachInfo != null) {
15825            // Restore the cached Canvas for our siblings
15826            attachInfo.mCanvas = canvas;
15827        }
15828    }
15829
15830    /**
15831     * Create a snapshot of the view into a bitmap.  We should probably make
15832     * some form of this public, but should think about the API.
15833     */
15834    Bitmap createSnapshot(Bitmap.Config quality, int backgroundColor, boolean skipChildren) {
15835        int width = mRight - mLeft;
15836        int height = mBottom - mTop;
15837
15838        final AttachInfo attachInfo = mAttachInfo;
15839        final float scale = attachInfo != null ? attachInfo.mApplicationScale : 1.0f;
15840        width = (int) ((width * scale) + 0.5f);
15841        height = (int) ((height * scale) + 0.5f);
15842
15843        Bitmap bitmap = Bitmap.createBitmap(mResources.getDisplayMetrics(),
15844                width > 0 ? width : 1, height > 0 ? height : 1, quality);
15845        if (bitmap == null) {
15846            throw new OutOfMemoryError();
15847        }
15848
15849        Resources resources = getResources();
15850        if (resources != null) {
15851            bitmap.setDensity(resources.getDisplayMetrics().densityDpi);
15852        }
15853
15854        Canvas canvas;
15855        if (attachInfo != null) {
15856            canvas = attachInfo.mCanvas;
15857            if (canvas == null) {
15858                canvas = new Canvas();
15859            }
15860            canvas.setBitmap(bitmap);
15861            // Temporarily clobber the cached Canvas in case one of our children
15862            // is also using a drawing cache. Without this, the children would
15863            // steal the canvas by attaching their own bitmap to it and bad, bad
15864            // things would happen (invisible views, corrupted drawings, etc.)
15865            attachInfo.mCanvas = null;
15866        } else {
15867            // This case should hopefully never or seldom happen
15868            canvas = new Canvas(bitmap);
15869        }
15870
15871        if ((backgroundColor & 0xff000000) != 0) {
15872            bitmap.eraseColor(backgroundColor);
15873        }
15874
15875        computeScroll();
15876        final int restoreCount = canvas.save();
15877        canvas.scale(scale, scale);
15878        canvas.translate(-mScrollX, -mScrollY);
15879
15880        // Temporarily remove the dirty mask
15881        int flags = mPrivateFlags;
15882        mPrivateFlags &= ~PFLAG_DIRTY_MASK;
15883
15884        // Fast path for layouts with no backgrounds
15885        if ((mPrivateFlags & PFLAG_SKIP_DRAW) == PFLAG_SKIP_DRAW) {
15886            dispatchDraw(canvas);
15887            if (mOverlay != null && !mOverlay.isEmpty()) {
15888                mOverlay.getOverlayView().draw(canvas);
15889            }
15890        } else {
15891            draw(canvas);
15892        }
15893
15894        mPrivateFlags = flags;
15895
15896        canvas.restoreToCount(restoreCount);
15897        canvas.setBitmap(null);
15898
15899        if (attachInfo != null) {
15900            // Restore the cached Canvas for our siblings
15901            attachInfo.mCanvas = canvas;
15902        }
15903
15904        return bitmap;
15905    }
15906
15907    /**
15908     * Indicates whether this View is currently in edit mode. A View is usually
15909     * in edit mode when displayed within a developer tool. For instance, if
15910     * this View is being drawn by a visual user interface builder, this method
15911     * should return true.
15912     *
15913     * Subclasses should check the return value of this method to provide
15914     * different behaviors if their normal behavior might interfere with the
15915     * host environment. For instance: the class spawns a thread in its
15916     * constructor, the drawing code relies on device-specific features, etc.
15917     *
15918     * This method is usually checked in the drawing code of custom widgets.
15919     *
15920     * @return True if this View is in edit mode, false otherwise.
15921     */
15922    public boolean isInEditMode() {
15923        return false;
15924    }
15925
15926    /**
15927     * If the View draws content inside its padding and enables fading edges,
15928     * it needs to support padding offsets. Padding offsets are added to the
15929     * fading edges to extend the length of the fade so that it covers pixels
15930     * drawn inside the padding.
15931     *
15932     * Subclasses of this class should override this method if they need
15933     * to draw content inside the padding.
15934     *
15935     * @return True if padding offset must be applied, false otherwise.
15936     *
15937     * @see #getLeftPaddingOffset()
15938     * @see #getRightPaddingOffset()
15939     * @see #getTopPaddingOffset()
15940     * @see #getBottomPaddingOffset()
15941     *
15942     * @since CURRENT
15943     */
15944    protected boolean isPaddingOffsetRequired() {
15945        return false;
15946    }
15947
15948    /**
15949     * Amount by which to extend the left fading region. Called only when
15950     * {@link #isPaddingOffsetRequired()} returns true.
15951     *
15952     * @return The left padding offset in pixels.
15953     *
15954     * @see #isPaddingOffsetRequired()
15955     *
15956     * @since CURRENT
15957     */
15958    protected int getLeftPaddingOffset() {
15959        return 0;
15960    }
15961
15962    /**
15963     * Amount by which to extend the right fading region. Called only when
15964     * {@link #isPaddingOffsetRequired()} returns true.
15965     *
15966     * @return The right padding offset in pixels.
15967     *
15968     * @see #isPaddingOffsetRequired()
15969     *
15970     * @since CURRENT
15971     */
15972    protected int getRightPaddingOffset() {
15973        return 0;
15974    }
15975
15976    /**
15977     * Amount by which to extend the top fading region. Called only when
15978     * {@link #isPaddingOffsetRequired()} returns true.
15979     *
15980     * @return The top padding offset in pixels.
15981     *
15982     * @see #isPaddingOffsetRequired()
15983     *
15984     * @since CURRENT
15985     */
15986    protected int getTopPaddingOffset() {
15987        return 0;
15988    }
15989
15990    /**
15991     * Amount by which to extend the bottom fading region. Called only when
15992     * {@link #isPaddingOffsetRequired()} returns true.
15993     *
15994     * @return The bottom padding offset in pixels.
15995     *
15996     * @see #isPaddingOffsetRequired()
15997     *
15998     * @since CURRENT
15999     */
16000    protected int getBottomPaddingOffset() {
16001        return 0;
16002    }
16003
16004    /**
16005     * @hide
16006     * @param offsetRequired
16007     */
16008    protected int getFadeTop(boolean offsetRequired) {
16009        int top = mPaddingTop;
16010        if (offsetRequired) top += getTopPaddingOffset();
16011        return top;
16012    }
16013
16014    /**
16015     * @hide
16016     * @param offsetRequired
16017     */
16018    protected int getFadeHeight(boolean offsetRequired) {
16019        int padding = mPaddingTop;
16020        if (offsetRequired) padding += getTopPaddingOffset();
16021        return mBottom - mTop - mPaddingBottom - padding;
16022    }
16023
16024    /**
16025     * <p>Indicates whether this view is attached to a hardware accelerated
16026     * window or not.</p>
16027     *
16028     * <p>Even if this method returns true, it does not mean that every call
16029     * to {@link #draw(android.graphics.Canvas)} will be made with an hardware
16030     * accelerated {@link android.graphics.Canvas}. For instance, if this view
16031     * is drawn onto an offscreen {@link android.graphics.Bitmap} and its
16032     * window is hardware accelerated,
16033     * {@link android.graphics.Canvas#isHardwareAccelerated()} will likely
16034     * return false, and this method will return true.</p>
16035     *
16036     * @return True if the view is attached to a window and the window is
16037     *         hardware accelerated; false in any other case.
16038     */
16039    @ViewDebug.ExportedProperty(category = "drawing")
16040    public boolean isHardwareAccelerated() {
16041        return mAttachInfo != null && mAttachInfo.mHardwareAccelerated;
16042    }
16043
16044    /**
16045     * Sets a rectangular area on this view to which the view will be clipped
16046     * when it is drawn. Setting the value to null will remove the clip bounds
16047     * and the view will draw normally, using its full bounds.
16048     *
16049     * @param clipBounds The rectangular area, in the local coordinates of
16050     * this view, to which future drawing operations will be clipped.
16051     */
16052    public void setClipBounds(Rect clipBounds) {
16053        if (clipBounds == mClipBounds
16054                || (clipBounds != null && clipBounds.equals(mClipBounds))) {
16055            return;
16056        }
16057        if (clipBounds != null) {
16058            if (mClipBounds == null) {
16059                mClipBounds = new Rect(clipBounds);
16060            } else {
16061                mClipBounds.set(clipBounds);
16062            }
16063        } else {
16064            mClipBounds = null;
16065        }
16066        mRenderNode.setClipBounds(mClipBounds);
16067        invalidateViewProperty(false, false);
16068    }
16069
16070    /**
16071     * Returns a copy of the current {@link #setClipBounds(Rect) clipBounds}.
16072     *
16073     * @return A copy of the current clip bounds if clip bounds are set,
16074     * otherwise null.
16075     */
16076    public Rect getClipBounds() {
16077        return (mClipBounds != null) ? new Rect(mClipBounds) : null;
16078    }
16079
16080
16081    /**
16082     * Populates an output rectangle with the clip bounds of the view,
16083     * returning {@code true} if successful or {@code false} if the view's
16084     * clip bounds are {@code null}.
16085     *
16086     * @param outRect rectangle in which to place the clip bounds of the view
16087     * @return {@code true} if successful or {@code false} if the view's
16088     *         clip bounds are {@code null}
16089     */
16090    public boolean getClipBounds(Rect outRect) {
16091        if (mClipBounds != null) {
16092            outRect.set(mClipBounds);
16093            return true;
16094        }
16095        return false;
16096    }
16097
16098    /**
16099     * Utility function, called by draw(canvas, parent, drawingTime) to handle the less common
16100     * case of an active Animation being run on the view.
16101     */
16102    private boolean applyLegacyAnimation(ViewGroup parent, long drawingTime,
16103            Animation a, boolean scalingRequired) {
16104        Transformation invalidationTransform;
16105        final int flags = parent.mGroupFlags;
16106        final boolean initialized = a.isInitialized();
16107        if (!initialized) {
16108            a.initialize(mRight - mLeft, mBottom - mTop, parent.getWidth(), parent.getHeight());
16109            a.initializeInvalidateRegion(0, 0, mRight - mLeft, mBottom - mTop);
16110            if (mAttachInfo != null) a.setListenerHandler(mAttachInfo.mHandler);
16111            onAnimationStart();
16112        }
16113
16114        final Transformation t = parent.getChildTransformation();
16115        boolean more = a.getTransformation(drawingTime, t, 1f);
16116        if (scalingRequired && mAttachInfo.mApplicationScale != 1f) {
16117            if (parent.mInvalidationTransformation == null) {
16118                parent.mInvalidationTransformation = new Transformation();
16119            }
16120            invalidationTransform = parent.mInvalidationTransformation;
16121            a.getTransformation(drawingTime, invalidationTransform, 1f);
16122        } else {
16123            invalidationTransform = t;
16124        }
16125
16126        if (more) {
16127            if (!a.willChangeBounds()) {
16128                if ((flags & (ViewGroup.FLAG_OPTIMIZE_INVALIDATE | ViewGroup.FLAG_ANIMATION_DONE)) ==
16129                        ViewGroup.FLAG_OPTIMIZE_INVALIDATE) {
16130                    parent.mGroupFlags |= ViewGroup.FLAG_INVALIDATE_REQUIRED;
16131                } else if ((flags & ViewGroup.FLAG_INVALIDATE_REQUIRED) == 0) {
16132                    // The child need to draw an animation, potentially offscreen, so
16133                    // make sure we do not cancel invalidate requests
16134                    parent.mPrivateFlags |= PFLAG_DRAW_ANIMATION;
16135                    parent.invalidate(mLeft, mTop, mRight, mBottom);
16136                }
16137            } else {
16138                if (parent.mInvalidateRegion == null) {
16139                    parent.mInvalidateRegion = new RectF();
16140                }
16141                final RectF region = parent.mInvalidateRegion;
16142                a.getInvalidateRegion(0, 0, mRight - mLeft, mBottom - mTop, region,
16143                        invalidationTransform);
16144
16145                // The child need to draw an animation, potentially offscreen, so
16146                // make sure we do not cancel invalidate requests
16147                parent.mPrivateFlags |= PFLAG_DRAW_ANIMATION;
16148
16149                final int left = mLeft + (int) region.left;
16150                final int top = mTop + (int) region.top;
16151                parent.invalidate(left, top, left + (int) (region.width() + .5f),
16152                        top + (int) (region.height() + .5f));
16153            }
16154        }
16155        return more;
16156    }
16157
16158    /**
16159     * This method is called by getDisplayList() when a display list is recorded for a View.
16160     * It pushes any properties to the RenderNode that aren't managed by the RenderNode.
16161     */
16162    void setDisplayListProperties(RenderNode renderNode) {
16163        if (renderNode != null) {
16164            renderNode.setHasOverlappingRendering(hasOverlappingRendering());
16165            renderNode.setClipToBounds(mParent instanceof ViewGroup
16166                    && ((ViewGroup) mParent).getClipChildren());
16167
16168            float alpha = 1;
16169            if (mParent instanceof ViewGroup && (((ViewGroup) mParent).mGroupFlags &
16170                    ViewGroup.FLAG_SUPPORT_STATIC_TRANSFORMATIONS) != 0) {
16171                ViewGroup parentVG = (ViewGroup) mParent;
16172                final Transformation t = parentVG.getChildTransformation();
16173                if (parentVG.getChildStaticTransformation(this, t)) {
16174                    final int transformType = t.getTransformationType();
16175                    if (transformType != Transformation.TYPE_IDENTITY) {
16176                        if ((transformType & Transformation.TYPE_ALPHA) != 0) {
16177                            alpha = t.getAlpha();
16178                        }
16179                        if ((transformType & Transformation.TYPE_MATRIX) != 0) {
16180                            renderNode.setStaticMatrix(t.getMatrix());
16181                        }
16182                    }
16183                }
16184            }
16185            if (mTransformationInfo != null) {
16186                alpha *= getFinalAlpha();
16187                if (alpha < 1) {
16188                    final int multipliedAlpha = (int) (255 * alpha);
16189                    if (onSetAlpha(multipliedAlpha)) {
16190                        alpha = 1;
16191                    }
16192                }
16193                renderNode.setAlpha(alpha);
16194            } else if (alpha < 1) {
16195                renderNode.setAlpha(alpha);
16196            }
16197        }
16198    }
16199
16200    /**
16201     * This method is called by ViewGroup.drawChild() to have each child view draw itself.
16202     *
16203     * This is where the View specializes rendering behavior based on layer type,
16204     * and hardware acceleration.
16205     */
16206    boolean draw(Canvas canvas, ViewGroup parent, long drawingTime) {
16207        final boolean hardwareAcceleratedCanvas = canvas.isHardwareAccelerated();
16208        /* If an attached view draws to a HW canvas, it may use its RenderNode + DisplayList.
16209         *
16210         * If a view is dettached, its DisplayList shouldn't exist. If the canvas isn't
16211         * HW accelerated, it can't handle drawing RenderNodes.
16212         */
16213        boolean drawingWithRenderNode = mAttachInfo != null
16214                && mAttachInfo.mHardwareAccelerated
16215                && hardwareAcceleratedCanvas;
16216
16217        boolean more = false;
16218        final boolean childHasIdentityMatrix = hasIdentityMatrix();
16219        final int parentFlags = parent.mGroupFlags;
16220
16221        if ((parentFlags & ViewGroup.FLAG_CLEAR_TRANSFORMATION) != 0) {
16222            parent.getChildTransformation().clear();
16223            parent.mGroupFlags &= ~ViewGroup.FLAG_CLEAR_TRANSFORMATION;
16224        }
16225
16226        Transformation transformToApply = null;
16227        boolean concatMatrix = false;
16228        final boolean scalingRequired = mAttachInfo != null && mAttachInfo.mScalingRequired;
16229        final Animation a = getAnimation();
16230        if (a != null) {
16231            more = applyLegacyAnimation(parent, drawingTime, a, scalingRequired);
16232            concatMatrix = a.willChangeTransformationMatrix();
16233            if (concatMatrix) {
16234                mPrivateFlags3 |= PFLAG3_VIEW_IS_ANIMATING_TRANSFORM;
16235            }
16236            transformToApply = parent.getChildTransformation();
16237        } else {
16238            if ((mPrivateFlags3 & PFLAG3_VIEW_IS_ANIMATING_TRANSFORM) != 0) {
16239                // No longer animating: clear out old animation matrix
16240                mRenderNode.setAnimationMatrix(null);
16241                mPrivateFlags3 &= ~PFLAG3_VIEW_IS_ANIMATING_TRANSFORM;
16242            }
16243            if (!drawingWithRenderNode
16244                    && (parentFlags & ViewGroup.FLAG_SUPPORT_STATIC_TRANSFORMATIONS) != 0) {
16245                final Transformation t = parent.getChildTransformation();
16246                final boolean hasTransform = parent.getChildStaticTransformation(this, t);
16247                if (hasTransform) {
16248                    final int transformType = t.getTransformationType();
16249                    transformToApply = transformType != Transformation.TYPE_IDENTITY ? t : null;
16250                    concatMatrix = (transformType & Transformation.TYPE_MATRIX) != 0;
16251                }
16252            }
16253        }
16254
16255        concatMatrix |= !childHasIdentityMatrix;
16256
16257        // Sets the flag as early as possible to allow draw() implementations
16258        // to call invalidate() successfully when doing animations
16259        mPrivateFlags |= PFLAG_DRAWN;
16260
16261        if (!concatMatrix &&
16262                (parentFlags & (ViewGroup.FLAG_SUPPORT_STATIC_TRANSFORMATIONS |
16263                        ViewGroup.FLAG_CLIP_CHILDREN)) == ViewGroup.FLAG_CLIP_CHILDREN &&
16264                canvas.quickReject(mLeft, mTop, mRight, mBottom, Canvas.EdgeType.BW) &&
16265                (mPrivateFlags & PFLAG_DRAW_ANIMATION) == 0) {
16266            mPrivateFlags2 |= PFLAG2_VIEW_QUICK_REJECTED;
16267            return more;
16268        }
16269        mPrivateFlags2 &= ~PFLAG2_VIEW_QUICK_REJECTED;
16270
16271        if (hardwareAcceleratedCanvas) {
16272            // Clear INVALIDATED flag to allow invalidation to occur during rendering, but
16273            // retain the flag's value temporarily in the mRecreateDisplayList flag
16274            mRecreateDisplayList = (mPrivateFlags & PFLAG_INVALIDATED) != 0;
16275            mPrivateFlags &= ~PFLAG_INVALIDATED;
16276        }
16277
16278        RenderNode renderNode = null;
16279        Bitmap cache = null;
16280        int layerType = getLayerType(); // TODO: signify cache state with just 'cache' local
16281        if (layerType == LAYER_TYPE_SOFTWARE
16282                || (!drawingWithRenderNode && layerType != LAYER_TYPE_NONE)) {
16283            // If not drawing with RenderNode, treat HW layers as SW
16284            layerType = LAYER_TYPE_SOFTWARE;
16285            buildDrawingCache(true);
16286            cache = getDrawingCache(true);
16287        }
16288
16289        if (drawingWithRenderNode) {
16290            // Delay getting the display list until animation-driven alpha values are
16291            // set up and possibly passed on to the view
16292            renderNode = updateDisplayListIfDirty();
16293            if (!renderNode.isValid()) {
16294                // Uncommon, but possible. If a view is removed from the hierarchy during the call
16295                // to getDisplayList(), the display list will be marked invalid and we should not
16296                // try to use it again.
16297                renderNode = null;
16298                drawingWithRenderNode = false;
16299            }
16300        }
16301
16302        int sx = 0;
16303        int sy = 0;
16304        if (!drawingWithRenderNode) {
16305            computeScroll();
16306            sx = mScrollX;
16307            sy = mScrollY;
16308        }
16309
16310        final boolean drawingWithDrawingCache = cache != null && !drawingWithRenderNode;
16311        final boolean offsetForScroll = cache == null && !drawingWithRenderNode;
16312
16313        int restoreTo = -1;
16314        if (!drawingWithRenderNode || transformToApply != null) {
16315            restoreTo = canvas.save();
16316        }
16317        if (offsetForScroll) {
16318            canvas.translate(mLeft - sx, mTop - sy);
16319        } else {
16320            if (!drawingWithRenderNode) {
16321                canvas.translate(mLeft, mTop);
16322            }
16323            if (scalingRequired) {
16324                if (drawingWithRenderNode) {
16325                    // TODO: Might not need this if we put everything inside the DL
16326                    restoreTo = canvas.save();
16327                }
16328                // mAttachInfo cannot be null, otherwise scalingRequired == false
16329                final float scale = 1.0f / mAttachInfo.mApplicationScale;
16330                canvas.scale(scale, scale);
16331            }
16332        }
16333
16334        float alpha = drawingWithRenderNode ? 1 : (getAlpha() * getTransitionAlpha());
16335        if (transformToApply != null
16336                || alpha < 1
16337                || !hasIdentityMatrix()
16338                || (mPrivateFlags3 & PFLAG3_VIEW_IS_ANIMATING_ALPHA) != 0) {
16339            if (transformToApply != null || !childHasIdentityMatrix) {
16340                int transX = 0;
16341                int transY = 0;
16342
16343                if (offsetForScroll) {
16344                    transX = -sx;
16345                    transY = -sy;
16346                }
16347
16348                if (transformToApply != null) {
16349                    if (concatMatrix) {
16350                        if (drawingWithRenderNode) {
16351                            renderNode.setAnimationMatrix(transformToApply.getMatrix());
16352                        } else {
16353                            // Undo the scroll translation, apply the transformation matrix,
16354                            // then redo the scroll translate to get the correct result.
16355                            canvas.translate(-transX, -transY);
16356                            canvas.concat(transformToApply.getMatrix());
16357                            canvas.translate(transX, transY);
16358                        }
16359                        parent.mGroupFlags |= ViewGroup.FLAG_CLEAR_TRANSFORMATION;
16360                    }
16361
16362                    float transformAlpha = transformToApply.getAlpha();
16363                    if (transformAlpha < 1) {
16364                        alpha *= transformAlpha;
16365                        parent.mGroupFlags |= ViewGroup.FLAG_CLEAR_TRANSFORMATION;
16366                    }
16367                }
16368
16369                if (!childHasIdentityMatrix && !drawingWithRenderNode) {
16370                    canvas.translate(-transX, -transY);
16371                    canvas.concat(getMatrix());
16372                    canvas.translate(transX, transY);
16373                }
16374            }
16375
16376            // Deal with alpha if it is or used to be <1
16377            if (alpha < 1 || (mPrivateFlags3 & PFLAG3_VIEW_IS_ANIMATING_ALPHA) != 0) {
16378                if (alpha < 1) {
16379                    mPrivateFlags3 |= PFLAG3_VIEW_IS_ANIMATING_ALPHA;
16380                } else {
16381                    mPrivateFlags3 &= ~PFLAG3_VIEW_IS_ANIMATING_ALPHA;
16382                }
16383                parent.mGroupFlags |= ViewGroup.FLAG_CLEAR_TRANSFORMATION;
16384                if (!drawingWithDrawingCache) {
16385                    final int multipliedAlpha = (int) (255 * alpha);
16386                    if (!onSetAlpha(multipliedAlpha)) {
16387                        if (drawingWithRenderNode) {
16388                            renderNode.setAlpha(alpha * getAlpha() * getTransitionAlpha());
16389                        } else if (layerType == LAYER_TYPE_NONE) {
16390                            canvas.saveLayerAlpha(sx, sy, sx + getWidth(), sy + getHeight(),
16391                                    multipliedAlpha);
16392                        }
16393                    } else {
16394                        // Alpha is handled by the child directly, clobber the layer's alpha
16395                        mPrivateFlags |= PFLAG_ALPHA_SET;
16396                    }
16397                }
16398            }
16399        } else if ((mPrivateFlags & PFLAG_ALPHA_SET) == PFLAG_ALPHA_SET) {
16400            onSetAlpha(255);
16401            mPrivateFlags &= ~PFLAG_ALPHA_SET;
16402        }
16403
16404        if (!drawingWithRenderNode) {
16405            // apply clips directly, since RenderNode won't do it for this draw
16406            if ((parentFlags & ViewGroup.FLAG_CLIP_CHILDREN) != 0 && cache == null) {
16407                if (offsetForScroll) {
16408                    canvas.clipRect(sx, sy, sx + getWidth(), sy + getHeight());
16409                } else {
16410                    if (!scalingRequired || cache == null) {
16411                        canvas.clipRect(0, 0, getWidth(), getHeight());
16412                    } else {
16413                        canvas.clipRect(0, 0, cache.getWidth(), cache.getHeight());
16414                    }
16415                }
16416            }
16417
16418            if (mClipBounds != null) {
16419                // clip bounds ignore scroll
16420                canvas.clipRect(mClipBounds);
16421            }
16422        }
16423
16424        if (!drawingWithDrawingCache) {
16425            if (drawingWithRenderNode) {
16426                mPrivateFlags &= ~PFLAG_DIRTY_MASK;
16427                ((DisplayListCanvas) canvas).drawRenderNode(renderNode);
16428            } else {
16429                // Fast path for layouts with no backgrounds
16430                if ((mPrivateFlags & PFLAG_SKIP_DRAW) == PFLAG_SKIP_DRAW) {
16431                    mPrivateFlags &= ~PFLAG_DIRTY_MASK;
16432                    dispatchDraw(canvas);
16433                } else {
16434                    draw(canvas);
16435                }
16436            }
16437        } else if (cache != null) {
16438            mPrivateFlags &= ~PFLAG_DIRTY_MASK;
16439            if (layerType == LAYER_TYPE_NONE) {
16440                // no layer paint, use temporary paint to draw bitmap
16441                Paint cachePaint = parent.mCachePaint;
16442                if (cachePaint == null) {
16443                    cachePaint = new Paint();
16444                    cachePaint.setDither(false);
16445                    parent.mCachePaint = cachePaint;
16446                }
16447                cachePaint.setAlpha((int) (alpha * 255));
16448                canvas.drawBitmap(cache, 0.0f, 0.0f, cachePaint);
16449            } else {
16450                // use layer paint to draw the bitmap, merging the two alphas, but also restore
16451                int layerPaintAlpha = mLayerPaint.getAlpha();
16452                mLayerPaint.setAlpha((int) (alpha * layerPaintAlpha));
16453                canvas.drawBitmap(cache, 0.0f, 0.0f, mLayerPaint);
16454                mLayerPaint.setAlpha(layerPaintAlpha);
16455            }
16456        }
16457
16458        if (restoreTo >= 0) {
16459            canvas.restoreToCount(restoreTo);
16460        }
16461
16462        if (a != null && !more) {
16463            if (!hardwareAcceleratedCanvas && !a.getFillAfter()) {
16464                onSetAlpha(255);
16465            }
16466            parent.finishAnimatingView(this, a);
16467        }
16468
16469        if (more && hardwareAcceleratedCanvas) {
16470            if (a.hasAlpha() && (mPrivateFlags & PFLAG_ALPHA_SET) == PFLAG_ALPHA_SET) {
16471                // alpha animations should cause the child to recreate its display list
16472                invalidate(true);
16473            }
16474        }
16475
16476        mRecreateDisplayList = false;
16477
16478        return more;
16479    }
16480
16481    /**
16482     * Manually render this view (and all of its children) to the given Canvas.
16483     * The view must have already done a full layout before this function is
16484     * called.  When implementing a view, implement
16485     * {@link #onDraw(android.graphics.Canvas)} instead of overriding this method.
16486     * If you do need to override this method, call the superclass version.
16487     *
16488     * @param canvas The Canvas to which the View is rendered.
16489     */
16490    @CallSuper
16491    public void draw(Canvas canvas) {
16492        final int privateFlags = mPrivateFlags;
16493        final boolean dirtyOpaque = (privateFlags & PFLAG_DIRTY_MASK) == PFLAG_DIRTY_OPAQUE &&
16494                (mAttachInfo == null || !mAttachInfo.mIgnoreDirtyState);
16495        mPrivateFlags = (privateFlags & ~PFLAG_DIRTY_MASK) | PFLAG_DRAWN;
16496
16497        /*
16498         * Draw traversal performs several drawing steps which must be executed
16499         * in the appropriate order:
16500         *
16501         *      1. Draw the background
16502         *      2. If necessary, save the canvas' layers to prepare for fading
16503         *      3. Draw view's content
16504         *      4. Draw children
16505         *      5. If necessary, draw the fading edges and restore layers
16506         *      6. Draw decorations (scrollbars for instance)
16507         */
16508
16509        // Step 1, draw the background, if needed
16510        int saveCount;
16511
16512        if (!dirtyOpaque) {
16513            drawBackground(canvas);
16514        }
16515
16516        // skip step 2 & 5 if possible (common case)
16517        final int viewFlags = mViewFlags;
16518        boolean horizontalEdges = (viewFlags & FADING_EDGE_HORIZONTAL) != 0;
16519        boolean verticalEdges = (viewFlags & FADING_EDGE_VERTICAL) != 0;
16520        if (!verticalEdges && !horizontalEdges) {
16521            // Step 3, draw the content
16522            if (!dirtyOpaque) onDraw(canvas);
16523
16524            // Step 4, draw the children
16525            dispatchDraw(canvas);
16526
16527            // Overlay is part of the content and draws beneath Foreground
16528            if (mOverlay != null && !mOverlay.isEmpty()) {
16529                mOverlay.getOverlayView().dispatchDraw(canvas);
16530            }
16531
16532            // Step 6, draw decorations (foreground, scrollbars)
16533            onDrawForeground(canvas);
16534
16535            // we're done...
16536            return;
16537        }
16538
16539        /*
16540         * Here we do the full fledged routine...
16541         * (this is an uncommon case where speed matters less,
16542         * this is why we repeat some of the tests that have been
16543         * done above)
16544         */
16545
16546        boolean drawTop = false;
16547        boolean drawBottom = false;
16548        boolean drawLeft = false;
16549        boolean drawRight = false;
16550
16551        float topFadeStrength = 0.0f;
16552        float bottomFadeStrength = 0.0f;
16553        float leftFadeStrength = 0.0f;
16554        float rightFadeStrength = 0.0f;
16555
16556        // Step 2, save the canvas' layers
16557        int paddingLeft = mPaddingLeft;
16558
16559        final boolean offsetRequired = isPaddingOffsetRequired();
16560        if (offsetRequired) {
16561            paddingLeft += getLeftPaddingOffset();
16562        }
16563
16564        int left = mScrollX + paddingLeft;
16565        int right = left + mRight - mLeft - mPaddingRight - paddingLeft;
16566        int top = mScrollY + getFadeTop(offsetRequired);
16567        int bottom = top + getFadeHeight(offsetRequired);
16568
16569        if (offsetRequired) {
16570            right += getRightPaddingOffset();
16571            bottom += getBottomPaddingOffset();
16572        }
16573
16574        final ScrollabilityCache scrollabilityCache = mScrollCache;
16575        final float fadeHeight = scrollabilityCache.fadingEdgeLength;
16576        int length = (int) fadeHeight;
16577
16578        // clip the fade length if top and bottom fades overlap
16579        // overlapping fades produce odd-looking artifacts
16580        if (verticalEdges && (top + length > bottom - length)) {
16581            length = (bottom - top) / 2;
16582        }
16583
16584        // also clip horizontal fades if necessary
16585        if (horizontalEdges && (left + length > right - length)) {
16586            length = (right - left) / 2;
16587        }
16588
16589        if (verticalEdges) {
16590            topFadeStrength = Math.max(0.0f, Math.min(1.0f, getTopFadingEdgeStrength()));
16591            drawTop = topFadeStrength * fadeHeight > 1.0f;
16592            bottomFadeStrength = Math.max(0.0f, Math.min(1.0f, getBottomFadingEdgeStrength()));
16593            drawBottom = bottomFadeStrength * fadeHeight > 1.0f;
16594        }
16595
16596        if (horizontalEdges) {
16597            leftFadeStrength = Math.max(0.0f, Math.min(1.0f, getLeftFadingEdgeStrength()));
16598            drawLeft = leftFadeStrength * fadeHeight > 1.0f;
16599            rightFadeStrength = Math.max(0.0f, Math.min(1.0f, getRightFadingEdgeStrength()));
16600            drawRight = rightFadeStrength * fadeHeight > 1.0f;
16601        }
16602
16603        saveCount = canvas.getSaveCount();
16604
16605        int solidColor = getSolidColor();
16606        if (solidColor == 0) {
16607            final int flags = Canvas.HAS_ALPHA_LAYER_SAVE_FLAG;
16608
16609            if (drawTop) {
16610                canvas.saveLayer(left, top, right, top + length, null, flags);
16611            }
16612
16613            if (drawBottom) {
16614                canvas.saveLayer(left, bottom - length, right, bottom, null, flags);
16615            }
16616
16617            if (drawLeft) {
16618                canvas.saveLayer(left, top, left + length, bottom, null, flags);
16619            }
16620
16621            if (drawRight) {
16622                canvas.saveLayer(right - length, top, right, bottom, null, flags);
16623            }
16624        } else {
16625            scrollabilityCache.setFadeColor(solidColor);
16626        }
16627
16628        // Step 3, draw the content
16629        if (!dirtyOpaque) onDraw(canvas);
16630
16631        // Step 4, draw the children
16632        dispatchDraw(canvas);
16633
16634        // Step 5, draw the fade effect and restore layers
16635        final Paint p = scrollabilityCache.paint;
16636        final Matrix matrix = scrollabilityCache.matrix;
16637        final Shader fade = scrollabilityCache.shader;
16638
16639        if (drawTop) {
16640            matrix.setScale(1, fadeHeight * topFadeStrength);
16641            matrix.postTranslate(left, top);
16642            fade.setLocalMatrix(matrix);
16643            p.setShader(fade);
16644            canvas.drawRect(left, top, right, top + length, p);
16645        }
16646
16647        if (drawBottom) {
16648            matrix.setScale(1, fadeHeight * bottomFadeStrength);
16649            matrix.postRotate(180);
16650            matrix.postTranslate(left, bottom);
16651            fade.setLocalMatrix(matrix);
16652            p.setShader(fade);
16653            canvas.drawRect(left, bottom - length, right, bottom, p);
16654        }
16655
16656        if (drawLeft) {
16657            matrix.setScale(1, fadeHeight * leftFadeStrength);
16658            matrix.postRotate(-90);
16659            matrix.postTranslate(left, top);
16660            fade.setLocalMatrix(matrix);
16661            p.setShader(fade);
16662            canvas.drawRect(left, top, left + length, bottom, p);
16663        }
16664
16665        if (drawRight) {
16666            matrix.setScale(1, fadeHeight * rightFadeStrength);
16667            matrix.postRotate(90);
16668            matrix.postTranslate(right, top);
16669            fade.setLocalMatrix(matrix);
16670            p.setShader(fade);
16671            canvas.drawRect(right - length, top, right, bottom, p);
16672        }
16673
16674        canvas.restoreToCount(saveCount);
16675
16676        // Overlay is part of the content and draws beneath Foreground
16677        if (mOverlay != null && !mOverlay.isEmpty()) {
16678            mOverlay.getOverlayView().dispatchDraw(canvas);
16679        }
16680
16681        // Step 6, draw decorations (foreground, scrollbars)
16682        onDrawForeground(canvas);
16683    }
16684
16685    /**
16686     * Draws the background onto the specified canvas.
16687     *
16688     * @param canvas Canvas on which to draw the background
16689     */
16690    private void drawBackground(Canvas canvas) {
16691        final Drawable background = mBackground;
16692        if (background == null) {
16693            return;
16694        }
16695
16696        setBackgroundBounds();
16697
16698        // Attempt to use a display list if requested.
16699        if (canvas.isHardwareAccelerated() && mAttachInfo != null
16700                && mAttachInfo.mHardwareRenderer != null) {
16701            mBackgroundRenderNode = getDrawableRenderNode(background, mBackgroundRenderNode);
16702
16703            final RenderNode renderNode = mBackgroundRenderNode;
16704            if (renderNode != null && renderNode.isValid()) {
16705                setBackgroundRenderNodeProperties(renderNode);
16706                ((DisplayListCanvas) canvas).drawRenderNode(renderNode);
16707                return;
16708            }
16709        }
16710
16711        final int scrollX = mScrollX;
16712        final int scrollY = mScrollY;
16713        if ((scrollX | scrollY) == 0) {
16714            background.draw(canvas);
16715        } else {
16716            canvas.translate(scrollX, scrollY);
16717            background.draw(canvas);
16718            canvas.translate(-scrollX, -scrollY);
16719        }
16720    }
16721
16722    /**
16723     * Sets the correct background bounds and rebuilds the outline, if needed.
16724     * <p/>
16725     * This is called by LayoutLib.
16726     */
16727    void setBackgroundBounds() {
16728        if (mBackgroundSizeChanged && mBackground != null) {
16729            mBackground.setBounds(0, 0, mRight - mLeft, mBottom - mTop);
16730            mBackgroundSizeChanged = false;
16731            rebuildOutline();
16732        }
16733    }
16734
16735    private void setBackgroundRenderNodeProperties(RenderNode renderNode) {
16736        renderNode.setTranslationX(mScrollX);
16737        renderNode.setTranslationY(mScrollY);
16738    }
16739
16740    /**
16741     * Creates a new display list or updates the existing display list for the
16742     * specified Drawable.
16743     *
16744     * @param drawable Drawable for which to create a display list
16745     * @param renderNode Existing RenderNode, or {@code null}
16746     * @return A valid display list for the specified drawable
16747     */
16748    private RenderNode getDrawableRenderNode(Drawable drawable, RenderNode renderNode) {
16749        if (renderNode == null) {
16750            renderNode = RenderNode.create(drawable.getClass().getName(), this);
16751        }
16752
16753        final Rect bounds = drawable.getBounds();
16754        final int width = bounds.width();
16755        final int height = bounds.height();
16756        final DisplayListCanvas canvas = renderNode.start(width, height);
16757
16758        // Reverse left/top translation done by drawable canvas, which will
16759        // instead be applied by rendernode's LTRB bounds below. This way, the
16760        // drawable's bounds match with its rendernode bounds and its content
16761        // will lie within those bounds in the rendernode tree.
16762        canvas.translate(-bounds.left, -bounds.top);
16763
16764        try {
16765            drawable.draw(canvas);
16766        } finally {
16767            renderNode.end(canvas);
16768        }
16769
16770        // Set up drawable properties that are view-independent.
16771        renderNode.setLeftTopRightBottom(bounds.left, bounds.top, bounds.right, bounds.bottom);
16772        renderNode.setProjectBackwards(drawable.isProjected());
16773        renderNode.setProjectionReceiver(true);
16774        renderNode.setClipToBounds(false);
16775        return renderNode;
16776    }
16777
16778    /**
16779     * Returns the overlay for this view, creating it if it does not yet exist.
16780     * Adding drawables to the overlay will cause them to be displayed whenever
16781     * the view itself is redrawn. Objects in the overlay should be actively
16782     * managed: remove them when they should not be displayed anymore. The
16783     * overlay will always have the same size as its host view.
16784     *
16785     * <p>Note: Overlays do not currently work correctly with {@link
16786     * SurfaceView} or {@link TextureView}; contents in overlays for these
16787     * types of views may not display correctly.</p>
16788     *
16789     * @return The ViewOverlay object for this view.
16790     * @see ViewOverlay
16791     */
16792    public ViewOverlay getOverlay() {
16793        if (mOverlay == null) {
16794            mOverlay = new ViewOverlay(mContext, this);
16795        }
16796        return mOverlay;
16797    }
16798
16799    /**
16800     * Override this if your view is known to always be drawn on top of a solid color background,
16801     * and needs to draw fading edges. Returning a non-zero color enables the view system to
16802     * optimize the drawing of the fading edges. If you do return a non-zero color, the alpha
16803     * should be set to 0xFF.
16804     *
16805     * @see #setVerticalFadingEdgeEnabled(boolean)
16806     * @see #setHorizontalFadingEdgeEnabled(boolean)
16807     *
16808     * @return The known solid color background for this view, or 0 if the color may vary
16809     */
16810    @ViewDebug.ExportedProperty(category = "drawing")
16811    @ColorInt
16812    public int getSolidColor() {
16813        return 0;
16814    }
16815
16816    /**
16817     * Build a human readable string representation of the specified view flags.
16818     *
16819     * @param flags the view flags to convert to a string
16820     * @return a String representing the supplied flags
16821     */
16822    private static String printFlags(int flags) {
16823        String output = "";
16824        int numFlags = 0;
16825        if ((flags & FOCUSABLE_MASK) == FOCUSABLE) {
16826            output += "TAKES_FOCUS";
16827            numFlags++;
16828        }
16829
16830        switch (flags & VISIBILITY_MASK) {
16831        case INVISIBLE:
16832            if (numFlags > 0) {
16833                output += " ";
16834            }
16835            output += "INVISIBLE";
16836            // USELESS HERE numFlags++;
16837            break;
16838        case GONE:
16839            if (numFlags > 0) {
16840                output += " ";
16841            }
16842            output += "GONE";
16843            // USELESS HERE numFlags++;
16844            break;
16845        default:
16846            break;
16847        }
16848        return output;
16849    }
16850
16851    /**
16852     * Build a human readable string representation of the specified private
16853     * view flags.
16854     *
16855     * @param privateFlags the private view flags to convert to a string
16856     * @return a String representing the supplied flags
16857     */
16858    private static String printPrivateFlags(int privateFlags) {
16859        String output = "";
16860        int numFlags = 0;
16861
16862        if ((privateFlags & PFLAG_WANTS_FOCUS) == PFLAG_WANTS_FOCUS) {
16863            output += "WANTS_FOCUS";
16864            numFlags++;
16865        }
16866
16867        if ((privateFlags & PFLAG_FOCUSED) == PFLAG_FOCUSED) {
16868            if (numFlags > 0) {
16869                output += " ";
16870            }
16871            output += "FOCUSED";
16872            numFlags++;
16873        }
16874
16875        if ((privateFlags & PFLAG_SELECTED) == PFLAG_SELECTED) {
16876            if (numFlags > 0) {
16877                output += " ";
16878            }
16879            output += "SELECTED";
16880            numFlags++;
16881        }
16882
16883        if ((privateFlags & PFLAG_IS_ROOT_NAMESPACE) == PFLAG_IS_ROOT_NAMESPACE) {
16884            if (numFlags > 0) {
16885                output += " ";
16886            }
16887            output += "IS_ROOT_NAMESPACE";
16888            numFlags++;
16889        }
16890
16891        if ((privateFlags & PFLAG_HAS_BOUNDS) == PFLAG_HAS_BOUNDS) {
16892            if (numFlags > 0) {
16893                output += " ";
16894            }
16895            output += "HAS_BOUNDS";
16896            numFlags++;
16897        }
16898
16899        if ((privateFlags & PFLAG_DRAWN) == PFLAG_DRAWN) {
16900            if (numFlags > 0) {
16901                output += " ";
16902            }
16903            output += "DRAWN";
16904            // USELESS HERE numFlags++;
16905        }
16906        return output;
16907    }
16908
16909    /**
16910     * <p>Indicates whether or not this view's layout will be requested during
16911     * the next hierarchy layout pass.</p>
16912     *
16913     * @return true if the layout will be forced during next layout pass
16914     */
16915    public boolean isLayoutRequested() {
16916        return (mPrivateFlags & PFLAG_FORCE_LAYOUT) == PFLAG_FORCE_LAYOUT;
16917    }
16918
16919    /**
16920     * Indicates whether or not this view has requested a partial layout that
16921     * may not affect its size or position within its parent. This state will be reset
16922     * the next time this view is laid out.
16923     *
16924     * @return true if partial layout has been requested
16925     */
16926    public final boolean isPartialLayoutRequested() {
16927        return (mPrivateFlags3 & PFLAG3_PARTIAL_LAYOUT_REQUESTED)
16928                == PFLAG3_PARTIAL_LAYOUT_REQUESTED;
16929    }
16930
16931    /**
16932     * Returns true if this view's {@link ViewGroup.LayoutParams LayoutParams} changed
16933     * since the last time this view was successfully laid out. Typically this happens as a
16934     * result of a call to {@link #setLayoutParams(LayoutParams)}.
16935     *
16936     * @return true if this view's LayoutParams changed since last layout.
16937     */
16938    public final boolean didLayoutParamsChange() {
16939        if (sLayoutParamsAlwaysChanged) {
16940            return true;
16941        }
16942        return (mPrivateFlags3 & PFLAG3_LAYOUT_PARAMS_CHANGED) == PFLAG3_LAYOUT_PARAMS_CHANGED;
16943    }
16944
16945    /**
16946     * Return true if o is a ViewGroup that is laying out using optical bounds.
16947     * @hide
16948     */
16949    public static boolean isLayoutModeOptical(Object o) {
16950        return o instanceof ViewGroup && ((ViewGroup) o).isLayoutModeOptical();
16951    }
16952
16953    private boolean setOpticalFrame(int left, int top, int right, int bottom) {
16954        Insets parentInsets = mParent instanceof View ?
16955                ((View) mParent).getOpticalInsets() : Insets.NONE;
16956        Insets childInsets = getOpticalInsets();
16957        return setFrame(
16958                left   + parentInsets.left - childInsets.left,
16959                top    + parentInsets.top  - childInsets.top,
16960                right  + parentInsets.left + childInsets.right,
16961                bottom + parentInsets.top  + childInsets.bottom);
16962    }
16963
16964    /**
16965     * Assign a size and position to a view and all of its
16966     * descendants
16967     *
16968     * <p>This is the second phase of the layout mechanism.
16969     * (The first is measuring). In this phase, each parent calls
16970     * layout on all of its children to position them.
16971     * This is typically done using the child measurements
16972     * that were stored in the measure pass().</p>
16973     *
16974     * <p>Derived classes should not override this method.
16975     * Derived classes with children should override
16976     * onLayout. In that method, they should
16977     * call layout on each of their children.</p>
16978     *
16979     * @param l Left position, relative to parent
16980     * @param t Top position, relative to parent
16981     * @param r Right position, relative to parent
16982     * @param b Bottom position, relative to parent
16983     */
16984    @SuppressWarnings({"unchecked"})
16985    public void layout(int l, int t, int r, int b) {
16986        if ((mPrivateFlags3 & PFLAG3_MEASURE_NEEDED_BEFORE_LAYOUT) != 0) {
16987            onMeasure(mOldWidthMeasureSpec, mOldHeightMeasureSpec);
16988            mPrivateFlags3 &= ~PFLAG3_MEASURE_NEEDED_BEFORE_LAYOUT;
16989        }
16990
16991        int oldL = mLeft;
16992        int oldT = mTop;
16993        int oldB = mBottom;
16994        int oldR = mRight;
16995
16996        boolean changed = isLayoutModeOptical(mParent) ?
16997                setOpticalFrame(l, t, r, b) : setFrame(l, t, r, b);
16998
16999        if (changed || (mPrivateFlags & PFLAG_LAYOUT_REQUIRED) == PFLAG_LAYOUT_REQUIRED) {
17000            onLayout(changed, l, t, r, b);
17001            mPrivateFlags &= ~PFLAG_LAYOUT_REQUIRED;
17002            mPrivateFlags3 &= ~PFLAG3_LAYOUT_PARAMS_CHANGED;
17003
17004            ListenerInfo li = mListenerInfo;
17005            if (li != null && li.mOnLayoutChangeListeners != null) {
17006                ArrayList<OnLayoutChangeListener> listenersCopy =
17007                        (ArrayList<OnLayoutChangeListener>)li.mOnLayoutChangeListeners.clone();
17008                int numListeners = listenersCopy.size();
17009                for (int i = 0; i < numListeners; ++i) {
17010                    listenersCopy.get(i).onLayoutChange(this, l, t, r, b, oldL, oldT, oldR, oldB);
17011                }
17012            }
17013        }
17014
17015        mPrivateFlags &= ~PFLAG_FORCE_LAYOUT;
17016        mPrivateFlags3 &= ~PFLAG3_PARTIAL_LAYOUT_REQUESTED;
17017        mPrivateFlags3 |= PFLAG3_IS_LAID_OUT;
17018    }
17019
17020    /**
17021     * Called from layout when this view should
17022     * assign a size and position to each of its children.
17023     *
17024     * Derived classes with children should override
17025     * this method and call layout on each of
17026     * their children.
17027     * @param changed This is a new size or position for this view
17028     * @param left Left position, relative to parent
17029     * @param top Top position, relative to parent
17030     * @param right Right position, relative to parent
17031     * @param bottom Bottom position, relative to parent
17032     */
17033    protected void onLayout(boolean changed, int left, int top, int right, int bottom) {
17034    }
17035
17036    /**
17037     * Assign a size and position to this view.
17038     *
17039     * This is called from layout.
17040     *
17041     * @param left Left position, relative to parent
17042     * @param top Top position, relative to parent
17043     * @param right Right position, relative to parent
17044     * @param bottom Bottom position, relative to parent
17045     * @return true if the new size and position are different than the
17046     *         previous ones
17047     * {@hide}
17048     */
17049    protected boolean setFrame(int left, int top, int right, int bottom) {
17050        boolean changed = false;
17051
17052        if (DBG) {
17053            Log.d("View", this + " View.setFrame(" + left + "," + top + ","
17054                    + right + "," + bottom + ")");
17055        }
17056
17057        if (mLeft != left || mRight != right || mTop != top || mBottom != bottom) {
17058            changed = true;
17059
17060            // Remember our drawn bit
17061            int drawn = mPrivateFlags & PFLAG_DRAWN;
17062
17063            int oldWidth = mRight - mLeft;
17064            int oldHeight = mBottom - mTop;
17065            int newWidth = right - left;
17066            int newHeight = bottom - top;
17067            boolean sizeChanged = (newWidth != oldWidth) || (newHeight != oldHeight);
17068
17069            // Invalidate our old position
17070            invalidate(sizeChanged);
17071
17072            mLeft = left;
17073            mTop = top;
17074            mRight = right;
17075            mBottom = bottom;
17076            mRenderNode.setLeftTopRightBottom(mLeft, mTop, mRight, mBottom);
17077
17078            mPrivateFlags |= PFLAG_HAS_BOUNDS;
17079
17080
17081            if (sizeChanged) {
17082                sizeChange(newWidth, newHeight, oldWidth, oldHeight);
17083            }
17084
17085            if ((mViewFlags & VISIBILITY_MASK) == VISIBLE || mGhostView != null) {
17086                // If we are visible, force the DRAWN bit to on so that
17087                // this invalidate will go through (at least to our parent).
17088                // This is because someone may have invalidated this view
17089                // before this call to setFrame came in, thereby clearing
17090                // the DRAWN bit.
17091                mPrivateFlags |= PFLAG_DRAWN;
17092                invalidate(sizeChanged);
17093                // parent display list may need to be recreated based on a change in the bounds
17094                // of any child
17095                invalidateParentCaches();
17096            }
17097
17098            // Reset drawn bit to original value (invalidate turns it off)
17099            mPrivateFlags |= drawn;
17100
17101            mBackgroundSizeChanged = true;
17102            if (mForegroundInfo != null) {
17103                mForegroundInfo.mBoundsChanged = true;
17104            }
17105
17106            notifySubtreeAccessibilityStateChangedIfNeeded();
17107        }
17108        return changed;
17109    }
17110
17111    /**
17112     * Same as setFrame, but public and hidden. For use in {@link android.transition.ChangeBounds}.
17113     * @hide
17114     */
17115    public void setLeftTopRightBottom(int left, int top, int right, int bottom) {
17116        setFrame(left, top, right, bottom);
17117    }
17118
17119    private void sizeChange(int newWidth, int newHeight, int oldWidth, int oldHeight) {
17120        onSizeChanged(newWidth, newHeight, oldWidth, oldHeight);
17121        if (mOverlay != null) {
17122            mOverlay.getOverlayView().setRight(newWidth);
17123            mOverlay.getOverlayView().setBottom(newHeight);
17124        }
17125        rebuildOutline();
17126    }
17127
17128    /**
17129     * Finalize inflating a view from XML.  This is called as the last phase
17130     * of inflation, after all child views have been added.
17131     *
17132     * <p>Even if the subclass overrides onFinishInflate, they should always be
17133     * sure to call the super method, so that we get called.
17134     */
17135    @CallSuper
17136    protected void onFinishInflate() {
17137    }
17138
17139    /**
17140     * Returns the resources associated with this view.
17141     *
17142     * @return Resources object.
17143     */
17144    public Resources getResources() {
17145        return mResources;
17146    }
17147
17148    /**
17149     * Invalidates the specified Drawable.
17150     *
17151     * @param drawable the drawable to invalidate
17152     */
17153    @Override
17154    public void invalidateDrawable(@NonNull Drawable drawable) {
17155        if (verifyDrawable(drawable)) {
17156            final Rect dirty = drawable.getDirtyBounds();
17157            final int scrollX = mScrollX;
17158            final int scrollY = mScrollY;
17159
17160            invalidate(dirty.left + scrollX, dirty.top + scrollY,
17161                    dirty.right + scrollX, dirty.bottom + scrollY);
17162            rebuildOutline();
17163        }
17164    }
17165
17166    /**
17167     * Schedules an action on a drawable to occur at a specified time.
17168     *
17169     * @param who the recipient of the action
17170     * @param what the action to run on the drawable
17171     * @param when the time at which the action must occur. Uses the
17172     *        {@link SystemClock#uptimeMillis} timebase.
17173     */
17174    @Override
17175    public void scheduleDrawable(Drawable who, Runnable what, long when) {
17176        if (verifyDrawable(who) && what != null) {
17177            final long delay = when - SystemClock.uptimeMillis();
17178            if (mAttachInfo != null) {
17179                mAttachInfo.mViewRootImpl.mChoreographer.postCallbackDelayed(
17180                        Choreographer.CALLBACK_ANIMATION, what, who,
17181                        Choreographer.subtractFrameDelay(delay));
17182            } else {
17183                // Postpone the runnable until we know
17184                // on which thread it needs to run.
17185                getRunQueue().postDelayed(what, delay);
17186            }
17187        }
17188    }
17189
17190    /**
17191     * Cancels a scheduled action on a drawable.
17192     *
17193     * @param who the recipient of the action
17194     * @param what the action to cancel
17195     */
17196    @Override
17197    public void unscheduleDrawable(Drawable who, Runnable what) {
17198        if (verifyDrawable(who) && what != null) {
17199            if (mAttachInfo != null) {
17200                mAttachInfo.mViewRootImpl.mChoreographer.removeCallbacks(
17201                        Choreographer.CALLBACK_ANIMATION, what, who);
17202            }
17203            getRunQueue().removeCallbacks(what);
17204        }
17205    }
17206
17207    /**
17208     * Unschedule any events associated with the given Drawable.  This can be
17209     * used when selecting a new Drawable into a view, so that the previous
17210     * one is completely unscheduled.
17211     *
17212     * @param who The Drawable to unschedule.
17213     *
17214     * @see #drawableStateChanged
17215     */
17216    public void unscheduleDrawable(Drawable who) {
17217        if (mAttachInfo != null && who != null) {
17218            mAttachInfo.mViewRootImpl.mChoreographer.removeCallbacks(
17219                    Choreographer.CALLBACK_ANIMATION, null, who);
17220        }
17221    }
17222
17223    /**
17224     * Resolve the Drawables depending on the layout direction. This is implicitly supposing
17225     * that the View directionality can and will be resolved before its Drawables.
17226     *
17227     * Will call {@link View#onResolveDrawables} when resolution is done.
17228     *
17229     * @hide
17230     */
17231    protected void resolveDrawables() {
17232        // Drawables resolution may need to happen before resolving the layout direction (which is
17233        // done only during the measure() call).
17234        // If the layout direction is not resolved yet, we cannot resolve the Drawables except in
17235        // one case: when the raw layout direction has not been defined as LAYOUT_DIRECTION_INHERIT.
17236        // So, if the raw layout direction is LAYOUT_DIRECTION_LTR or LAYOUT_DIRECTION_RTL or
17237        // LAYOUT_DIRECTION_LOCALE, we can "cheat" and we don't need to wait for the layout
17238        // direction to be resolved as its resolved value will be the same as its raw value.
17239        if (!isLayoutDirectionResolved() &&
17240                getRawLayoutDirection() == View.LAYOUT_DIRECTION_INHERIT) {
17241            return;
17242        }
17243
17244        final int layoutDirection = isLayoutDirectionResolved() ?
17245                getLayoutDirection() : getRawLayoutDirection();
17246
17247        if (mBackground != null) {
17248            mBackground.setLayoutDirection(layoutDirection);
17249        }
17250        if (mForegroundInfo != null && mForegroundInfo.mDrawable != null) {
17251            mForegroundInfo.mDrawable.setLayoutDirection(layoutDirection);
17252        }
17253        mPrivateFlags2 |= PFLAG2_DRAWABLE_RESOLVED;
17254        onResolveDrawables(layoutDirection);
17255    }
17256
17257    boolean areDrawablesResolved() {
17258        return (mPrivateFlags2 & PFLAG2_DRAWABLE_RESOLVED) == PFLAG2_DRAWABLE_RESOLVED;
17259    }
17260
17261    /**
17262     * Called when layout direction has been resolved.
17263     *
17264     * The default implementation does nothing.
17265     *
17266     * @param layoutDirection The resolved layout direction.
17267     *
17268     * @see #LAYOUT_DIRECTION_LTR
17269     * @see #LAYOUT_DIRECTION_RTL
17270     *
17271     * @hide
17272     */
17273    public void onResolveDrawables(@ResolvedLayoutDir int layoutDirection) {
17274    }
17275
17276    /**
17277     * @hide
17278     */
17279    protected void resetResolvedDrawables() {
17280        resetResolvedDrawablesInternal();
17281    }
17282
17283    void resetResolvedDrawablesInternal() {
17284        mPrivateFlags2 &= ~PFLAG2_DRAWABLE_RESOLVED;
17285    }
17286
17287    /**
17288     * If your view subclass is displaying its own Drawable objects, it should
17289     * override this function and return true for any Drawable it is
17290     * displaying.  This allows animations for those drawables to be
17291     * scheduled.
17292     *
17293     * <p>Be sure to call through to the super class when overriding this
17294     * function.
17295     *
17296     * @param who The Drawable to verify.  Return true if it is one you are
17297     *            displaying, else return the result of calling through to the
17298     *            super class.
17299     *
17300     * @return boolean If true than the Drawable is being displayed in the
17301     *         view; else false and it is not allowed to animate.
17302     *
17303     * @see #unscheduleDrawable(android.graphics.drawable.Drawable)
17304     * @see #drawableStateChanged()
17305     */
17306    @CallSuper
17307    protected boolean verifyDrawable(Drawable who) {
17308        return who == mBackground || (mScrollCache != null && mScrollCache.scrollBar == who)
17309                || (mForegroundInfo != null && mForegroundInfo.mDrawable == who);
17310    }
17311
17312    /**
17313     * This function is called whenever the state of the view changes in such
17314     * a way that it impacts the state of drawables being shown.
17315     * <p>
17316     * If the View has a StateListAnimator, it will also be called to run necessary state
17317     * change animations.
17318     * <p>
17319     * Be sure to call through to the superclass when overriding this function.
17320     *
17321     * @see Drawable#setState(int[])
17322     */
17323    @CallSuper
17324    protected void drawableStateChanged() {
17325        final int[] state = getDrawableState();
17326        boolean changed = false;
17327
17328        final Drawable bg = mBackground;
17329        if (bg != null && bg.isStateful()) {
17330            changed |= bg.setState(state);
17331        }
17332
17333        final Drawable fg = mForegroundInfo != null ? mForegroundInfo.mDrawable : null;
17334        if (fg != null && fg.isStateful()) {
17335            changed |= fg.setState(state);
17336        }
17337
17338        if (mScrollCache != null) {
17339            final Drawable scrollBar = mScrollCache.scrollBar;
17340            if (scrollBar != null && scrollBar.isStateful()) {
17341                changed |= scrollBar.setState(state)
17342                        && mScrollCache.state != ScrollabilityCache.OFF;
17343            }
17344        }
17345
17346        if (mStateListAnimator != null) {
17347            mStateListAnimator.setState(state);
17348        }
17349
17350        if (changed) {
17351            invalidate();
17352        }
17353    }
17354
17355    /**
17356     * This function is called whenever the view hotspot changes and needs to
17357     * be propagated to drawables or child views managed by the view.
17358     * <p>
17359     * Dispatching to child views is handled by
17360     * {@link #dispatchDrawableHotspotChanged(float, float)}.
17361     * <p>
17362     * Be sure to call through to the superclass when overriding this function.
17363     *
17364     * @param x hotspot x coordinate
17365     * @param y hotspot y coordinate
17366     */
17367    @CallSuper
17368    public void drawableHotspotChanged(float x, float y) {
17369        if (mBackground != null) {
17370            mBackground.setHotspot(x, y);
17371        }
17372        if (mForegroundInfo != null && mForegroundInfo.mDrawable != null) {
17373            mForegroundInfo.mDrawable.setHotspot(x, y);
17374        }
17375
17376        dispatchDrawableHotspotChanged(x, y);
17377    }
17378
17379    /**
17380     * Dispatches drawableHotspotChanged to all of this View's children.
17381     *
17382     * @param x hotspot x coordinate
17383     * @param y hotspot y coordinate
17384     * @see #drawableHotspotChanged(float, float)
17385     */
17386    public void dispatchDrawableHotspotChanged(float x, float y) {
17387    }
17388
17389    /**
17390     * Call this to force a view to update its drawable state. This will cause
17391     * drawableStateChanged to be called on this view. Views that are interested
17392     * in the new state should call getDrawableState.
17393     *
17394     * @see #drawableStateChanged
17395     * @see #getDrawableState
17396     */
17397    public void refreshDrawableState() {
17398        mPrivateFlags |= PFLAG_DRAWABLE_STATE_DIRTY;
17399        drawableStateChanged();
17400
17401        ViewParent parent = mParent;
17402        if (parent != null) {
17403            parent.childDrawableStateChanged(this);
17404        }
17405    }
17406
17407    /**
17408     * Return an array of resource IDs of the drawable states representing the
17409     * current state of the view.
17410     *
17411     * @return The current drawable state
17412     *
17413     * @see Drawable#setState(int[])
17414     * @see #drawableStateChanged()
17415     * @see #onCreateDrawableState(int)
17416     */
17417    public final int[] getDrawableState() {
17418        if ((mDrawableState != null) && ((mPrivateFlags & PFLAG_DRAWABLE_STATE_DIRTY) == 0)) {
17419            return mDrawableState;
17420        } else {
17421            mDrawableState = onCreateDrawableState(0);
17422            mPrivateFlags &= ~PFLAG_DRAWABLE_STATE_DIRTY;
17423            return mDrawableState;
17424        }
17425    }
17426
17427    /**
17428     * Generate the new {@link android.graphics.drawable.Drawable} state for
17429     * this view. This is called by the view
17430     * system when the cached Drawable state is determined to be invalid.  To
17431     * retrieve the current state, you should use {@link #getDrawableState}.
17432     *
17433     * @param extraSpace if non-zero, this is the number of extra entries you
17434     * would like in the returned array in which you can place your own
17435     * states.
17436     *
17437     * @return Returns an array holding the current {@link Drawable} state of
17438     * the view.
17439     *
17440     * @see #mergeDrawableStates(int[], int[])
17441     */
17442    protected int[] onCreateDrawableState(int extraSpace) {
17443        if ((mViewFlags & DUPLICATE_PARENT_STATE) == DUPLICATE_PARENT_STATE &&
17444                mParent instanceof View) {
17445            return ((View) mParent).onCreateDrawableState(extraSpace);
17446        }
17447
17448        int[] drawableState;
17449
17450        int privateFlags = mPrivateFlags;
17451
17452        int viewStateIndex = 0;
17453        if ((privateFlags & PFLAG_PRESSED) != 0) viewStateIndex |= StateSet.VIEW_STATE_PRESSED;
17454        if ((mViewFlags & ENABLED_MASK) == ENABLED) viewStateIndex |= StateSet.VIEW_STATE_ENABLED;
17455        if (isFocused()) viewStateIndex |= StateSet.VIEW_STATE_FOCUSED;
17456        if ((privateFlags & PFLAG_SELECTED) != 0) viewStateIndex |= StateSet.VIEW_STATE_SELECTED;
17457        if (hasWindowFocus()) viewStateIndex |= StateSet.VIEW_STATE_WINDOW_FOCUSED;
17458        if ((privateFlags & PFLAG_ACTIVATED) != 0) viewStateIndex |= StateSet.VIEW_STATE_ACTIVATED;
17459        if (mAttachInfo != null && mAttachInfo.mHardwareAccelerationRequested &&
17460                ThreadedRenderer.isAvailable()) {
17461            // This is set if HW acceleration is requested, even if the current
17462            // process doesn't allow it.  This is just to allow app preview
17463            // windows to better match their app.
17464            viewStateIndex |= StateSet.VIEW_STATE_ACCELERATED;
17465        }
17466        if ((privateFlags & PFLAG_HOVERED) != 0) viewStateIndex |= StateSet.VIEW_STATE_HOVERED;
17467
17468        final int privateFlags2 = mPrivateFlags2;
17469        if ((privateFlags2 & PFLAG2_DRAG_CAN_ACCEPT) != 0) {
17470            viewStateIndex |= StateSet.VIEW_STATE_DRAG_CAN_ACCEPT;
17471        }
17472        if ((privateFlags2 & PFLAG2_DRAG_HOVERED) != 0) {
17473            viewStateIndex |= StateSet.VIEW_STATE_DRAG_HOVERED;
17474        }
17475
17476        drawableState = StateSet.get(viewStateIndex);
17477
17478        //noinspection ConstantIfStatement
17479        if (false) {
17480            Log.i("View", "drawableStateIndex=" + viewStateIndex);
17481            Log.i("View", toString()
17482                    + " pressed=" + ((privateFlags & PFLAG_PRESSED) != 0)
17483                    + " en=" + ((mViewFlags & ENABLED_MASK) == ENABLED)
17484                    + " fo=" + hasFocus()
17485                    + " sl=" + ((privateFlags & PFLAG_SELECTED) != 0)
17486                    + " wf=" + hasWindowFocus()
17487                    + ": " + Arrays.toString(drawableState));
17488        }
17489
17490        if (extraSpace == 0) {
17491            return drawableState;
17492        }
17493
17494        final int[] fullState;
17495        if (drawableState != null) {
17496            fullState = new int[drawableState.length + extraSpace];
17497            System.arraycopy(drawableState, 0, fullState, 0, drawableState.length);
17498        } else {
17499            fullState = new int[extraSpace];
17500        }
17501
17502        return fullState;
17503    }
17504
17505    /**
17506     * Merge your own state values in <var>additionalState</var> into the base
17507     * state values <var>baseState</var> that were returned by
17508     * {@link #onCreateDrawableState(int)}.
17509     *
17510     * @param baseState The base state values returned by
17511     * {@link #onCreateDrawableState(int)}, which will be modified to also hold your
17512     * own additional state values.
17513     *
17514     * @param additionalState The additional state values you would like
17515     * added to <var>baseState</var>; this array is not modified.
17516     *
17517     * @return As a convenience, the <var>baseState</var> array you originally
17518     * passed into the function is returned.
17519     *
17520     * @see #onCreateDrawableState(int)
17521     */
17522    protected static int[] mergeDrawableStates(int[] baseState, int[] additionalState) {
17523        final int N = baseState.length;
17524        int i = N - 1;
17525        while (i >= 0 && baseState[i] == 0) {
17526            i--;
17527        }
17528        System.arraycopy(additionalState, 0, baseState, i + 1, additionalState.length);
17529        return baseState;
17530    }
17531
17532    /**
17533     * Call {@link Drawable#jumpToCurrentState() Drawable.jumpToCurrentState()}
17534     * on all Drawable objects associated with this view.
17535     * <p>
17536     * Also calls {@link StateListAnimator#jumpToCurrentState()} if there is a StateListAnimator
17537     * attached to this view.
17538     */
17539    @CallSuper
17540    public void jumpDrawablesToCurrentState() {
17541        if (mBackground != null) {
17542            mBackground.jumpToCurrentState();
17543        }
17544        if (mStateListAnimator != null) {
17545            mStateListAnimator.jumpToCurrentState();
17546        }
17547        if (mForegroundInfo != null && mForegroundInfo.mDrawable != null) {
17548            mForegroundInfo.mDrawable.jumpToCurrentState();
17549        }
17550    }
17551
17552    /**
17553     * Sets the background color for this view.
17554     * @param color the color of the background
17555     */
17556    @RemotableViewMethod
17557    public void setBackgroundColor(@ColorInt int color) {
17558        if (mBackground instanceof ColorDrawable) {
17559            ((ColorDrawable) mBackground.mutate()).setColor(color);
17560            computeOpaqueFlags();
17561            mBackgroundResource = 0;
17562        } else {
17563            setBackground(new ColorDrawable(color));
17564        }
17565    }
17566
17567    /**
17568     * Set the background to a given resource. The resource should refer to
17569     * a Drawable object or 0 to remove the background.
17570     * @param resid The identifier of the resource.
17571     *
17572     * @attr ref android.R.styleable#View_background
17573     */
17574    @RemotableViewMethod
17575    public void setBackgroundResource(@DrawableRes int resid) {
17576        if (resid != 0 && resid == mBackgroundResource) {
17577            return;
17578        }
17579
17580        Drawable d = null;
17581        if (resid != 0) {
17582            d = mContext.getDrawable(resid);
17583        }
17584        setBackground(d);
17585
17586        mBackgroundResource = resid;
17587    }
17588
17589    /**
17590     * Set the background to a given Drawable, or remove the background. If the
17591     * background has padding, this View's padding is set to the background's
17592     * padding. However, when a background is removed, this View's padding isn't
17593     * touched. If setting the padding is desired, please use
17594     * {@link #setPadding(int, int, int, int)}.
17595     *
17596     * @param background The Drawable to use as the background, or null to remove the
17597     *        background
17598     */
17599    public void setBackground(Drawable background) {
17600        //noinspection deprecation
17601        setBackgroundDrawable(background);
17602    }
17603
17604    /**
17605     * @deprecated use {@link #setBackground(Drawable)} instead
17606     */
17607    @Deprecated
17608    public void setBackgroundDrawable(Drawable background) {
17609        computeOpaqueFlags();
17610
17611        if (background == mBackground) {
17612            return;
17613        }
17614
17615        boolean requestLayout = false;
17616
17617        mBackgroundResource = 0;
17618
17619        /*
17620         * Regardless of whether we're setting a new background or not, we want
17621         * to clear the previous drawable.
17622         */
17623        if (mBackground != null) {
17624            mBackground.setCallback(null);
17625            unscheduleDrawable(mBackground);
17626        }
17627
17628        if (background != null) {
17629            Rect padding = sThreadLocal.get();
17630            if (padding == null) {
17631                padding = new Rect();
17632                sThreadLocal.set(padding);
17633            }
17634            resetResolvedDrawablesInternal();
17635            background.setLayoutDirection(getLayoutDirection());
17636            if (background.getPadding(padding)) {
17637                resetResolvedPaddingInternal();
17638                switch (background.getLayoutDirection()) {
17639                    case LAYOUT_DIRECTION_RTL:
17640                        mUserPaddingLeftInitial = padding.right;
17641                        mUserPaddingRightInitial = padding.left;
17642                        internalSetPadding(padding.right, padding.top, padding.left, padding.bottom);
17643                        break;
17644                    case LAYOUT_DIRECTION_LTR:
17645                    default:
17646                        mUserPaddingLeftInitial = padding.left;
17647                        mUserPaddingRightInitial = padding.right;
17648                        internalSetPadding(padding.left, padding.top, padding.right, padding.bottom);
17649                }
17650                mLeftPaddingDefined = false;
17651                mRightPaddingDefined = false;
17652            }
17653
17654            // Compare the minimum sizes of the old Drawable and the new.  If there isn't an old or
17655            // if it has a different minimum size, we should layout again
17656            if (mBackground == null
17657                    || mBackground.getMinimumHeight() != background.getMinimumHeight()
17658                    || mBackground.getMinimumWidth() != background.getMinimumWidth()) {
17659                requestLayout = true;
17660            }
17661
17662            background.setCallback(this);
17663            if (background.isStateful()) {
17664                background.setState(getDrawableState());
17665            }
17666            background.setVisible(getVisibility() == VISIBLE, false);
17667            mBackground = background;
17668
17669            applyBackgroundTint();
17670
17671            if ((mPrivateFlags & PFLAG_SKIP_DRAW) != 0) {
17672                mPrivateFlags &= ~PFLAG_SKIP_DRAW;
17673                requestLayout = true;
17674            }
17675        } else {
17676            /* Remove the background */
17677            mBackground = null;
17678            if ((mViewFlags & WILL_NOT_DRAW) != 0
17679                    && (mForegroundInfo == null || mForegroundInfo.mDrawable == null)) {
17680                mPrivateFlags |= PFLAG_SKIP_DRAW;
17681            }
17682
17683            /*
17684             * When the background is set, we try to apply its padding to this
17685             * View. When the background is removed, we don't touch this View's
17686             * padding. This is noted in the Javadocs. Hence, we don't need to
17687             * requestLayout(), the invalidate() below is sufficient.
17688             */
17689
17690            // The old background's minimum size could have affected this
17691            // View's layout, so let's requestLayout
17692            requestLayout = true;
17693        }
17694
17695        computeOpaqueFlags();
17696
17697        if (requestLayout) {
17698            requestLayout();
17699        }
17700
17701        mBackgroundSizeChanged = true;
17702        invalidate(true);
17703    }
17704
17705    /**
17706     * Gets the background drawable
17707     *
17708     * @return The drawable used as the background for this view, if any.
17709     *
17710     * @see #setBackground(Drawable)
17711     *
17712     * @attr ref android.R.styleable#View_background
17713     */
17714    public Drawable getBackground() {
17715        return mBackground;
17716    }
17717
17718    /**
17719     * Applies a tint to the background drawable. Does not modify the current tint
17720     * mode, which is {@link PorterDuff.Mode#SRC_IN} by default.
17721     * <p>
17722     * Subsequent calls to {@link #setBackground(Drawable)} will automatically
17723     * mutate the drawable and apply the specified tint and tint mode using
17724     * {@link Drawable#setTintList(ColorStateList)}.
17725     *
17726     * @param tint the tint to apply, may be {@code null} to clear tint
17727     *
17728     * @attr ref android.R.styleable#View_backgroundTint
17729     * @see #getBackgroundTintList()
17730     * @see Drawable#setTintList(ColorStateList)
17731     */
17732    public void setBackgroundTintList(@Nullable ColorStateList tint) {
17733        if (mBackgroundTint == null) {
17734            mBackgroundTint = new TintInfo();
17735        }
17736        mBackgroundTint.mTintList = tint;
17737        mBackgroundTint.mHasTintList = true;
17738
17739        applyBackgroundTint();
17740    }
17741
17742    /**
17743     * Return the tint applied to the background drawable, if specified.
17744     *
17745     * @return the tint applied to the background drawable
17746     * @attr ref android.R.styleable#View_backgroundTint
17747     * @see #setBackgroundTintList(ColorStateList)
17748     */
17749    @Nullable
17750    public ColorStateList getBackgroundTintList() {
17751        return mBackgroundTint != null ? mBackgroundTint.mTintList : null;
17752    }
17753
17754    /**
17755     * Specifies the blending mode used to apply the tint specified by
17756     * {@link #setBackgroundTintList(ColorStateList)}} to the background
17757     * drawable. The default mode is {@link PorterDuff.Mode#SRC_IN}.
17758     *
17759     * @param tintMode the blending mode used to apply the tint, may be
17760     *                 {@code null} to clear tint
17761     * @attr ref android.R.styleable#View_backgroundTintMode
17762     * @see #getBackgroundTintMode()
17763     * @see Drawable#setTintMode(PorterDuff.Mode)
17764     */
17765    public void setBackgroundTintMode(@Nullable PorterDuff.Mode tintMode) {
17766        if (mBackgroundTint == null) {
17767            mBackgroundTint = new TintInfo();
17768        }
17769        mBackgroundTint.mTintMode = tintMode;
17770        mBackgroundTint.mHasTintMode = true;
17771
17772        applyBackgroundTint();
17773    }
17774
17775    /**
17776     * Return the blending mode used to apply the tint to the background
17777     * drawable, if specified.
17778     *
17779     * @return the blending mode used to apply the tint to the background
17780     *         drawable
17781     * @attr ref android.R.styleable#View_backgroundTintMode
17782     * @see #setBackgroundTintMode(PorterDuff.Mode)
17783     */
17784    @Nullable
17785    public PorterDuff.Mode getBackgroundTintMode() {
17786        return mBackgroundTint != null ? mBackgroundTint.mTintMode : null;
17787    }
17788
17789    private void applyBackgroundTint() {
17790        if (mBackground != null && mBackgroundTint != null) {
17791            final TintInfo tintInfo = mBackgroundTint;
17792            if (tintInfo.mHasTintList || tintInfo.mHasTintMode) {
17793                mBackground = mBackground.mutate();
17794
17795                if (tintInfo.mHasTintList) {
17796                    mBackground.setTintList(tintInfo.mTintList);
17797                }
17798
17799                if (tintInfo.mHasTintMode) {
17800                    mBackground.setTintMode(tintInfo.mTintMode);
17801                }
17802
17803                // The drawable (or one of its children) may not have been
17804                // stateful before applying the tint, so let's try again.
17805                if (mBackground.isStateful()) {
17806                    mBackground.setState(getDrawableState());
17807                }
17808            }
17809        }
17810    }
17811
17812    /**
17813     * Returns the drawable used as the foreground of this View. The
17814     * foreground drawable, if non-null, is always drawn on top of the view's content.
17815     *
17816     * @return a Drawable or null if no foreground was set
17817     *
17818     * @see #onDrawForeground(Canvas)
17819     */
17820    public Drawable getForeground() {
17821        return mForegroundInfo != null ? mForegroundInfo.mDrawable : null;
17822    }
17823
17824    /**
17825     * Supply a Drawable that is to be rendered on top of all of the content in the view.
17826     *
17827     * @param foreground the Drawable to be drawn on top of the children
17828     *
17829     * @attr ref android.R.styleable#View_foreground
17830     */
17831    public void setForeground(Drawable foreground) {
17832        if (mForegroundInfo == null) {
17833            if (foreground == null) {
17834                // Nothing to do.
17835                return;
17836            }
17837            mForegroundInfo = new ForegroundInfo();
17838        }
17839
17840        if (foreground == mForegroundInfo.mDrawable) {
17841            // Nothing to do
17842            return;
17843        }
17844
17845        if (mForegroundInfo.mDrawable != null) {
17846            mForegroundInfo.mDrawable.setCallback(null);
17847            unscheduleDrawable(mForegroundInfo.mDrawable);
17848        }
17849
17850        mForegroundInfo.mDrawable = foreground;
17851        mForegroundInfo.mBoundsChanged = true;
17852        if (foreground != null) {
17853            if ((mPrivateFlags & PFLAG_SKIP_DRAW) != 0) {
17854                mPrivateFlags &= ~PFLAG_SKIP_DRAW;
17855            }
17856            foreground.setCallback(this);
17857            foreground.setLayoutDirection(getLayoutDirection());
17858            if (foreground.isStateful()) {
17859                foreground.setState(getDrawableState());
17860            }
17861            applyForegroundTint();
17862        } else if ((mViewFlags & WILL_NOT_DRAW) != 0 && mBackground == null) {
17863            mPrivateFlags |= PFLAG_SKIP_DRAW;
17864        }
17865        requestLayout();
17866        invalidate();
17867    }
17868
17869    /**
17870     * Magic bit used to support features of framework-internal window decor implementation details.
17871     * This used to live exclusively in FrameLayout.
17872     *
17873     * @return true if the foreground should draw inside the padding region or false
17874     *         if it should draw inset by the view's padding
17875     * @hide internal use only; only used by FrameLayout and internal screen layouts.
17876     */
17877    public boolean isForegroundInsidePadding() {
17878        return mForegroundInfo != null ? mForegroundInfo.mInsidePadding : true;
17879    }
17880
17881    /**
17882     * Describes how the foreground is positioned.
17883     *
17884     * @return foreground gravity.
17885     *
17886     * @see #setForegroundGravity(int)
17887     *
17888     * @attr ref android.R.styleable#View_foregroundGravity
17889     */
17890    public int getForegroundGravity() {
17891        return mForegroundInfo != null ? mForegroundInfo.mGravity
17892                : Gravity.START | Gravity.TOP;
17893    }
17894
17895    /**
17896     * Describes how the foreground is positioned. Defaults to START and TOP.
17897     *
17898     * @param gravity see {@link android.view.Gravity}
17899     *
17900     * @see #getForegroundGravity()
17901     *
17902     * @attr ref android.R.styleable#View_foregroundGravity
17903     */
17904    public void setForegroundGravity(int gravity) {
17905        if (mForegroundInfo == null) {
17906            mForegroundInfo = new ForegroundInfo();
17907        }
17908
17909        if (mForegroundInfo.mGravity != gravity) {
17910            if ((gravity & Gravity.RELATIVE_HORIZONTAL_GRAVITY_MASK) == 0) {
17911                gravity |= Gravity.START;
17912            }
17913
17914            if ((gravity & Gravity.VERTICAL_GRAVITY_MASK) == 0) {
17915                gravity |= Gravity.TOP;
17916            }
17917
17918            mForegroundInfo.mGravity = gravity;
17919            requestLayout();
17920        }
17921    }
17922
17923    /**
17924     * Applies a tint to the foreground drawable. Does not modify the current tint
17925     * mode, which is {@link PorterDuff.Mode#SRC_IN} by default.
17926     * <p>
17927     * Subsequent calls to {@link #setForeground(Drawable)} will automatically
17928     * mutate the drawable and apply the specified tint and tint mode using
17929     * {@link Drawable#setTintList(ColorStateList)}.
17930     *
17931     * @param tint the tint to apply, may be {@code null} to clear tint
17932     *
17933     * @attr ref android.R.styleable#View_foregroundTint
17934     * @see #getForegroundTintList()
17935     * @see Drawable#setTintList(ColorStateList)
17936     */
17937    public void setForegroundTintList(@Nullable ColorStateList tint) {
17938        if (mForegroundInfo == null) {
17939            mForegroundInfo = new ForegroundInfo();
17940        }
17941        if (mForegroundInfo.mTintInfo == null) {
17942            mForegroundInfo.mTintInfo = new TintInfo();
17943        }
17944        mForegroundInfo.mTintInfo.mTintList = tint;
17945        mForegroundInfo.mTintInfo.mHasTintList = true;
17946
17947        applyForegroundTint();
17948    }
17949
17950    /**
17951     * Return the tint applied to the foreground drawable, if specified.
17952     *
17953     * @return the tint applied to the foreground drawable
17954     * @attr ref android.R.styleable#View_foregroundTint
17955     * @see #setForegroundTintList(ColorStateList)
17956     */
17957    @Nullable
17958    public ColorStateList getForegroundTintList() {
17959        return mForegroundInfo != null && mForegroundInfo.mTintInfo != null
17960                ? mForegroundInfo.mTintInfo.mTintList : null;
17961    }
17962
17963    /**
17964     * Specifies the blending mode used to apply the tint specified by
17965     * {@link #setForegroundTintList(ColorStateList)}} to the background
17966     * drawable. The default mode is {@link PorterDuff.Mode#SRC_IN}.
17967     *
17968     * @param tintMode the blending mode used to apply the tint, may be
17969     *                 {@code null} to clear tint
17970     * @attr ref android.R.styleable#View_foregroundTintMode
17971     * @see #getForegroundTintMode()
17972     * @see Drawable#setTintMode(PorterDuff.Mode)
17973     */
17974    public void setForegroundTintMode(@Nullable PorterDuff.Mode tintMode) {
17975        if (mForegroundInfo == null) {
17976            mForegroundInfo = new ForegroundInfo();
17977        }
17978        if (mForegroundInfo.mTintInfo == null) {
17979            mForegroundInfo.mTintInfo = new TintInfo();
17980        }
17981        mForegroundInfo.mTintInfo.mTintMode = tintMode;
17982        mForegroundInfo.mTintInfo.mHasTintMode = true;
17983
17984        applyForegroundTint();
17985    }
17986
17987    /**
17988     * Return the blending mode used to apply the tint to the foreground
17989     * drawable, if specified.
17990     *
17991     * @return the blending mode used to apply the tint to the foreground
17992     *         drawable
17993     * @attr ref android.R.styleable#View_foregroundTintMode
17994     * @see #setForegroundTintMode(PorterDuff.Mode)
17995     */
17996    @Nullable
17997    public PorterDuff.Mode getForegroundTintMode() {
17998        return mForegroundInfo != null && mForegroundInfo.mTintInfo != null
17999                ? mForegroundInfo.mTintInfo.mTintMode : null;
18000    }
18001
18002    private void applyForegroundTint() {
18003        if (mForegroundInfo != null && mForegroundInfo.mDrawable != null
18004                && mForegroundInfo.mTintInfo != null) {
18005            final TintInfo tintInfo = mForegroundInfo.mTintInfo;
18006            if (tintInfo.mHasTintList || tintInfo.mHasTintMode) {
18007                mForegroundInfo.mDrawable = mForegroundInfo.mDrawable.mutate();
18008
18009                if (tintInfo.mHasTintList) {
18010                    mForegroundInfo.mDrawable.setTintList(tintInfo.mTintList);
18011                }
18012
18013                if (tintInfo.mHasTintMode) {
18014                    mForegroundInfo.mDrawable.setTintMode(tintInfo.mTintMode);
18015                }
18016
18017                // The drawable (or one of its children) may not have been
18018                // stateful before applying the tint, so let's try again.
18019                if (mForegroundInfo.mDrawable.isStateful()) {
18020                    mForegroundInfo.mDrawable.setState(getDrawableState());
18021                }
18022            }
18023        }
18024    }
18025
18026    /**
18027     * Draw any foreground content for this view.
18028     *
18029     * <p>Foreground content may consist of scroll bars, a {@link #setForeground foreground}
18030     * drawable or other view-specific decorations. The foreground is drawn on top of the
18031     * primary view content.</p>
18032     *
18033     * @param canvas canvas to draw into
18034     */
18035    public void onDrawForeground(Canvas canvas) {
18036        onDrawScrollIndicators(canvas);
18037        onDrawScrollBars(canvas);
18038
18039        final Drawable foreground = mForegroundInfo != null ? mForegroundInfo.mDrawable : null;
18040        if (foreground != null) {
18041            if (mForegroundInfo.mBoundsChanged) {
18042                mForegroundInfo.mBoundsChanged = false;
18043                final Rect selfBounds = mForegroundInfo.mSelfBounds;
18044                final Rect overlayBounds = mForegroundInfo.mOverlayBounds;
18045
18046                if (mForegroundInfo.mInsidePadding) {
18047                    selfBounds.set(0, 0, getWidth(), getHeight());
18048                } else {
18049                    selfBounds.set(getPaddingLeft(), getPaddingTop(),
18050                            getWidth() - getPaddingRight(), getHeight() - getPaddingBottom());
18051                }
18052
18053                final int ld = getLayoutDirection();
18054                Gravity.apply(mForegroundInfo.mGravity, foreground.getIntrinsicWidth(),
18055                        foreground.getIntrinsicHeight(), selfBounds, overlayBounds, ld);
18056                foreground.setBounds(overlayBounds);
18057            }
18058
18059            foreground.draw(canvas);
18060        }
18061    }
18062
18063    /**
18064     * Sets the padding. The view may add on the space required to display
18065     * the scrollbars, depending on the style and visibility of the scrollbars.
18066     * So the values returned from {@link #getPaddingLeft}, {@link #getPaddingTop},
18067     * {@link #getPaddingRight} and {@link #getPaddingBottom} may be different
18068     * from the values set in this call.
18069     *
18070     * @attr ref android.R.styleable#View_padding
18071     * @attr ref android.R.styleable#View_paddingBottom
18072     * @attr ref android.R.styleable#View_paddingLeft
18073     * @attr ref android.R.styleable#View_paddingRight
18074     * @attr ref android.R.styleable#View_paddingTop
18075     * @param left the left padding in pixels
18076     * @param top the top padding in pixels
18077     * @param right the right padding in pixels
18078     * @param bottom the bottom padding in pixels
18079     */
18080    public void setPadding(int left, int top, int right, int bottom) {
18081        resetResolvedPaddingInternal();
18082
18083        mUserPaddingStart = UNDEFINED_PADDING;
18084        mUserPaddingEnd = UNDEFINED_PADDING;
18085
18086        mUserPaddingLeftInitial = left;
18087        mUserPaddingRightInitial = right;
18088
18089        mLeftPaddingDefined = true;
18090        mRightPaddingDefined = true;
18091
18092        internalSetPadding(left, top, right, bottom);
18093    }
18094
18095    /**
18096     * @hide
18097     */
18098    protected void internalSetPadding(int left, int top, int right, int bottom) {
18099        mUserPaddingLeft = left;
18100        mUserPaddingRight = right;
18101        mUserPaddingBottom = bottom;
18102
18103        final int viewFlags = mViewFlags;
18104        boolean changed = false;
18105
18106        // Common case is there are no scroll bars.
18107        if ((viewFlags & (SCROLLBARS_VERTICAL|SCROLLBARS_HORIZONTAL)) != 0) {
18108            if ((viewFlags & SCROLLBARS_VERTICAL) != 0) {
18109                final int offset = (viewFlags & SCROLLBARS_INSET_MASK) == 0
18110                        ? 0 : getVerticalScrollbarWidth();
18111                switch (mVerticalScrollbarPosition) {
18112                    case SCROLLBAR_POSITION_DEFAULT:
18113                        if (isLayoutRtl()) {
18114                            left += offset;
18115                        } else {
18116                            right += offset;
18117                        }
18118                        break;
18119                    case SCROLLBAR_POSITION_RIGHT:
18120                        right += offset;
18121                        break;
18122                    case SCROLLBAR_POSITION_LEFT:
18123                        left += offset;
18124                        break;
18125                }
18126            }
18127            if ((viewFlags & SCROLLBARS_HORIZONTAL) != 0) {
18128                bottom += (viewFlags & SCROLLBARS_INSET_MASK) == 0
18129                        ? 0 : getHorizontalScrollbarHeight();
18130            }
18131        }
18132
18133        if (mPaddingLeft != left) {
18134            changed = true;
18135            mPaddingLeft = left;
18136        }
18137        if (mPaddingTop != top) {
18138            changed = true;
18139            mPaddingTop = top;
18140        }
18141        if (mPaddingRight != right) {
18142            changed = true;
18143            mPaddingRight = right;
18144        }
18145        if (mPaddingBottom != bottom) {
18146            changed = true;
18147            mPaddingBottom = bottom;
18148        }
18149
18150        if (changed) {
18151            requestLayout();
18152            invalidateOutline();
18153        }
18154    }
18155
18156    /**
18157     * Sets the relative padding. The view may add on the space required to display
18158     * the scrollbars, depending on the style and visibility of the scrollbars.
18159     * So the values returned from {@link #getPaddingStart}, {@link #getPaddingTop},
18160     * {@link #getPaddingEnd} and {@link #getPaddingBottom} may be different
18161     * from the values set in this call.
18162     *
18163     * @attr ref android.R.styleable#View_padding
18164     * @attr ref android.R.styleable#View_paddingBottom
18165     * @attr ref android.R.styleable#View_paddingStart
18166     * @attr ref android.R.styleable#View_paddingEnd
18167     * @attr ref android.R.styleable#View_paddingTop
18168     * @param start the start padding in pixels
18169     * @param top the top padding in pixels
18170     * @param end the end padding in pixels
18171     * @param bottom the bottom padding in pixels
18172     */
18173    public void setPaddingRelative(int start, int top, int end, int bottom) {
18174        resetResolvedPaddingInternal();
18175
18176        mUserPaddingStart = start;
18177        mUserPaddingEnd = end;
18178        mLeftPaddingDefined = true;
18179        mRightPaddingDefined = true;
18180
18181        switch(getLayoutDirection()) {
18182            case LAYOUT_DIRECTION_RTL:
18183                mUserPaddingLeftInitial = end;
18184                mUserPaddingRightInitial = start;
18185                internalSetPadding(end, top, start, bottom);
18186                break;
18187            case LAYOUT_DIRECTION_LTR:
18188            default:
18189                mUserPaddingLeftInitial = start;
18190                mUserPaddingRightInitial = end;
18191                internalSetPadding(start, top, end, bottom);
18192        }
18193    }
18194
18195    /**
18196     * Returns the top padding of this view.
18197     *
18198     * @return the top padding in pixels
18199     */
18200    public int getPaddingTop() {
18201        return mPaddingTop;
18202    }
18203
18204    /**
18205     * Returns the bottom padding of this view. If there are inset and enabled
18206     * scrollbars, this value may include the space required to display the
18207     * scrollbars as well.
18208     *
18209     * @return the bottom padding in pixels
18210     */
18211    public int getPaddingBottom() {
18212        return mPaddingBottom;
18213    }
18214
18215    /**
18216     * Returns the left padding of this view. If there are inset and enabled
18217     * scrollbars, this value may include the space required to display the
18218     * scrollbars as well.
18219     *
18220     * @return the left padding in pixels
18221     */
18222    public int getPaddingLeft() {
18223        if (!isPaddingResolved()) {
18224            resolvePadding();
18225        }
18226        return mPaddingLeft;
18227    }
18228
18229    /**
18230     * Returns the start padding of this view depending on its resolved layout direction.
18231     * If there are inset and enabled scrollbars, this value may include the space
18232     * required to display the scrollbars as well.
18233     *
18234     * @return the start padding in pixels
18235     */
18236    public int getPaddingStart() {
18237        if (!isPaddingResolved()) {
18238            resolvePadding();
18239        }
18240        return (getLayoutDirection() == LAYOUT_DIRECTION_RTL) ?
18241                mPaddingRight : mPaddingLeft;
18242    }
18243
18244    /**
18245     * Returns the right padding of this view. If there are inset and enabled
18246     * scrollbars, this value may include the space required to display the
18247     * scrollbars as well.
18248     *
18249     * @return the right padding in pixels
18250     */
18251    public int getPaddingRight() {
18252        if (!isPaddingResolved()) {
18253            resolvePadding();
18254        }
18255        return mPaddingRight;
18256    }
18257
18258    /**
18259     * Returns the end padding of this view depending on its resolved layout direction.
18260     * If there are inset and enabled scrollbars, this value may include the space
18261     * required to display the scrollbars as well.
18262     *
18263     * @return the end padding in pixels
18264     */
18265    public int getPaddingEnd() {
18266        if (!isPaddingResolved()) {
18267            resolvePadding();
18268        }
18269        return (getLayoutDirection() == LAYOUT_DIRECTION_RTL) ?
18270                mPaddingLeft : mPaddingRight;
18271    }
18272
18273    /**
18274     * Return if the padding has been set through relative values
18275     * {@link #setPaddingRelative(int, int, int, int)} or through
18276     * @attr ref android.R.styleable#View_paddingStart or
18277     * @attr ref android.R.styleable#View_paddingEnd
18278     *
18279     * @return true if the padding is relative or false if it is not.
18280     */
18281    public boolean isPaddingRelative() {
18282        return (mUserPaddingStart != UNDEFINED_PADDING || mUserPaddingEnd != UNDEFINED_PADDING);
18283    }
18284
18285    Insets computeOpticalInsets() {
18286        return (mBackground == null) ? Insets.NONE : mBackground.getOpticalInsets();
18287    }
18288
18289    /**
18290     * @hide
18291     */
18292    public void resetPaddingToInitialValues() {
18293        if (isRtlCompatibilityMode()) {
18294            mPaddingLeft = mUserPaddingLeftInitial;
18295            mPaddingRight = mUserPaddingRightInitial;
18296            return;
18297        }
18298        if (isLayoutRtl()) {
18299            mPaddingLeft = (mUserPaddingEnd >= 0) ? mUserPaddingEnd : mUserPaddingLeftInitial;
18300            mPaddingRight = (mUserPaddingStart >= 0) ? mUserPaddingStart : mUserPaddingRightInitial;
18301        } else {
18302            mPaddingLeft = (mUserPaddingStart >= 0) ? mUserPaddingStart : mUserPaddingLeftInitial;
18303            mPaddingRight = (mUserPaddingEnd >= 0) ? mUserPaddingEnd : mUserPaddingRightInitial;
18304        }
18305    }
18306
18307    /**
18308     * @hide
18309     */
18310    public Insets getOpticalInsets() {
18311        if (mLayoutInsets == null) {
18312            mLayoutInsets = computeOpticalInsets();
18313        }
18314        return mLayoutInsets;
18315    }
18316
18317    /**
18318     * Set this view's optical insets.
18319     *
18320     * <p>This method should be treated similarly to setMeasuredDimension and not as a general
18321     * property. Views that compute their own optical insets should call it as part of measurement.
18322     * This method does not request layout. If you are setting optical insets outside of
18323     * measure/layout itself you will want to call requestLayout() yourself.
18324     * </p>
18325     * @hide
18326     */
18327    public void setOpticalInsets(Insets insets) {
18328        mLayoutInsets = insets;
18329    }
18330
18331    /**
18332     * Changes the selection state of this view. A view can be selected or not.
18333     * Note that selection is not the same as focus. Views are typically
18334     * selected in the context of an AdapterView like ListView or GridView;
18335     * the selected view is the view that is highlighted.
18336     *
18337     * @param selected true if the view must be selected, false otherwise
18338     */
18339    public void setSelected(boolean selected) {
18340        //noinspection DoubleNegation
18341        if (((mPrivateFlags & PFLAG_SELECTED) != 0) != selected) {
18342            mPrivateFlags = (mPrivateFlags & ~PFLAG_SELECTED) | (selected ? PFLAG_SELECTED : 0);
18343            if (!selected) resetPressedState();
18344            invalidate(true);
18345            refreshDrawableState();
18346            dispatchSetSelected(selected);
18347            if (selected) {
18348                sendAccessibilityEvent(AccessibilityEvent.TYPE_VIEW_SELECTED);
18349            } else {
18350                notifyViewAccessibilityStateChangedIfNeeded(
18351                        AccessibilityEvent.CONTENT_CHANGE_TYPE_UNDEFINED);
18352            }
18353        }
18354    }
18355
18356    /**
18357     * Dispatch setSelected to all of this View's children.
18358     *
18359     * @see #setSelected(boolean)
18360     *
18361     * @param selected The new selected state
18362     */
18363    protected void dispatchSetSelected(boolean selected) {
18364    }
18365
18366    /**
18367     * Indicates the selection state of this view.
18368     *
18369     * @return true if the view is selected, false otherwise
18370     */
18371    @ViewDebug.ExportedProperty
18372    public boolean isSelected() {
18373        return (mPrivateFlags & PFLAG_SELECTED) != 0;
18374    }
18375
18376    /**
18377     * Changes the activated state of this view. A view can be activated or not.
18378     * Note that activation is not the same as selection.  Selection is
18379     * a transient property, representing the view (hierarchy) the user is
18380     * currently interacting with.  Activation is a longer-term state that the
18381     * user can move views in and out of.  For example, in a list view with
18382     * single or multiple selection enabled, the views in the current selection
18383     * set are activated.  (Um, yeah, we are deeply sorry about the terminology
18384     * here.)  The activated state is propagated down to children of the view it
18385     * is set on.
18386     *
18387     * @param activated true if the view must be activated, false otherwise
18388     */
18389    public void setActivated(boolean activated) {
18390        //noinspection DoubleNegation
18391        if (((mPrivateFlags & PFLAG_ACTIVATED) != 0) != activated) {
18392            mPrivateFlags = (mPrivateFlags & ~PFLAG_ACTIVATED) | (activated ? PFLAG_ACTIVATED : 0);
18393            invalidate(true);
18394            refreshDrawableState();
18395            dispatchSetActivated(activated);
18396        }
18397    }
18398
18399    /**
18400     * Dispatch setActivated to all of this View's children.
18401     *
18402     * @see #setActivated(boolean)
18403     *
18404     * @param activated The new activated state
18405     */
18406    protected void dispatchSetActivated(boolean activated) {
18407    }
18408
18409    /**
18410     * Indicates the activation state of this view.
18411     *
18412     * @return true if the view is activated, false otherwise
18413     */
18414    @ViewDebug.ExportedProperty
18415    public boolean isActivated() {
18416        return (mPrivateFlags & PFLAG_ACTIVATED) != 0;
18417    }
18418
18419    /**
18420     * Returns the ViewTreeObserver for this view's hierarchy. The view tree
18421     * observer can be used to get notifications when global events, like
18422     * layout, happen.
18423     *
18424     * The returned ViewTreeObserver observer is not guaranteed to remain
18425     * valid for the lifetime of this View. If the caller of this method keeps
18426     * a long-lived reference to ViewTreeObserver, it should always check for
18427     * the return value of {@link ViewTreeObserver#isAlive()}.
18428     *
18429     * @return The ViewTreeObserver for this view's hierarchy.
18430     */
18431    public ViewTreeObserver getViewTreeObserver() {
18432        if (mAttachInfo != null) {
18433            return mAttachInfo.mTreeObserver;
18434        }
18435        if (mFloatingTreeObserver == null) {
18436            mFloatingTreeObserver = new ViewTreeObserver();
18437        }
18438        return mFloatingTreeObserver;
18439    }
18440
18441    /**
18442     * <p>Finds the topmost view in the current view hierarchy.</p>
18443     *
18444     * @return the topmost view containing this view
18445     */
18446    public View getRootView() {
18447        if (mAttachInfo != null) {
18448            final View v = mAttachInfo.mRootView;
18449            if (v != null) {
18450                return v;
18451            }
18452        }
18453
18454        View parent = this;
18455
18456        while (parent.mParent != null && parent.mParent instanceof View) {
18457            parent = (View) parent.mParent;
18458        }
18459
18460        return parent;
18461    }
18462
18463    /**
18464     * Transforms a motion event from view-local coordinates to on-screen
18465     * coordinates.
18466     *
18467     * @param ev the view-local motion event
18468     * @return false if the transformation could not be applied
18469     * @hide
18470     */
18471    public boolean toGlobalMotionEvent(MotionEvent ev) {
18472        final AttachInfo info = mAttachInfo;
18473        if (info == null) {
18474            return false;
18475        }
18476
18477        final Matrix m = info.mTmpMatrix;
18478        m.set(Matrix.IDENTITY_MATRIX);
18479        transformMatrixToGlobal(m);
18480        ev.transform(m);
18481        return true;
18482    }
18483
18484    /**
18485     * Transforms a motion event from on-screen coordinates to view-local
18486     * coordinates.
18487     *
18488     * @param ev the on-screen motion event
18489     * @return false if the transformation could not be applied
18490     * @hide
18491     */
18492    public boolean toLocalMotionEvent(MotionEvent ev) {
18493        final AttachInfo info = mAttachInfo;
18494        if (info == null) {
18495            return false;
18496        }
18497
18498        final Matrix m = info.mTmpMatrix;
18499        m.set(Matrix.IDENTITY_MATRIX);
18500        transformMatrixToLocal(m);
18501        ev.transform(m);
18502        return true;
18503    }
18504
18505    /**
18506     * Modifies the input matrix such that it maps view-local coordinates to
18507     * on-screen coordinates.
18508     *
18509     * @param m input matrix to modify
18510     * @hide
18511     */
18512    public void transformMatrixToGlobal(Matrix m) {
18513        final ViewParent parent = mParent;
18514        if (parent instanceof View) {
18515            final View vp = (View) parent;
18516            vp.transformMatrixToGlobal(m);
18517            m.preTranslate(-vp.mScrollX, -vp.mScrollY);
18518        } else if (parent instanceof ViewRootImpl) {
18519            final ViewRootImpl vr = (ViewRootImpl) parent;
18520            vr.transformMatrixToGlobal(m);
18521            m.preTranslate(0, -vr.mCurScrollY);
18522        }
18523
18524        m.preTranslate(mLeft, mTop);
18525
18526        if (!hasIdentityMatrix()) {
18527            m.preConcat(getMatrix());
18528        }
18529    }
18530
18531    /**
18532     * Modifies the input matrix such that it maps on-screen coordinates to
18533     * view-local coordinates.
18534     *
18535     * @param m input matrix to modify
18536     * @hide
18537     */
18538    public void transformMatrixToLocal(Matrix m) {
18539        final ViewParent parent = mParent;
18540        if (parent instanceof View) {
18541            final View vp = (View) parent;
18542            vp.transformMatrixToLocal(m);
18543            m.postTranslate(vp.mScrollX, vp.mScrollY);
18544        } else if (parent instanceof ViewRootImpl) {
18545            final ViewRootImpl vr = (ViewRootImpl) parent;
18546            vr.transformMatrixToLocal(m);
18547            m.postTranslate(0, vr.mCurScrollY);
18548        }
18549
18550        m.postTranslate(-mLeft, -mTop);
18551
18552        if (!hasIdentityMatrix()) {
18553            m.postConcat(getInverseMatrix());
18554        }
18555    }
18556
18557    /**
18558     * @hide
18559     */
18560    @ViewDebug.ExportedProperty(category = "layout", indexMapping = {
18561            @ViewDebug.IntToString(from = 0, to = "x"),
18562            @ViewDebug.IntToString(from = 1, to = "y")
18563    })
18564    public int[] getLocationOnScreen() {
18565        int[] location = new int[2];
18566        getLocationOnScreen(location);
18567        return location;
18568    }
18569
18570    /**
18571     * <p>Computes the coordinates of this view on the screen. The argument
18572     * must be an array of two integers. After the method returns, the array
18573     * contains the x and y location in that order.</p>
18574     *
18575     * @param outLocation an array of two integers in which to hold the coordinates
18576     */
18577    public void getLocationOnScreen(@Size(2) int[] outLocation) {
18578        getLocationInWindow(outLocation);
18579
18580        final AttachInfo info = mAttachInfo;
18581        if (info != null) {
18582            outLocation[0] += info.mWindowLeft;
18583            outLocation[1] += info.mWindowTop;
18584        }
18585    }
18586
18587    /**
18588     * <p>Computes the coordinates of this view in its window. The argument
18589     * must be an array of two integers. After the method returns, the array
18590     * contains the x and y location in that order.</p>
18591     *
18592     * @param outLocation an array of two integers in which to hold the coordinates
18593     */
18594    public void getLocationInWindow(@Size(2) int[] outLocation) {
18595        if (outLocation == null || outLocation.length < 2) {
18596            throw new IllegalArgumentException("outLocation must be an array of two integers");
18597        }
18598
18599        outLocation[0] = 0;
18600        outLocation[1] = 0;
18601
18602        transformFromViewToWindowSpace(outLocation);
18603    }
18604
18605    void transformFromViewToWindowSpace(@Size(2) int[] inOutLocation) {
18606        if (inOutLocation == null || inOutLocation.length < 2) {
18607            throw new IllegalArgumentException("inOutLocation must be an array of two integers");
18608        }
18609
18610        if (mAttachInfo == null) {
18611            // When the view is not attached to a window, this method does not make sense
18612            inOutLocation[0] = inOutLocation[1] = 0;
18613            return;
18614        }
18615
18616        float position[] = mAttachInfo.mTmpTransformLocation;
18617        position[0] = inOutLocation[0];
18618        position[1] = inOutLocation[1];
18619
18620        if (!hasIdentityMatrix()) {
18621            getMatrix().mapPoints(position);
18622        }
18623
18624        position[0] += mLeft;
18625        position[1] += mTop;
18626
18627        ViewParent viewParent = mParent;
18628        while (viewParent instanceof View) {
18629            final View view = (View) viewParent;
18630
18631            position[0] -= view.mScrollX;
18632            position[1] -= view.mScrollY;
18633
18634            if (!view.hasIdentityMatrix()) {
18635                view.getMatrix().mapPoints(position);
18636            }
18637
18638            position[0] += view.mLeft;
18639            position[1] += view.mTop;
18640
18641            viewParent = view.mParent;
18642         }
18643
18644        if (viewParent instanceof ViewRootImpl) {
18645            // *cough*
18646            final ViewRootImpl vr = (ViewRootImpl) viewParent;
18647            position[1] -= vr.mCurScrollY;
18648        }
18649
18650        inOutLocation[0] = Math.round(position[0]);
18651        inOutLocation[1] = Math.round(position[1]);
18652    }
18653
18654    /**
18655     * {@hide}
18656     * @param id the id of the view to be found
18657     * @return the view of the specified id, null if cannot be found
18658     */
18659    protected View findViewTraversal(@IdRes int id) {
18660        if (id == mID) {
18661            return this;
18662        }
18663        return null;
18664    }
18665
18666    /**
18667     * {@hide}
18668     * @param tag the tag of the view to be found
18669     * @return the view of specified tag, null if cannot be found
18670     */
18671    protected View findViewWithTagTraversal(Object tag) {
18672        if (tag != null && tag.equals(mTag)) {
18673            return this;
18674        }
18675        return null;
18676    }
18677
18678    /**
18679     * {@hide}
18680     * @param predicate The predicate to evaluate.
18681     * @param childToSkip If not null, ignores this child during the recursive traversal.
18682     * @return The first view that matches the predicate or null.
18683     */
18684    protected View findViewByPredicateTraversal(Predicate<View> predicate, View childToSkip) {
18685        if (predicate.apply(this)) {
18686            return this;
18687        }
18688        return null;
18689    }
18690
18691    /**
18692     * Look for a child view with the given id.  If this view has the given
18693     * id, return this view.
18694     *
18695     * @param id The id to search for.
18696     * @return The view that has the given id in the hierarchy or null
18697     */
18698    @Nullable
18699    public final View findViewById(@IdRes int id) {
18700        if (id < 0) {
18701            return null;
18702        }
18703        return findViewTraversal(id);
18704    }
18705
18706    /**
18707     * Finds a view by its unuque and stable accessibility id.
18708     *
18709     * @param accessibilityId The searched accessibility id.
18710     * @return The found view.
18711     */
18712    final View findViewByAccessibilityId(int accessibilityId) {
18713        if (accessibilityId < 0) {
18714            return null;
18715        }
18716        View view = findViewByAccessibilityIdTraversal(accessibilityId);
18717        if (view != null) {
18718            return view.includeForAccessibility() ? view : null;
18719        }
18720        return null;
18721    }
18722
18723    /**
18724     * Performs the traversal to find a view by its unuque and stable accessibility id.
18725     *
18726     * <strong>Note:</strong>This method does not stop at the root namespace
18727     * boundary since the user can touch the screen at an arbitrary location
18728     * potentially crossing the root namespace bounday which will send an
18729     * accessibility event to accessibility services and they should be able
18730     * to obtain the event source. Also accessibility ids are guaranteed to be
18731     * unique in the window.
18732     *
18733     * @param accessibilityId The accessibility id.
18734     * @return The found view.
18735     *
18736     * @hide
18737     */
18738    public View findViewByAccessibilityIdTraversal(int accessibilityId) {
18739        if (getAccessibilityViewId() == accessibilityId) {
18740            return this;
18741        }
18742        return null;
18743    }
18744
18745    /**
18746     * Look for a child view with the given tag.  If this view has the given
18747     * tag, return this view.
18748     *
18749     * @param tag The tag to search for, using "tag.equals(getTag())".
18750     * @return The View that has the given tag in the hierarchy or null
18751     */
18752    public final View findViewWithTag(Object tag) {
18753        if (tag == null) {
18754            return null;
18755        }
18756        return findViewWithTagTraversal(tag);
18757    }
18758
18759    /**
18760     * {@hide}
18761     * Look for a child view that matches the specified predicate.
18762     * If this view matches the predicate, return this view.
18763     *
18764     * @param predicate The predicate to evaluate.
18765     * @return The first view that matches the predicate or null.
18766     */
18767    public final View findViewByPredicate(Predicate<View> predicate) {
18768        return findViewByPredicateTraversal(predicate, null);
18769    }
18770
18771    /**
18772     * {@hide}
18773     * Look for a child view that matches the specified predicate,
18774     * starting with the specified view and its descendents and then
18775     * recusively searching the ancestors and siblings of that view
18776     * until this view is reached.
18777     *
18778     * This method is useful in cases where the predicate does not match
18779     * a single unique view (perhaps multiple views use the same id)
18780     * and we are trying to find the view that is "closest" in scope to the
18781     * starting view.
18782     *
18783     * @param start The view to start from.
18784     * @param predicate The predicate to evaluate.
18785     * @return The first view that matches the predicate or null.
18786     */
18787    public final View findViewByPredicateInsideOut(View start, Predicate<View> predicate) {
18788        View childToSkip = null;
18789        for (;;) {
18790            View view = start.findViewByPredicateTraversal(predicate, childToSkip);
18791            if (view != null || start == this) {
18792                return view;
18793            }
18794
18795            ViewParent parent = start.getParent();
18796            if (parent == null || !(parent instanceof View)) {
18797                return null;
18798            }
18799
18800            childToSkip = start;
18801            start = (View) parent;
18802        }
18803    }
18804
18805    /**
18806     * Sets the identifier for this view. The identifier does not have to be
18807     * unique in this view's hierarchy. The identifier should be a positive
18808     * number.
18809     *
18810     * @see #NO_ID
18811     * @see #getId()
18812     * @see #findViewById(int)
18813     *
18814     * @param id a number used to identify the view
18815     *
18816     * @attr ref android.R.styleable#View_id
18817     */
18818    public void setId(@IdRes int id) {
18819        mID = id;
18820        if (mID == View.NO_ID && mLabelForId != View.NO_ID) {
18821            mID = generateViewId();
18822        }
18823    }
18824
18825    /**
18826     * {@hide}
18827     *
18828     * @param isRoot true if the view belongs to the root namespace, false
18829     *        otherwise
18830     */
18831    public void setIsRootNamespace(boolean isRoot) {
18832        if (isRoot) {
18833            mPrivateFlags |= PFLAG_IS_ROOT_NAMESPACE;
18834        } else {
18835            mPrivateFlags &= ~PFLAG_IS_ROOT_NAMESPACE;
18836        }
18837    }
18838
18839    /**
18840     * {@hide}
18841     *
18842     * @return true if the view belongs to the root namespace, false otherwise
18843     */
18844    public boolean isRootNamespace() {
18845        return (mPrivateFlags&PFLAG_IS_ROOT_NAMESPACE) != 0;
18846    }
18847
18848    /**
18849     * Returns this view's identifier.
18850     *
18851     * @return a positive integer used to identify the view or {@link #NO_ID}
18852     *         if the view has no ID
18853     *
18854     * @see #setId(int)
18855     * @see #findViewById(int)
18856     * @attr ref android.R.styleable#View_id
18857     */
18858    @IdRes
18859    @ViewDebug.CapturedViewProperty
18860    public int getId() {
18861        return mID;
18862    }
18863
18864    /**
18865     * Returns this view's tag.
18866     *
18867     * @return the Object stored in this view as a tag, or {@code null} if not
18868     *         set
18869     *
18870     * @see #setTag(Object)
18871     * @see #getTag(int)
18872     */
18873    @ViewDebug.ExportedProperty
18874    public Object getTag() {
18875        return mTag;
18876    }
18877
18878    /**
18879     * Sets the tag associated with this view. A tag can be used to mark
18880     * a view in its hierarchy and does not have to be unique within the
18881     * hierarchy. Tags can also be used to store data within a view without
18882     * resorting to another data structure.
18883     *
18884     * @param tag an Object to tag the view with
18885     *
18886     * @see #getTag()
18887     * @see #setTag(int, Object)
18888     */
18889    public void setTag(final Object tag) {
18890        mTag = tag;
18891    }
18892
18893    /**
18894     * Returns the tag associated with this view and the specified key.
18895     *
18896     * @param key The key identifying the tag
18897     *
18898     * @return the Object stored in this view as a tag, or {@code null} if not
18899     *         set
18900     *
18901     * @see #setTag(int, Object)
18902     * @see #getTag()
18903     */
18904    public Object getTag(int key) {
18905        if (mKeyedTags != null) return mKeyedTags.get(key);
18906        return null;
18907    }
18908
18909    /**
18910     * Sets a tag associated with this view and a key. A tag can be used
18911     * to mark a view in its hierarchy and does not have to be unique within
18912     * the hierarchy. Tags can also be used to store data within a view
18913     * without resorting to another data structure.
18914     *
18915     * The specified key should be an id declared in the resources of the
18916     * application to ensure it is unique (see the <a
18917     * href="{@docRoot}guide/topics/resources/more-resources.html#Id">ID resource type</a>).
18918     * Keys identified as belonging to
18919     * the Android framework or not associated with any package will cause
18920     * an {@link IllegalArgumentException} to be thrown.
18921     *
18922     * @param key The key identifying the tag
18923     * @param tag An Object to tag the view with
18924     *
18925     * @throws IllegalArgumentException If they specified key is not valid
18926     *
18927     * @see #setTag(Object)
18928     * @see #getTag(int)
18929     */
18930    public void setTag(int key, final Object tag) {
18931        // If the package id is 0x00 or 0x01, it's either an undefined package
18932        // or a framework id
18933        if ((key >>> 24) < 2) {
18934            throw new IllegalArgumentException("The key must be an application-specific "
18935                    + "resource id.");
18936        }
18937
18938        setKeyedTag(key, tag);
18939    }
18940
18941    /**
18942     * Variation of {@link #setTag(int, Object)} that enforces the key to be a
18943     * framework id.
18944     *
18945     * @hide
18946     */
18947    public void setTagInternal(int key, Object tag) {
18948        if ((key >>> 24) != 0x1) {
18949            throw new IllegalArgumentException("The key must be a framework-specific "
18950                    + "resource id.");
18951        }
18952
18953        setKeyedTag(key, tag);
18954    }
18955
18956    private void setKeyedTag(int key, Object tag) {
18957        if (mKeyedTags == null) {
18958            mKeyedTags = new SparseArray<Object>(2);
18959        }
18960
18961        mKeyedTags.put(key, tag);
18962    }
18963
18964    /**
18965     * Prints information about this view in the log output, with the tag
18966     * {@link #VIEW_LOG_TAG}.
18967     *
18968     * @hide
18969     */
18970    public void debug() {
18971        debug(0);
18972    }
18973
18974    /**
18975     * Prints information about this view in the log output, with the tag
18976     * {@link #VIEW_LOG_TAG}. Each line in the output is preceded with an
18977     * indentation defined by the <code>depth</code>.
18978     *
18979     * @param depth the indentation level
18980     *
18981     * @hide
18982     */
18983    protected void debug(int depth) {
18984        String output = debugIndent(depth - 1);
18985
18986        output += "+ " + this;
18987        int id = getId();
18988        if (id != -1) {
18989            output += " (id=" + id + ")";
18990        }
18991        Object tag = getTag();
18992        if (tag != null) {
18993            output += " (tag=" + tag + ")";
18994        }
18995        Log.d(VIEW_LOG_TAG, output);
18996
18997        if ((mPrivateFlags & PFLAG_FOCUSED) != 0) {
18998            output = debugIndent(depth) + " FOCUSED";
18999            Log.d(VIEW_LOG_TAG, output);
19000        }
19001
19002        output = debugIndent(depth);
19003        output += "frame={" + mLeft + ", " + mTop + ", " + mRight
19004                + ", " + mBottom + "} scroll={" + mScrollX + ", " + mScrollY
19005                + "} ";
19006        Log.d(VIEW_LOG_TAG, output);
19007
19008        if (mPaddingLeft != 0 || mPaddingTop != 0 || mPaddingRight != 0
19009                || mPaddingBottom != 0) {
19010            output = debugIndent(depth);
19011            output += "padding={" + mPaddingLeft + ", " + mPaddingTop
19012                    + ", " + mPaddingRight + ", " + mPaddingBottom + "}";
19013            Log.d(VIEW_LOG_TAG, output);
19014        }
19015
19016        output = debugIndent(depth);
19017        output += "mMeasureWidth=" + mMeasuredWidth +
19018                " mMeasureHeight=" + mMeasuredHeight;
19019        Log.d(VIEW_LOG_TAG, output);
19020
19021        output = debugIndent(depth);
19022        if (mLayoutParams == null) {
19023            output += "BAD! no layout params";
19024        } else {
19025            output = mLayoutParams.debug(output);
19026        }
19027        Log.d(VIEW_LOG_TAG, output);
19028
19029        output = debugIndent(depth);
19030        output += "flags={";
19031        output += View.printFlags(mViewFlags);
19032        output += "}";
19033        Log.d(VIEW_LOG_TAG, output);
19034
19035        output = debugIndent(depth);
19036        output += "privateFlags={";
19037        output += View.printPrivateFlags(mPrivateFlags);
19038        output += "}";
19039        Log.d(VIEW_LOG_TAG, output);
19040    }
19041
19042    /**
19043     * Creates a string of whitespaces used for indentation.
19044     *
19045     * @param depth the indentation level
19046     * @return a String containing (depth * 2 + 3) * 2 white spaces
19047     *
19048     * @hide
19049     */
19050    protected static String debugIndent(int depth) {
19051        StringBuilder spaces = new StringBuilder((depth * 2 + 3) * 2);
19052        for (int i = 0; i < (depth * 2) + 3; i++) {
19053            spaces.append(' ').append(' ');
19054        }
19055        return spaces.toString();
19056    }
19057
19058    /**
19059     * <p>Return the offset of the widget's text baseline from the widget's top
19060     * boundary. If this widget does not support baseline alignment, this
19061     * method returns -1. </p>
19062     *
19063     * @return the offset of the baseline within the widget's bounds or -1
19064     *         if baseline alignment is not supported
19065     */
19066    @ViewDebug.ExportedProperty(category = "layout")
19067    public int getBaseline() {
19068        return -1;
19069    }
19070
19071    /**
19072     * Returns whether the view hierarchy is currently undergoing a layout pass. This
19073     * information is useful to avoid situations such as calling {@link #requestLayout()} during
19074     * a layout pass.
19075     *
19076     * @return whether the view hierarchy is currently undergoing a layout pass
19077     */
19078    public boolean isInLayout() {
19079        ViewRootImpl viewRoot = getViewRootImpl();
19080        return (viewRoot != null && viewRoot.isInLayout());
19081    }
19082
19083    /**
19084     * Call this when something has changed which has invalidated the
19085     * layout of this view. This will schedule a layout pass of the view
19086     * tree. This should not be called while the view hierarchy is currently in a layout
19087     * pass ({@link #isInLayout()}. If layout is happening, the request may be honored at the
19088     * end of the current layout pass (and then layout will run again) or after the current
19089     * frame is drawn and the next layout occurs.
19090     *
19091     * <p>Subclasses which override this method should call the superclass method to
19092     * handle possible request-during-layout errors correctly.</p>
19093     */
19094    @CallSuper
19095    public void requestLayout() {
19096        if (mMeasureCache != null) mMeasureCache.clear();
19097
19098        if (mAttachInfo != null && mAttachInfo.mViewRequestingLayout == null) {
19099            // Only trigger request-during-layout logic if this is the view requesting it,
19100            // not the views in its parent hierarchy
19101            ViewRootImpl viewRoot = getViewRootImpl();
19102            if (viewRoot != null && viewRoot.isInLayout()) {
19103                if (!viewRoot.requestLayoutDuringLayout(this)) {
19104                    return;
19105                }
19106            }
19107            mAttachInfo.mViewRequestingLayout = this;
19108        }
19109
19110        mPrivateFlags |= PFLAG_FORCE_LAYOUT;
19111        mPrivateFlags |= PFLAG_INVALIDATED;
19112
19113        if (mParent != null && !mParent.isLayoutRequested()) {
19114            mParent.requestLayoutForChild(this);
19115        }
19116        if (mAttachInfo != null && mAttachInfo.mViewRequestingLayout == this) {
19117            mAttachInfo.mViewRequestingLayout = null;
19118        }
19119    }
19120
19121    /**
19122     * Forces this view to be laid out during the next layout pass.
19123     * This method does not call requestLayout() or forceLayout()
19124     * on the parent.
19125     */
19126    public void forceLayout() {
19127        if (mMeasureCache != null) mMeasureCache.clear();
19128
19129        mPrivateFlags |= PFLAG_FORCE_LAYOUT;
19130        mPrivateFlags |= PFLAG_INVALIDATED;
19131    }
19132
19133    void forcePartialLayout() {
19134        forceLayout();
19135        mPrivateFlags3 |= PFLAG3_PARTIAL_LAYOUT_REQUESTED;
19136    }
19137
19138    /**
19139     * <p>
19140     * This is called to find out how big a view should be. The parent
19141     * supplies constraint information in the width and height parameters.
19142     * </p>
19143     *
19144     * <p>
19145     * The actual measurement work of a view is performed in
19146     * {@link #onMeasure(int, int)}, called by this method. Therefore, only
19147     * {@link #onMeasure(int, int)} can and must be overridden by subclasses.
19148     * </p>
19149     *
19150     *
19151     * @param widthMeasureSpec Horizontal space requirements as imposed by the
19152     *        parent
19153     * @param heightMeasureSpec Vertical space requirements as imposed by the
19154     *        parent
19155     *
19156     * @see #onMeasure(int, int)
19157     */
19158    public final void measure(int widthMeasureSpec, int heightMeasureSpec) {
19159        boolean optical = isLayoutModeOptical(this);
19160        if (optical != isLayoutModeOptical(mParent)) {
19161            Insets insets = getOpticalInsets();
19162            int oWidth  = insets.left + insets.right;
19163            int oHeight = insets.top  + insets.bottom;
19164            widthMeasureSpec  = MeasureSpec.adjust(widthMeasureSpec,  optical ? -oWidth  : oWidth);
19165            heightMeasureSpec = MeasureSpec.adjust(heightMeasureSpec, optical ? -oHeight : oHeight);
19166        }
19167
19168        // Suppress sign extension for the low bytes
19169        long key = (long) widthMeasureSpec << 32 | (long) heightMeasureSpec & 0xffffffffL;
19170        if (mMeasureCache == null) mMeasureCache = new LongSparseLongArray(2);
19171
19172        final boolean forceLayout = (mPrivateFlags & PFLAG_FORCE_LAYOUT) == PFLAG_FORCE_LAYOUT;
19173
19174        // Optimize layout by avoiding an extra EXACTLY pass when the view is
19175        // already measured as the correct size. In API 23 and below, this
19176        // extra pass is required to make LinearLayout re-distribute weight.
19177        final boolean specChanged = widthMeasureSpec != mOldWidthMeasureSpec
19178                || heightMeasureSpec != mOldHeightMeasureSpec;
19179        final boolean isSpecExactly = MeasureSpec.getMode(widthMeasureSpec) == MeasureSpec.EXACTLY
19180                && MeasureSpec.getMode(heightMeasureSpec) == MeasureSpec.EXACTLY;
19181        final boolean matchesSpecSize = getMeasuredWidth() == MeasureSpec.getSize(widthMeasureSpec)
19182                && getMeasuredHeight() == MeasureSpec.getSize(heightMeasureSpec);
19183        final boolean needsLayout = specChanged
19184                && (sAlwaysRemeasureExactly || !isSpecExactly || !matchesSpecSize);
19185
19186        if (forceLayout || needsLayout) {
19187            // first clears the measured dimension flag
19188            mPrivateFlags &= ~PFLAG_MEASURED_DIMENSION_SET;
19189
19190            resolveRtlPropertiesIfNeeded();
19191
19192            int cacheIndex = forceLayout ? -1 : mMeasureCache.indexOfKey(key);
19193            if (cacheIndex < 0 || sIgnoreMeasureCache) {
19194                // measure ourselves, this should set the measured dimension flag back
19195                onMeasure(widthMeasureSpec, heightMeasureSpec);
19196                mPrivateFlags3 &= ~PFLAG3_MEASURE_NEEDED_BEFORE_LAYOUT;
19197            } else {
19198                long value = mMeasureCache.valueAt(cacheIndex);
19199                // Casting a long to int drops the high 32 bits, no mask needed
19200                setMeasuredDimensionRaw((int) (value >> 32), (int) value);
19201                mPrivateFlags3 |= PFLAG3_MEASURE_NEEDED_BEFORE_LAYOUT;
19202            }
19203
19204            // flag not set, setMeasuredDimension() was not invoked, we raise
19205            // an exception to warn the developer
19206            if ((mPrivateFlags & PFLAG_MEASURED_DIMENSION_SET) != PFLAG_MEASURED_DIMENSION_SET) {
19207                throw new IllegalStateException("View with id " + getId() + ": "
19208                        + getClass().getName() + "#onMeasure() did not set the"
19209                        + " measured dimension by calling"
19210                        + " setMeasuredDimension()");
19211            }
19212
19213            mPrivateFlags |= PFLAG_LAYOUT_REQUIRED;
19214        }
19215
19216        mOldWidthMeasureSpec = widthMeasureSpec;
19217        mOldHeightMeasureSpec = heightMeasureSpec;
19218
19219        mMeasureCache.put(key, ((long) mMeasuredWidth) << 32 |
19220                (long) mMeasuredHeight & 0xffffffffL); // suppress sign extension
19221    }
19222
19223    /**
19224     * <p>
19225     * Measure the view and its content to determine the measured width and the
19226     * measured height. This method is invoked by {@link #measure(int, int)} and
19227     * should be overridden by subclasses to provide accurate and efficient
19228     * measurement of their contents.
19229     * </p>
19230     *
19231     * <p>
19232     * <strong>CONTRACT:</strong> When overriding this method, you
19233     * <em>must</em> call {@link #setMeasuredDimension(int, int)} to store the
19234     * measured width and height of this view. Failure to do so will trigger an
19235     * <code>IllegalStateException</code>, thrown by
19236     * {@link #measure(int, int)}. Calling the superclass'
19237     * {@link #onMeasure(int, int)} is a valid use.
19238     * </p>
19239     *
19240     * <p>
19241     * The base class implementation of measure defaults to the background size,
19242     * unless a larger size is allowed by the MeasureSpec. Subclasses should
19243     * override {@link #onMeasure(int, int)} to provide better measurements of
19244     * their content.
19245     * </p>
19246     *
19247     * <p>
19248     * If this method is overridden, it is the subclass's responsibility to make
19249     * sure the measured height and width are at least the view's minimum height
19250     * and width ({@link #getSuggestedMinimumHeight()} and
19251     * {@link #getSuggestedMinimumWidth()}).
19252     * </p>
19253     *
19254     * @param widthMeasureSpec horizontal space requirements as imposed by the parent.
19255     *                         The requirements are encoded with
19256     *                         {@link android.view.View.MeasureSpec}.
19257     * @param heightMeasureSpec vertical space requirements as imposed by the parent.
19258     *                         The requirements are encoded with
19259     *                         {@link android.view.View.MeasureSpec}.
19260     *
19261     * @see #getMeasuredWidth()
19262     * @see #getMeasuredHeight()
19263     * @see #setMeasuredDimension(int, int)
19264     * @see #getSuggestedMinimumHeight()
19265     * @see #getSuggestedMinimumWidth()
19266     * @see android.view.View.MeasureSpec#getMode(int)
19267     * @see android.view.View.MeasureSpec#getSize(int)
19268     */
19269    protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
19270        setMeasuredDimension(getDefaultSize(getSuggestedMinimumWidth(), widthMeasureSpec),
19271                getDefaultSize(getSuggestedMinimumHeight(), heightMeasureSpec));
19272    }
19273
19274    /**
19275     * <p>This method must be called by {@link #onMeasure(int, int)} to store the
19276     * measured width and measured height. Failing to do so will trigger an
19277     * exception at measurement time.</p>
19278     *
19279     * @param measuredWidth The measured width of this view.  May be a complex
19280     * bit mask as defined by {@link #MEASURED_SIZE_MASK} and
19281     * {@link #MEASURED_STATE_TOO_SMALL}.
19282     * @param measuredHeight The measured height of this view.  May be a complex
19283     * bit mask as defined by {@link #MEASURED_SIZE_MASK} and
19284     * {@link #MEASURED_STATE_TOO_SMALL}.
19285     */
19286    protected final void setMeasuredDimension(int measuredWidth, int measuredHeight) {
19287        boolean optical = isLayoutModeOptical(this);
19288        if (optical != isLayoutModeOptical(mParent)) {
19289            Insets insets = getOpticalInsets();
19290            int opticalWidth  = insets.left + insets.right;
19291            int opticalHeight = insets.top  + insets.bottom;
19292
19293            measuredWidth  += optical ? opticalWidth  : -opticalWidth;
19294            measuredHeight += optical ? opticalHeight : -opticalHeight;
19295        }
19296        setMeasuredDimensionRaw(measuredWidth, measuredHeight);
19297    }
19298
19299    /**
19300     * Sets the measured dimension without extra processing for things like optical bounds.
19301     * Useful for reapplying consistent values that have already been cooked with adjustments
19302     * for optical bounds, etc. such as those from the measurement cache.
19303     *
19304     * @param measuredWidth The measured width of this view.  May be a complex
19305     * bit mask as defined by {@link #MEASURED_SIZE_MASK} and
19306     * {@link #MEASURED_STATE_TOO_SMALL}.
19307     * @param measuredHeight The measured height of this view.  May be a complex
19308     * bit mask as defined by {@link #MEASURED_SIZE_MASK} and
19309     * {@link #MEASURED_STATE_TOO_SMALL}.
19310     */
19311    private void setMeasuredDimensionRaw(int measuredWidth, int measuredHeight) {
19312        mMeasuredWidth = measuredWidth;
19313        mMeasuredHeight = measuredHeight;
19314
19315        mPrivateFlags |= PFLAG_MEASURED_DIMENSION_SET;
19316    }
19317
19318    /**
19319     * Merge two states as returned by {@link #getMeasuredState()}.
19320     * @param curState The current state as returned from a view or the result
19321     * of combining multiple views.
19322     * @param newState The new view state to combine.
19323     * @return Returns a new integer reflecting the combination of the two
19324     * states.
19325     */
19326    public static int combineMeasuredStates(int curState, int newState) {
19327        return curState | newState;
19328    }
19329
19330    /**
19331     * Version of {@link #resolveSizeAndState(int, int, int)}
19332     * returning only the {@link #MEASURED_SIZE_MASK} bits of the result.
19333     */
19334    public static int resolveSize(int size, int measureSpec) {
19335        return resolveSizeAndState(size, measureSpec, 0) & MEASURED_SIZE_MASK;
19336    }
19337
19338    /**
19339     * Utility to reconcile a desired size and state, with constraints imposed
19340     * by a MeasureSpec. Will take the desired size, unless a different size
19341     * is imposed by the constraints. The returned value is a compound integer,
19342     * with the resolved size in the {@link #MEASURED_SIZE_MASK} bits and
19343     * optionally the bit {@link #MEASURED_STATE_TOO_SMALL} set if the
19344     * resulting size is smaller than the size the view wants to be.
19345     *
19346     * @param size How big the view wants to be.
19347     * @param measureSpec Constraints imposed by the parent.
19348     * @param childMeasuredState Size information bit mask for the view's
19349     *                           children.
19350     * @return Size information bit mask as defined by
19351     *         {@link #MEASURED_SIZE_MASK} and
19352     *         {@link #MEASURED_STATE_TOO_SMALL}.
19353     */
19354    public static int resolveSizeAndState(int size, int measureSpec, int childMeasuredState) {
19355        final int specMode = MeasureSpec.getMode(measureSpec);
19356        final int specSize = MeasureSpec.getSize(measureSpec);
19357        final int result;
19358        switch (specMode) {
19359            case MeasureSpec.AT_MOST:
19360                if (specSize < size) {
19361                    result = specSize | MEASURED_STATE_TOO_SMALL;
19362                } else {
19363                    result = size;
19364                }
19365                break;
19366            case MeasureSpec.EXACTLY:
19367                result = specSize;
19368                break;
19369            case MeasureSpec.UNSPECIFIED:
19370            default:
19371                result = size;
19372        }
19373        return result | (childMeasuredState & MEASURED_STATE_MASK);
19374    }
19375
19376    /**
19377     * Utility to return a default size. Uses the supplied size if the
19378     * MeasureSpec imposed no constraints. Will get larger if allowed
19379     * by the MeasureSpec.
19380     *
19381     * @param size Default size for this view
19382     * @param measureSpec Constraints imposed by the parent
19383     * @return The size this view should be.
19384     */
19385    public static int getDefaultSize(int size, int measureSpec) {
19386        int result = size;
19387        int specMode = MeasureSpec.getMode(measureSpec);
19388        int specSize = MeasureSpec.getSize(measureSpec);
19389
19390        switch (specMode) {
19391        case MeasureSpec.UNSPECIFIED:
19392            result = size;
19393            break;
19394        case MeasureSpec.AT_MOST:
19395        case MeasureSpec.EXACTLY:
19396            result = specSize;
19397            break;
19398        }
19399        return result;
19400    }
19401
19402    /**
19403     * Returns the suggested minimum height that the view should use. This
19404     * returns the maximum of the view's minimum height
19405     * and the background's minimum height
19406     * ({@link android.graphics.drawable.Drawable#getMinimumHeight()}).
19407     * <p>
19408     * When being used in {@link #onMeasure(int, int)}, the caller should still
19409     * ensure the returned height is within the requirements of the parent.
19410     *
19411     * @return The suggested minimum height of the view.
19412     */
19413    protected int getSuggestedMinimumHeight() {
19414        return (mBackground == null) ? mMinHeight : max(mMinHeight, mBackground.getMinimumHeight());
19415
19416    }
19417
19418    /**
19419     * Returns the suggested minimum width that the view should use. This
19420     * returns the maximum of the view's minimum width
19421     * and the background's minimum width
19422     *  ({@link android.graphics.drawable.Drawable#getMinimumWidth()}).
19423     * <p>
19424     * When being used in {@link #onMeasure(int, int)}, the caller should still
19425     * ensure the returned width is within the requirements of the parent.
19426     *
19427     * @return The suggested minimum width of the view.
19428     */
19429    protected int getSuggestedMinimumWidth() {
19430        return (mBackground == null) ? mMinWidth : max(mMinWidth, mBackground.getMinimumWidth());
19431    }
19432
19433    /**
19434     * Returns the minimum height of the view.
19435     *
19436     * @return the minimum height the view will try to be.
19437     *
19438     * @see #setMinimumHeight(int)
19439     *
19440     * @attr ref android.R.styleable#View_minHeight
19441     */
19442    public int getMinimumHeight() {
19443        return mMinHeight;
19444    }
19445
19446    /**
19447     * Sets the minimum height of the view. It is not guaranteed the view will
19448     * be able to achieve this minimum height (for example, if its parent layout
19449     * constrains it with less available height).
19450     *
19451     * @param minHeight The minimum height the view will try to be.
19452     *
19453     * @see #getMinimumHeight()
19454     *
19455     * @attr ref android.R.styleable#View_minHeight
19456     */
19457    @RemotableViewMethod
19458    public void setMinimumHeight(int minHeight) {
19459        mMinHeight = minHeight;
19460        requestLayout();
19461    }
19462
19463    /**
19464     * Returns the minimum width of the view.
19465     *
19466     * @return the minimum width the view will try to be.
19467     *
19468     * @see #setMinimumWidth(int)
19469     *
19470     * @attr ref android.R.styleable#View_minWidth
19471     */
19472    public int getMinimumWidth() {
19473        return mMinWidth;
19474    }
19475
19476    /**
19477     * Sets the minimum width of the view. It is not guaranteed the view will
19478     * be able to achieve this minimum width (for example, if its parent layout
19479     * constrains it with less available width).
19480     *
19481     * @param minWidth The minimum width the view will try to be.
19482     *
19483     * @see #getMinimumWidth()
19484     *
19485     * @attr ref android.R.styleable#View_minWidth
19486     */
19487    public void setMinimumWidth(int minWidth) {
19488        mMinWidth = minWidth;
19489        requestLayout();
19490
19491    }
19492
19493    /**
19494     * Get the animation currently associated with this view.
19495     *
19496     * @return The animation that is currently playing or
19497     *         scheduled to play for this view.
19498     */
19499    public Animation getAnimation() {
19500        return mCurrentAnimation;
19501    }
19502
19503    /**
19504     * Start the specified animation now.
19505     *
19506     * @param animation the animation to start now
19507     */
19508    public void startAnimation(Animation animation) {
19509        animation.setStartTime(Animation.START_ON_FIRST_FRAME);
19510        setAnimation(animation);
19511        invalidateParentCaches();
19512        invalidate(true);
19513    }
19514
19515    /**
19516     * Cancels any animations for this view.
19517     */
19518    public void clearAnimation() {
19519        if (mCurrentAnimation != null) {
19520            mCurrentAnimation.detach();
19521        }
19522        mCurrentAnimation = null;
19523        invalidateParentIfNeeded();
19524    }
19525
19526    /**
19527     * Sets the next animation to play for this view.
19528     * If you want the animation to play immediately, use
19529     * {@link #startAnimation(android.view.animation.Animation)} instead.
19530     * This method provides allows fine-grained
19531     * control over the start time and invalidation, but you
19532     * must make sure that 1) the animation has a start time set, and
19533     * 2) the view's parent (which controls animations on its children)
19534     * will be invalidated when the animation is supposed to
19535     * start.
19536     *
19537     * @param animation The next animation, or null.
19538     */
19539    public void setAnimation(Animation animation) {
19540        mCurrentAnimation = animation;
19541
19542        if (animation != null) {
19543            // If the screen is off assume the animation start time is now instead of
19544            // the next frame we draw. Keeping the START_ON_FIRST_FRAME start time
19545            // would cause the animation to start when the screen turns back on
19546            if (mAttachInfo != null && mAttachInfo.mDisplayState == Display.STATE_OFF
19547                    && animation.getStartTime() == Animation.START_ON_FIRST_FRAME) {
19548                animation.setStartTime(AnimationUtils.currentAnimationTimeMillis());
19549            }
19550            animation.reset();
19551        }
19552    }
19553
19554    /**
19555     * Invoked by a parent ViewGroup to notify the start of the animation
19556     * currently associated with this view. If you override this method,
19557     * always call super.onAnimationStart();
19558     *
19559     * @see #setAnimation(android.view.animation.Animation)
19560     * @see #getAnimation()
19561     */
19562    @CallSuper
19563    protected void onAnimationStart() {
19564        mPrivateFlags |= PFLAG_ANIMATION_STARTED;
19565    }
19566
19567    /**
19568     * Invoked by a parent ViewGroup to notify the end of the animation
19569     * currently associated with this view. If you override this method,
19570     * always call super.onAnimationEnd();
19571     *
19572     * @see #setAnimation(android.view.animation.Animation)
19573     * @see #getAnimation()
19574     */
19575    @CallSuper
19576    protected void onAnimationEnd() {
19577        mPrivateFlags &= ~PFLAG_ANIMATION_STARTED;
19578    }
19579
19580    /**
19581     * Invoked if there is a Transform that involves alpha. Subclass that can
19582     * draw themselves with the specified alpha should return true, and then
19583     * respect that alpha when their onDraw() is called. If this returns false
19584     * then the view may be redirected to draw into an offscreen buffer to
19585     * fulfill the request, which will look fine, but may be slower than if the
19586     * subclass handles it internally. The default implementation returns false.
19587     *
19588     * @param alpha The alpha (0..255) to apply to the view's drawing
19589     * @return true if the view can draw with the specified alpha.
19590     */
19591    protected boolean onSetAlpha(int alpha) {
19592        return false;
19593    }
19594
19595    /**
19596     * This is used by the RootView to perform an optimization when
19597     * the view hierarchy contains one or several SurfaceView.
19598     * SurfaceView is always considered transparent, but its children are not,
19599     * therefore all View objects remove themselves from the global transparent
19600     * region (passed as a parameter to this function).
19601     *
19602     * @param region The transparent region for this ViewAncestor (window).
19603     *
19604     * @return Returns true if the effective visibility of the view at this
19605     * point is opaque, regardless of the transparent region; returns false
19606     * if it is possible for underlying windows to be seen behind the view.
19607     *
19608     * {@hide}
19609     */
19610    public boolean gatherTransparentRegion(Region region) {
19611        final AttachInfo attachInfo = mAttachInfo;
19612        if (region != null && attachInfo != null) {
19613            final int pflags = mPrivateFlags;
19614            if ((pflags & PFLAG_SKIP_DRAW) == 0) {
19615                // The SKIP_DRAW flag IS NOT set, so this view draws. We need to
19616                // remove it from the transparent region.
19617                final int[] location = attachInfo.mTransparentLocation;
19618                getLocationInWindow(location);
19619                region.op(location[0], location[1], location[0] + mRight - mLeft,
19620                        location[1] + mBottom - mTop, Region.Op.DIFFERENCE);
19621            } else {
19622                if (mBackground != null && mBackground.getOpacity() != PixelFormat.TRANSPARENT) {
19623                    // The SKIP_DRAW flag IS set and the background drawable exists, we remove
19624                    // the background drawable's non-transparent parts from this transparent region.
19625                    applyDrawableToTransparentRegion(mBackground, region);
19626                }
19627                if (mForegroundInfo != null && mForegroundInfo.mDrawable != null
19628                        && mForegroundInfo.mDrawable.getOpacity() != PixelFormat.TRANSPARENT) {
19629                    // Similarly, we remove the foreground drawable's non-transparent parts.
19630                    applyDrawableToTransparentRegion(mForegroundInfo.mDrawable, region);
19631                }
19632            }
19633        }
19634        return true;
19635    }
19636
19637    /**
19638     * Play a sound effect for this view.
19639     *
19640     * <p>The framework will play sound effects for some built in actions, such as
19641     * clicking, but you may wish to play these effects in your widget,
19642     * for instance, for internal navigation.
19643     *
19644     * <p>The sound effect will only be played if sound effects are enabled by the user, and
19645     * {@link #isSoundEffectsEnabled()} is true.
19646     *
19647     * @param soundConstant One of the constants defined in {@link SoundEffectConstants}
19648     */
19649    public void playSoundEffect(int soundConstant) {
19650        if (mAttachInfo == null || mAttachInfo.mRootCallbacks == null || !isSoundEffectsEnabled()) {
19651            return;
19652        }
19653        mAttachInfo.mRootCallbacks.playSoundEffect(soundConstant);
19654    }
19655
19656    /**
19657     * BZZZTT!!1!
19658     *
19659     * <p>Provide haptic feedback to the user for this view.
19660     *
19661     * <p>The framework will provide haptic feedback for some built in actions,
19662     * such as long presses, but you may wish to provide feedback for your
19663     * own widget.
19664     *
19665     * <p>The feedback will only be performed if
19666     * {@link #isHapticFeedbackEnabled()} is true.
19667     *
19668     * @param feedbackConstant One of the constants defined in
19669     * {@link HapticFeedbackConstants}
19670     */
19671    public boolean performHapticFeedback(int feedbackConstant) {
19672        return performHapticFeedback(feedbackConstant, 0);
19673    }
19674
19675    /**
19676     * BZZZTT!!1!
19677     *
19678     * <p>Like {@link #performHapticFeedback(int)}, with additional options.
19679     *
19680     * @param feedbackConstant One of the constants defined in
19681     * {@link HapticFeedbackConstants}
19682     * @param flags Additional flags as per {@link HapticFeedbackConstants}.
19683     */
19684    public boolean performHapticFeedback(int feedbackConstant, int flags) {
19685        if (mAttachInfo == null) {
19686            return false;
19687        }
19688        //noinspection SimplifiableIfStatement
19689        if ((flags & HapticFeedbackConstants.FLAG_IGNORE_VIEW_SETTING) == 0
19690                && !isHapticFeedbackEnabled()) {
19691            return false;
19692        }
19693        return mAttachInfo.mRootCallbacks.performHapticFeedback(feedbackConstant,
19694                (flags & HapticFeedbackConstants.FLAG_IGNORE_GLOBAL_SETTING) != 0);
19695    }
19696
19697    /**
19698     * Request that the visibility of the status bar or other screen/window
19699     * decorations be changed.
19700     *
19701     * <p>This method is used to put the over device UI into temporary modes
19702     * where the user's attention is focused more on the application content,
19703     * by dimming or hiding surrounding system affordances.  This is typically
19704     * used in conjunction with {@link Window#FEATURE_ACTION_BAR_OVERLAY
19705     * Window.FEATURE_ACTION_BAR_OVERLAY}, allowing the applications content
19706     * to be placed behind the action bar (and with these flags other system
19707     * affordances) so that smooth transitions between hiding and showing them
19708     * can be done.
19709     *
19710     * <p>Two representative examples of the use of system UI visibility is
19711     * implementing a content browsing application (like a magazine reader)
19712     * and a video playing application.
19713     *
19714     * <p>The first code shows a typical implementation of a View in a content
19715     * browsing application.  In this implementation, the application goes
19716     * into a content-oriented mode by hiding the status bar and action bar,
19717     * and putting the navigation elements into lights out mode.  The user can
19718     * then interact with content while in this mode.  Such an application should
19719     * provide an easy way for the user to toggle out of the mode (such as to
19720     * check information in the status bar or access notifications).  In the
19721     * implementation here, this is done simply by tapping on the content.
19722     *
19723     * {@sample development/samples/ApiDemos/src/com/example/android/apis/view/ContentBrowserActivity.java
19724     *      content}
19725     *
19726     * <p>This second code sample shows a typical implementation of a View
19727     * in a video playing application.  In this situation, while the video is
19728     * playing the application would like to go into a complete full-screen mode,
19729     * to use as much of the display as possible for the video.  When in this state
19730     * the user can not interact with the application; the system intercepts
19731     * touching on the screen to pop the UI out of full screen mode.  See
19732     * {@link #fitSystemWindows(Rect)} for a sample layout that goes with this code.
19733     *
19734     * {@sample development/samples/ApiDemos/src/com/example/android/apis/view/VideoPlayerActivity.java
19735     *      content}
19736     *
19737     * @param visibility  Bitwise-or of flags {@link #SYSTEM_UI_FLAG_LOW_PROFILE},
19738     * {@link #SYSTEM_UI_FLAG_HIDE_NAVIGATION}, {@link #SYSTEM_UI_FLAG_FULLSCREEN},
19739     * {@link #SYSTEM_UI_FLAG_LAYOUT_STABLE}, {@link #SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION},
19740     * {@link #SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN}, {@link #SYSTEM_UI_FLAG_IMMERSIVE},
19741     * and {@link #SYSTEM_UI_FLAG_IMMERSIVE_STICKY}.
19742     */
19743    public void setSystemUiVisibility(int visibility) {
19744        if (visibility != mSystemUiVisibility) {
19745            mSystemUiVisibility = visibility;
19746            if (mParent != null && mAttachInfo != null && !mAttachInfo.mRecomputeGlobalAttributes) {
19747                mParent.recomputeViewAttributes(this);
19748            }
19749        }
19750    }
19751
19752    /**
19753     * Returns the last {@link #setSystemUiVisibility(int)} that this view has requested.
19754     * @return  Bitwise-or of flags {@link #SYSTEM_UI_FLAG_LOW_PROFILE},
19755     * {@link #SYSTEM_UI_FLAG_HIDE_NAVIGATION}, {@link #SYSTEM_UI_FLAG_FULLSCREEN},
19756     * {@link #SYSTEM_UI_FLAG_LAYOUT_STABLE}, {@link #SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION},
19757     * {@link #SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN}, {@link #SYSTEM_UI_FLAG_IMMERSIVE},
19758     * and {@link #SYSTEM_UI_FLAG_IMMERSIVE_STICKY}.
19759     */
19760    public int getSystemUiVisibility() {
19761        return mSystemUiVisibility;
19762    }
19763
19764    /**
19765     * Returns the current system UI visibility that is currently set for
19766     * the entire window.  This is the combination of the
19767     * {@link #setSystemUiVisibility(int)} values supplied by all of the
19768     * views in the window.
19769     */
19770    public int getWindowSystemUiVisibility() {
19771        return mAttachInfo != null ? mAttachInfo.mSystemUiVisibility : 0;
19772    }
19773
19774    /**
19775     * Override to find out when the window's requested system UI visibility
19776     * has changed, that is the value returned by {@link #getWindowSystemUiVisibility()}.
19777     * This is different from the callbacks received through
19778     * {@link #setOnSystemUiVisibilityChangeListener(OnSystemUiVisibilityChangeListener)}
19779     * in that this is only telling you about the local request of the window,
19780     * not the actual values applied by the system.
19781     */
19782    public void onWindowSystemUiVisibilityChanged(int visible) {
19783    }
19784
19785    /**
19786     * Dispatch callbacks to {@link #onWindowSystemUiVisibilityChanged(int)} down
19787     * the view hierarchy.
19788     */
19789    public void dispatchWindowSystemUiVisiblityChanged(int visible) {
19790        onWindowSystemUiVisibilityChanged(visible);
19791    }
19792
19793    /**
19794     * Set a listener to receive callbacks when the visibility of the system bar changes.
19795     * @param l  The {@link OnSystemUiVisibilityChangeListener} to receive callbacks.
19796     */
19797    public void setOnSystemUiVisibilityChangeListener(OnSystemUiVisibilityChangeListener l) {
19798        getListenerInfo().mOnSystemUiVisibilityChangeListener = l;
19799        if (mParent != null && mAttachInfo != null && !mAttachInfo.mRecomputeGlobalAttributes) {
19800            mParent.recomputeViewAttributes(this);
19801        }
19802    }
19803
19804    /**
19805     * Dispatch callbacks to {@link #setOnSystemUiVisibilityChangeListener} down
19806     * the view hierarchy.
19807     */
19808    public void dispatchSystemUiVisibilityChanged(int visibility) {
19809        ListenerInfo li = mListenerInfo;
19810        if (li != null && li.mOnSystemUiVisibilityChangeListener != null) {
19811            li.mOnSystemUiVisibilityChangeListener.onSystemUiVisibilityChange(
19812                    visibility & PUBLIC_STATUS_BAR_VISIBILITY_MASK);
19813        }
19814    }
19815
19816    boolean updateLocalSystemUiVisibility(int localValue, int localChanges) {
19817        int val = (mSystemUiVisibility&~localChanges) | (localValue&localChanges);
19818        if (val != mSystemUiVisibility) {
19819            setSystemUiVisibility(val);
19820            return true;
19821        }
19822        return false;
19823    }
19824
19825    /** @hide */
19826    public void setDisabledSystemUiVisibility(int flags) {
19827        if (mAttachInfo != null) {
19828            if (mAttachInfo.mDisabledSystemUiVisibility != flags) {
19829                mAttachInfo.mDisabledSystemUiVisibility = flags;
19830                if (mParent != null) {
19831                    mParent.recomputeViewAttributes(this);
19832                }
19833            }
19834        }
19835    }
19836
19837    /**
19838     * Creates an image that the system displays during the drag and drop
19839     * operation. This is called a &quot;drag shadow&quot;. The default implementation
19840     * for a DragShadowBuilder based on a View returns an image that has exactly the same
19841     * appearance as the given View. The default also positions the center of the drag shadow
19842     * directly under the touch point. If no View is provided (the constructor with no parameters
19843     * is used), and {@link #onProvideShadowMetrics(Point,Point) onProvideShadowMetrics()} and
19844     * {@link #onDrawShadow(Canvas) onDrawShadow()} are not overridden, then the
19845     * default is an invisible drag shadow.
19846     * <p>
19847     * You are not required to use the View you provide to the constructor as the basis of the
19848     * drag shadow. The {@link #onDrawShadow(Canvas) onDrawShadow()} method allows you to draw
19849     * anything you want as the drag shadow.
19850     * </p>
19851     * <p>
19852     *  You pass a DragShadowBuilder object to the system when you start the drag. The system
19853     *  calls {@link #onProvideShadowMetrics(Point,Point) onProvideShadowMetrics()} to get the
19854     *  size and position of the drag shadow. It uses this data to construct a
19855     *  {@link android.graphics.Canvas} object, then it calls {@link #onDrawShadow(Canvas) onDrawShadow()}
19856     *  so that your application can draw the shadow image in the Canvas.
19857     * </p>
19858     *
19859     * <div class="special reference">
19860     * <h3>Developer Guides</h3>
19861     * <p>For a guide to implementing drag and drop features, read the
19862     * <a href="{@docRoot}guide/topics/ui/drag-drop.html">Drag and Drop</a> developer guide.</p>
19863     * </div>
19864     */
19865    public static class DragShadowBuilder {
19866        private final WeakReference<View> mView;
19867
19868        /**
19869         * Constructs a shadow image builder based on a View. By default, the resulting drag
19870         * shadow will have the same appearance and dimensions as the View, with the touch point
19871         * over the center of the View.
19872         * @param view A View. Any View in scope can be used.
19873         */
19874        public DragShadowBuilder(View view) {
19875            mView = new WeakReference<View>(view);
19876        }
19877
19878        /**
19879         * Construct a shadow builder object with no associated View.  This
19880         * constructor variant is only useful when the {@link #onProvideShadowMetrics(Point, Point)}
19881         * and {@link #onDrawShadow(Canvas)} methods are also overridden in order
19882         * to supply the drag shadow's dimensions and appearance without
19883         * reference to any View object. If they are not overridden, then the result is an
19884         * invisible drag shadow.
19885         */
19886        public DragShadowBuilder() {
19887            mView = new WeakReference<View>(null);
19888        }
19889
19890        /**
19891         * Returns the View object that had been passed to the
19892         * {@link #View.DragShadowBuilder(View)}
19893         * constructor.  If that View parameter was {@code null} or if the
19894         * {@link #View.DragShadowBuilder()}
19895         * constructor was used to instantiate the builder object, this method will return
19896         * null.
19897         *
19898         * @return The View object associate with this builder object.
19899         */
19900        @SuppressWarnings({"JavadocReference"})
19901        final public View getView() {
19902            return mView.get();
19903        }
19904
19905        /**
19906         * Provides the metrics for the shadow image. These include the dimensions of
19907         * the shadow image, and the point within that shadow that should
19908         * be centered under the touch location while dragging.
19909         * <p>
19910         * The default implementation sets the dimensions of the shadow to be the
19911         * same as the dimensions of the View itself and centers the shadow under
19912         * the touch point.
19913         * </p>
19914         *
19915         * @param shadowSize A {@link android.graphics.Point} containing the width and height
19916         * of the shadow image. Your application must set {@link android.graphics.Point#x} to the
19917         * desired width and must set {@link android.graphics.Point#y} to the desired height of the
19918         * image.
19919         *
19920         * @param shadowTouchPoint A {@link android.graphics.Point} for the position within the
19921         * shadow image that should be underneath the touch point during the drag and drop
19922         * operation. Your application must set {@link android.graphics.Point#x} to the
19923         * X coordinate and {@link android.graphics.Point#y} to the Y coordinate of this position.
19924         */
19925        public void onProvideShadowMetrics(Point shadowSize, Point shadowTouchPoint) {
19926            final View view = mView.get();
19927            if (view != null) {
19928                shadowSize.set(view.getWidth(), view.getHeight());
19929                shadowTouchPoint.set(shadowSize.x / 2, shadowSize.y / 2);
19930            } else {
19931                Log.e(View.VIEW_LOG_TAG, "Asked for drag thumb metrics but no view");
19932            }
19933        }
19934
19935        /**
19936         * Draws the shadow image. The system creates the {@link android.graphics.Canvas} object
19937         * based on the dimensions it received from the
19938         * {@link #onProvideShadowMetrics(Point, Point)} callback.
19939         *
19940         * @param canvas A {@link android.graphics.Canvas} object in which to draw the shadow image.
19941         */
19942        public void onDrawShadow(Canvas canvas) {
19943            final View view = mView.get();
19944            if (view != null) {
19945                view.draw(canvas);
19946            } else {
19947                Log.e(View.VIEW_LOG_TAG, "Asked to draw drag shadow but no view");
19948            }
19949        }
19950    }
19951
19952    /**
19953     * @deprecated Use {@link #startDragAndDrop(ClipData, DragShadowBuilder, Object, int)
19954     * startDragAndDrop()} for newer platform versions.
19955     */
19956    public final boolean startDrag(ClipData data, DragShadowBuilder shadowBuilder,
19957                                   Object myLocalState, int flags) {
19958        return startDragAndDrop(data, shadowBuilder, myLocalState, flags);
19959    }
19960
19961    /**
19962     * Starts a drag and drop operation. When your application calls this method, it passes a
19963     * {@link android.view.View.DragShadowBuilder} object to the system. The
19964     * system calls this object's {@link DragShadowBuilder#onProvideShadowMetrics(Point, Point)}
19965     * to get metrics for the drag shadow, and then calls the object's
19966     * {@link DragShadowBuilder#onDrawShadow(Canvas)} to draw the drag shadow itself.
19967     * <p>
19968     *  Once the system has the drag shadow, it begins the drag and drop operation by sending
19969     *  drag events to all the View objects in your application that are currently visible. It does
19970     *  this either by calling the View object's drag listener (an implementation of
19971     *  {@link android.view.View.OnDragListener#onDrag(View,DragEvent) onDrag()} or by calling the
19972     *  View object's {@link android.view.View#onDragEvent(DragEvent) onDragEvent()} method.
19973     *  Both are passed a {@link android.view.DragEvent} object that has a
19974     *  {@link android.view.DragEvent#getAction()} value of
19975     *  {@link android.view.DragEvent#ACTION_DRAG_STARTED}.
19976     * </p>
19977     * <p>
19978     * Your application can invoke {@link #startDragAndDrop(ClipData, DragShadowBuilder, Object,
19979     * int) startDragAndDrop()} on any attached View object. The View object does not need to be
19980     * the one used in {@link android.view.View.DragShadowBuilder}, nor does it need to be related
19981     * to the View the user selected for dragging.
19982     * </p>
19983     * @param data A {@link android.content.ClipData} object pointing to the data to be
19984     * transferred by the drag and drop operation.
19985     * @param shadowBuilder A {@link android.view.View.DragShadowBuilder} object for building the
19986     * drag shadow.
19987     * @param myLocalState An {@link java.lang.Object} containing local data about the drag and
19988     * drop operation. This Object is put into every DragEvent object sent by the system during the
19989     * current drag.
19990     * <p>
19991     * myLocalState is a lightweight mechanism for the sending information from the dragged View
19992     * to the target Views. For example, it can contain flags that differentiate between a
19993     * a copy operation and a move operation.
19994     * </p>
19995     * @param flags Flags that control the drag and drop operation. No flags are currently defined,
19996     * so the parameter should be set to 0.
19997     * @return {@code true} if the method completes successfully, or
19998     * {@code false} if it fails anywhere. Returning {@code false} means the system was unable to
19999     * do a drag, and so no drag operation is in progress.
20000     */
20001    public final boolean startDragAndDrop(ClipData data, DragShadowBuilder shadowBuilder,
20002            Object myLocalState, int flags) {
20003        if (ViewDebug.DEBUG_DRAG) {
20004            Log.d(VIEW_LOG_TAG, "startDragAndDrop: data=" + data + " flags=" + flags);
20005        }
20006        boolean okay = false;
20007
20008        Point shadowSize = new Point();
20009        Point shadowTouchPoint = new Point();
20010        shadowBuilder.onProvideShadowMetrics(shadowSize, shadowTouchPoint);
20011
20012        if ((shadowSize.x < 0) || (shadowSize.y < 0) ||
20013                (shadowTouchPoint.x < 0) || (shadowTouchPoint.y < 0)) {
20014            throw new IllegalStateException("Drag shadow dimensions must not be negative");
20015        }
20016
20017        if (ViewDebug.DEBUG_DRAG) {
20018            Log.d(VIEW_LOG_TAG, "drag shadow: width=" + shadowSize.x + " height=" + shadowSize.y
20019                    + " shadowX=" + shadowTouchPoint.x + " shadowY=" + shadowTouchPoint.y);
20020        }
20021        if (mAttachInfo.mDragSurface != null) {
20022            mAttachInfo.mDragSurface.release();
20023        }
20024        mAttachInfo.mDragSurface = new Surface();
20025        try {
20026            mAttachInfo.mDragToken = mAttachInfo.mSession.prepareDrag(mAttachInfo.mWindow,
20027                    flags, shadowSize.x, shadowSize.y, mAttachInfo.mDragSurface);
20028            if (ViewDebug.DEBUG_DRAG) Log.d(VIEW_LOG_TAG, "prepareDrag returned token="
20029                    + mAttachInfo.mDragToken + " surface=" + mAttachInfo.mDragSurface);
20030            if (mAttachInfo.mDragToken != null) {
20031                Canvas canvas = mAttachInfo.mDragSurface.lockCanvas(null);
20032                try {
20033                    canvas.drawColor(0, PorterDuff.Mode.CLEAR);
20034                    shadowBuilder.onDrawShadow(canvas);
20035                } finally {
20036                    mAttachInfo.mDragSurface.unlockCanvasAndPost(canvas);
20037                }
20038
20039                final ViewRootImpl root = getViewRootImpl();
20040
20041                // Cache the local state object for delivery with DragEvents
20042                root.setLocalDragState(myLocalState);
20043
20044                // repurpose 'shadowSize' for the last touch point
20045                root.getLastTouchPoint(shadowSize);
20046
20047                okay = mAttachInfo.mSession.performDrag(mAttachInfo.mWindow, mAttachInfo.mDragToken,
20048                        shadowSize.x, shadowSize.y,
20049                        shadowTouchPoint.x, shadowTouchPoint.y, data);
20050                if (ViewDebug.DEBUG_DRAG) Log.d(VIEW_LOG_TAG, "performDrag returned " + okay);
20051            }
20052        } catch (Exception e) {
20053            Log.e(VIEW_LOG_TAG, "Unable to initiate drag", e);
20054            mAttachInfo.mDragSurface.destroy();
20055            mAttachInfo.mDragSurface = null;
20056        }
20057
20058        return okay;
20059    }
20060
20061    /**
20062     * Cancels an ongoing drag and drop operation.
20063     * <p>
20064     * A {@link android.view.DragEvent} object with
20065     * {@link android.view.DragEvent#getAction()} value of
20066     * {@link android.view.DragEvent#ACTION_DRAG_ENDED} and
20067     * {@link android.view.DragEvent#getResult()} value of {@code false}
20068     * will be sent to every
20069     * View that received {@link android.view.DragEvent#ACTION_DRAG_STARTED}
20070     * even if they are not currently visible.
20071     * </p>
20072     * <p>
20073     * This method can be called on any View in the same window as the View on which
20074     * {@link #startDragAndDrop(ClipData, DragShadowBuilder, Object, int) startDragAndDrop}
20075     * was called.
20076     * </p>
20077     */
20078    public final void cancelDragAndDrop() {
20079        if (ViewDebug.DEBUG_DRAG) {
20080            Log.d(VIEW_LOG_TAG, "cancelDragAndDrop");
20081        }
20082        if (mAttachInfo.mDragToken != null) {
20083            try {
20084                mAttachInfo.mSession.cancelDragAndDrop(mAttachInfo.mDragToken);
20085            } catch (Exception e) {
20086                Log.e(VIEW_LOG_TAG, "Unable to cancel drag", e);
20087            }
20088            mAttachInfo.mDragToken = null;
20089        } else {
20090            Log.e(VIEW_LOG_TAG, "No active drag to cancel");
20091        }
20092    }
20093
20094    public final void updateDragShadow(DragShadowBuilder shadowBuilder) {
20095        if (ViewDebug.DEBUG_DRAG) {
20096            Log.d(VIEW_LOG_TAG, "updateDragShadow");
20097        }
20098        if (mAttachInfo.mDragToken != null) {
20099            try {
20100                Canvas canvas = mAttachInfo.mDragSurface.lockCanvas(null);
20101                try {
20102                    canvas.drawColor(0, PorterDuff.Mode.CLEAR);
20103                    shadowBuilder.onDrawShadow(canvas);
20104                } finally {
20105                    mAttachInfo.mDragSurface.unlockCanvasAndPost(canvas);
20106                }
20107            } catch (Exception e) {
20108                Log.e(VIEW_LOG_TAG, "Unable to update drag shadow", e);
20109            }
20110        } else {
20111            Log.e(VIEW_LOG_TAG, "No active drag");
20112        }
20113    }
20114
20115    /**
20116     * Starts a move from {startX, startY}, the amount of the movement will be the offset
20117     * between {startX, startY} and the new cursor positon.
20118     * @param startX horizontal coordinate where the move started.
20119     * @param startY vertical coordinate where the move started.
20120     * @return whether moving was started successfully.
20121     * @hide
20122     */
20123    public final boolean startMovingTask(float startX, float startY) {
20124        if (ViewDebug.DEBUG_POSITIONING) {
20125            Log.d(VIEW_LOG_TAG, "startMovingTask: {" + startX + "," + startY + "}");
20126        }
20127        try {
20128            return mAttachInfo.mSession.startMovingTask(mAttachInfo.mWindow, startX, startY);
20129        } catch (RemoteException e) {
20130            Log.e(VIEW_LOG_TAG, "Unable to start moving", e);
20131        }
20132        return false;
20133    }
20134
20135    /**
20136     * Handles drag events sent by the system following a call to
20137     * {@link android.view.View#startDragAndDrop(ClipData,DragShadowBuilder,Object,int)
20138     * startDragAndDrop()}.
20139     *<p>
20140     * When the system calls this method, it passes a
20141     * {@link android.view.DragEvent} object. A call to
20142     * {@link android.view.DragEvent#getAction()} returns one of the action type constants defined
20143     * in DragEvent. The method uses these to determine what is happening in the drag and drop
20144     * operation.
20145     * @param event The {@link android.view.DragEvent} sent by the system.
20146     * The {@link android.view.DragEvent#getAction()} method returns an action type constant defined
20147     * in DragEvent, indicating the type of drag event represented by this object.
20148     * @return {@code true} if the method was successful, otherwise {@code false}.
20149     * <p>
20150     *  The method should return {@code true} in response to an action type of
20151     *  {@link android.view.DragEvent#ACTION_DRAG_STARTED} to receive drag events for the current
20152     *  operation.
20153     * </p>
20154     * <p>
20155     *  The method should also return {@code true} in response to an action type of
20156     *  {@link android.view.DragEvent#ACTION_DROP} if it consumed the drop, or
20157     *  {@code false} if it didn't.
20158     * </p>
20159     */
20160    public boolean onDragEvent(DragEvent event) {
20161        return false;
20162    }
20163
20164    /**
20165     * Detects if this View is enabled and has a drag event listener.
20166     * If both are true, then it calls the drag event listener with the
20167     * {@link android.view.DragEvent} it received. If the drag event listener returns
20168     * {@code true}, then dispatchDragEvent() returns {@code true}.
20169     * <p>
20170     * For all other cases, the method calls the
20171     * {@link android.view.View#onDragEvent(DragEvent) onDragEvent()} drag event handler
20172     * method and returns its result.
20173     * </p>
20174     * <p>
20175     * This ensures that a drag event is always consumed, even if the View does not have a drag
20176     * event listener. However, if the View has a listener and the listener returns true, then
20177     * onDragEvent() is not called.
20178     * </p>
20179     */
20180    public boolean dispatchDragEvent(DragEvent event) {
20181        ListenerInfo li = mListenerInfo;
20182        //noinspection SimplifiableIfStatement
20183        if (li != null && li.mOnDragListener != null && (mViewFlags & ENABLED_MASK) == ENABLED
20184                && li.mOnDragListener.onDrag(this, event)) {
20185            return true;
20186        }
20187        return onDragEvent(event);
20188    }
20189
20190    boolean canAcceptDrag() {
20191        return (mPrivateFlags2 & PFLAG2_DRAG_CAN_ACCEPT) != 0;
20192    }
20193
20194    /**
20195     * This needs to be a better API (NOT ON VIEW) before it is exposed.  If
20196     * it is ever exposed at all.
20197     * @hide
20198     */
20199    public void onCloseSystemDialogs(String reason) {
20200    }
20201
20202    /**
20203     * Given a Drawable whose bounds have been set to draw into this view,
20204     * update a Region being computed for
20205     * {@link #gatherTransparentRegion(android.graphics.Region)} so
20206     * that any non-transparent parts of the Drawable are removed from the
20207     * given transparent region.
20208     *
20209     * @param dr The Drawable whose transparency is to be applied to the region.
20210     * @param region A Region holding the current transparency information,
20211     * where any parts of the region that are set are considered to be
20212     * transparent.  On return, this region will be modified to have the
20213     * transparency information reduced by the corresponding parts of the
20214     * Drawable that are not transparent.
20215     * {@hide}
20216     */
20217    public void applyDrawableToTransparentRegion(Drawable dr, Region region) {
20218        if (DBG) {
20219            Log.i("View", "Getting transparent region for: " + this);
20220        }
20221        final Region r = dr.getTransparentRegion();
20222        final Rect db = dr.getBounds();
20223        final AttachInfo attachInfo = mAttachInfo;
20224        if (r != null && attachInfo != null) {
20225            final int w = getRight()-getLeft();
20226            final int h = getBottom()-getTop();
20227            if (db.left > 0) {
20228                //Log.i("VIEW", "Drawable left " + db.left + " > view 0");
20229                r.op(0, 0, db.left, h, Region.Op.UNION);
20230            }
20231            if (db.right < w) {
20232                //Log.i("VIEW", "Drawable right " + db.right + " < view " + w);
20233                r.op(db.right, 0, w, h, Region.Op.UNION);
20234            }
20235            if (db.top > 0) {
20236                //Log.i("VIEW", "Drawable top " + db.top + " > view 0");
20237                r.op(0, 0, w, db.top, Region.Op.UNION);
20238            }
20239            if (db.bottom < h) {
20240                //Log.i("VIEW", "Drawable bottom " + db.bottom + " < view " + h);
20241                r.op(0, db.bottom, w, h, Region.Op.UNION);
20242            }
20243            final int[] location = attachInfo.mTransparentLocation;
20244            getLocationInWindow(location);
20245            r.translate(location[0], location[1]);
20246            region.op(r, Region.Op.INTERSECT);
20247        } else {
20248            region.op(db, Region.Op.DIFFERENCE);
20249        }
20250    }
20251
20252    private void checkForLongClick(int delayOffset, float x, float y) {
20253        if ((mViewFlags & LONG_CLICKABLE) == LONG_CLICKABLE) {
20254            mHasPerformedLongPress = false;
20255
20256            if (mPendingCheckForLongPress == null) {
20257                mPendingCheckForLongPress = new CheckForLongPress();
20258            }
20259            mPendingCheckForLongPress.setAnchor(x, y);
20260            mPendingCheckForLongPress.rememberWindowAttachCount();
20261            postDelayed(mPendingCheckForLongPress,
20262                    ViewConfiguration.getLongPressTimeout() - delayOffset);
20263        }
20264    }
20265
20266    /**
20267     * Inflate a view from an XML resource.  This convenience method wraps the {@link
20268     * LayoutInflater} class, which provides a full range of options for view inflation.
20269     *
20270     * @param context The Context object for your activity or application.
20271     * @param resource The resource ID to inflate
20272     * @param root A view group that will be the parent.  Used to properly inflate the
20273     * layout_* parameters.
20274     * @see LayoutInflater
20275     */
20276    public static View inflate(Context context, @LayoutRes int resource, ViewGroup root) {
20277        LayoutInflater factory = LayoutInflater.from(context);
20278        return factory.inflate(resource, root);
20279    }
20280
20281    /**
20282     * Scroll the view with standard behavior for scrolling beyond the normal
20283     * content boundaries. Views that call this method should override
20284     * {@link #onOverScrolled(int, int, boolean, boolean)} to respond to the
20285     * results of an over-scroll operation.
20286     *
20287     * Views can use this method to handle any touch or fling-based scrolling.
20288     *
20289     * @param deltaX Change in X in pixels
20290     * @param deltaY Change in Y in pixels
20291     * @param scrollX Current X scroll value in pixels before applying deltaX
20292     * @param scrollY Current Y scroll value in pixels before applying deltaY
20293     * @param scrollRangeX Maximum content scroll range along the X axis
20294     * @param scrollRangeY Maximum content scroll range along the Y axis
20295     * @param maxOverScrollX Number of pixels to overscroll by in either direction
20296     *          along the X axis.
20297     * @param maxOverScrollY Number of pixels to overscroll by in either direction
20298     *          along the Y axis.
20299     * @param isTouchEvent true if this scroll operation is the result of a touch event.
20300     * @return true if scrolling was clamped to an over-scroll boundary along either
20301     *          axis, false otherwise.
20302     */
20303    @SuppressWarnings({"UnusedParameters"})
20304    protected boolean overScrollBy(int deltaX, int deltaY,
20305            int scrollX, int scrollY,
20306            int scrollRangeX, int scrollRangeY,
20307            int maxOverScrollX, int maxOverScrollY,
20308            boolean isTouchEvent) {
20309        final int overScrollMode = mOverScrollMode;
20310        final boolean canScrollHorizontal =
20311                computeHorizontalScrollRange() > computeHorizontalScrollExtent();
20312        final boolean canScrollVertical =
20313                computeVerticalScrollRange() > computeVerticalScrollExtent();
20314        final boolean overScrollHorizontal = overScrollMode == OVER_SCROLL_ALWAYS ||
20315                (overScrollMode == OVER_SCROLL_IF_CONTENT_SCROLLS && canScrollHorizontal);
20316        final boolean overScrollVertical = overScrollMode == OVER_SCROLL_ALWAYS ||
20317                (overScrollMode == OVER_SCROLL_IF_CONTENT_SCROLLS && canScrollVertical);
20318
20319        int newScrollX = scrollX + deltaX;
20320        if (!overScrollHorizontal) {
20321            maxOverScrollX = 0;
20322        }
20323
20324        int newScrollY = scrollY + deltaY;
20325        if (!overScrollVertical) {
20326            maxOverScrollY = 0;
20327        }
20328
20329        // Clamp values if at the limits and record
20330        final int left = -maxOverScrollX;
20331        final int right = maxOverScrollX + scrollRangeX;
20332        final int top = -maxOverScrollY;
20333        final int bottom = maxOverScrollY + scrollRangeY;
20334
20335        boolean clampedX = false;
20336        if (newScrollX > right) {
20337            newScrollX = right;
20338            clampedX = true;
20339        } else if (newScrollX < left) {
20340            newScrollX = left;
20341            clampedX = true;
20342        }
20343
20344        boolean clampedY = false;
20345        if (newScrollY > bottom) {
20346            newScrollY = bottom;
20347            clampedY = true;
20348        } else if (newScrollY < top) {
20349            newScrollY = top;
20350            clampedY = true;
20351        }
20352
20353        onOverScrolled(newScrollX, newScrollY, clampedX, clampedY);
20354
20355        return clampedX || clampedY;
20356    }
20357
20358    /**
20359     * Called by {@link #overScrollBy(int, int, int, int, int, int, int, int, boolean)} to
20360     * respond to the results of an over-scroll operation.
20361     *
20362     * @param scrollX New X scroll value in pixels
20363     * @param scrollY New Y scroll value in pixels
20364     * @param clampedX True if scrollX was clamped to an over-scroll boundary
20365     * @param clampedY True if scrollY was clamped to an over-scroll boundary
20366     */
20367    protected void onOverScrolled(int scrollX, int scrollY,
20368            boolean clampedX, boolean clampedY) {
20369        // Intentionally empty.
20370    }
20371
20372    /**
20373     * Returns the over-scroll mode for this view. The result will be
20374     * one of {@link #OVER_SCROLL_ALWAYS} (default), {@link #OVER_SCROLL_IF_CONTENT_SCROLLS}
20375     * (allow over-scrolling only if the view content is larger than the container),
20376     * or {@link #OVER_SCROLL_NEVER}.
20377     *
20378     * @return This view's over-scroll mode.
20379     */
20380    public int getOverScrollMode() {
20381        return mOverScrollMode;
20382    }
20383
20384    /**
20385     * Set the over-scroll mode for this view. Valid over-scroll modes are
20386     * {@link #OVER_SCROLL_ALWAYS} (default), {@link #OVER_SCROLL_IF_CONTENT_SCROLLS}
20387     * (allow over-scrolling only if the view content is larger than the container),
20388     * or {@link #OVER_SCROLL_NEVER}.
20389     *
20390     * Setting the over-scroll mode of a view will have an effect only if the
20391     * view is capable of scrolling.
20392     *
20393     * @param overScrollMode The new over-scroll mode for this view.
20394     */
20395    public void setOverScrollMode(int overScrollMode) {
20396        if (overScrollMode != OVER_SCROLL_ALWAYS &&
20397                overScrollMode != OVER_SCROLL_IF_CONTENT_SCROLLS &&
20398                overScrollMode != OVER_SCROLL_NEVER) {
20399            throw new IllegalArgumentException("Invalid overscroll mode " + overScrollMode);
20400        }
20401        mOverScrollMode = overScrollMode;
20402    }
20403
20404    /**
20405     * Enable or disable nested scrolling for this view.
20406     *
20407     * <p>If this property is set to true the view will be permitted to initiate nested
20408     * scrolling operations with a compatible parent view in the current hierarchy. If this
20409     * view does not implement nested scrolling this will have no effect. Disabling nested scrolling
20410     * while a nested scroll is in progress has the effect of {@link #stopNestedScroll() stopping}
20411     * the nested scroll.</p>
20412     *
20413     * @param enabled true to enable nested scrolling, false to disable
20414     *
20415     * @see #isNestedScrollingEnabled()
20416     */
20417    public void setNestedScrollingEnabled(boolean enabled) {
20418        if (enabled) {
20419            mPrivateFlags3 |= PFLAG3_NESTED_SCROLLING_ENABLED;
20420        } else {
20421            stopNestedScroll();
20422            mPrivateFlags3 &= ~PFLAG3_NESTED_SCROLLING_ENABLED;
20423        }
20424    }
20425
20426    /**
20427     * Returns true if nested scrolling is enabled for this view.
20428     *
20429     * <p>If nested scrolling is enabled and this View class implementation supports it,
20430     * this view will act as a nested scrolling child view when applicable, forwarding data
20431     * about the scroll operation in progress to a compatible and cooperating nested scrolling
20432     * parent.</p>
20433     *
20434     * @return true if nested scrolling is enabled
20435     *
20436     * @see #setNestedScrollingEnabled(boolean)
20437     */
20438    public boolean isNestedScrollingEnabled() {
20439        return (mPrivateFlags3 & PFLAG3_NESTED_SCROLLING_ENABLED) ==
20440                PFLAG3_NESTED_SCROLLING_ENABLED;
20441    }
20442
20443    /**
20444     * Begin a nestable scroll operation along the given axes.
20445     *
20446     * <p>A view starting a nested scroll promises to abide by the following contract:</p>
20447     *
20448     * <p>The view will call startNestedScroll upon initiating a scroll operation. In the case
20449     * of a touch scroll this corresponds to the initial {@link MotionEvent#ACTION_DOWN}.
20450     * In the case of touch scrolling the nested scroll will be terminated automatically in
20451     * the same manner as {@link ViewParent#requestDisallowInterceptTouchEvent(boolean)}.
20452     * In the event of programmatic scrolling the caller must explicitly call
20453     * {@link #stopNestedScroll()} to indicate the end of the nested scroll.</p>
20454     *
20455     * <p>If <code>startNestedScroll</code> returns true, a cooperative parent was found.
20456     * If it returns false the caller may ignore the rest of this contract until the next scroll.
20457     * Calling startNestedScroll while a nested scroll is already in progress will return true.</p>
20458     *
20459     * <p>At each incremental step of the scroll the caller should invoke
20460     * {@link #dispatchNestedPreScroll(int, int, int[], int[]) dispatchNestedPreScroll}
20461     * once it has calculated the requested scrolling delta. If it returns true the nested scrolling
20462     * parent at least partially consumed the scroll and the caller should adjust the amount it
20463     * scrolls by.</p>
20464     *
20465     * <p>After applying the remainder of the scroll delta the caller should invoke
20466     * {@link #dispatchNestedScroll(int, int, int, int, int[]) dispatchNestedScroll}, passing
20467     * both the delta consumed and the delta unconsumed. A nested scrolling parent may treat
20468     * these values differently. See {@link ViewParent#onNestedScroll(View, int, int, int, int)}.
20469     * </p>
20470     *
20471     * @param axes Flags consisting of a combination of {@link #SCROLL_AXIS_HORIZONTAL} and/or
20472     *             {@link #SCROLL_AXIS_VERTICAL}.
20473     * @return true if a cooperative parent was found and nested scrolling has been enabled for
20474     *         the current gesture.
20475     *
20476     * @see #stopNestedScroll()
20477     * @see #dispatchNestedPreScroll(int, int, int[], int[])
20478     * @see #dispatchNestedScroll(int, int, int, int, int[])
20479     */
20480    public boolean startNestedScroll(int axes) {
20481        if (hasNestedScrollingParent()) {
20482            // Already in progress
20483            return true;
20484        }
20485        if (isNestedScrollingEnabled()) {
20486            ViewParent p = getParent();
20487            View child = this;
20488            while (p != null) {
20489                try {
20490                    if (p.onStartNestedScroll(child, this, axes)) {
20491                        mNestedScrollingParent = p;
20492                        p.onNestedScrollAccepted(child, this, axes);
20493                        return true;
20494                    }
20495                } catch (AbstractMethodError e) {
20496                    Log.e(VIEW_LOG_TAG, "ViewParent " + p + " does not implement interface " +
20497                            "method onStartNestedScroll", e);
20498                    // Allow the search upward to continue
20499                }
20500                if (p instanceof View) {
20501                    child = (View) p;
20502                }
20503                p = p.getParent();
20504            }
20505        }
20506        return false;
20507    }
20508
20509    /**
20510     * Stop a nested scroll in progress.
20511     *
20512     * <p>Calling this method when a nested scroll is not currently in progress is harmless.</p>
20513     *
20514     * @see #startNestedScroll(int)
20515     */
20516    public void stopNestedScroll() {
20517        if (mNestedScrollingParent != null) {
20518            mNestedScrollingParent.onStopNestedScroll(this);
20519            mNestedScrollingParent = null;
20520        }
20521    }
20522
20523    /**
20524     * Returns true if this view has a nested scrolling parent.
20525     *
20526     * <p>The presence of a nested scrolling parent indicates that this view has initiated
20527     * a nested scroll and it was accepted by an ancestor view further up the view hierarchy.</p>
20528     *
20529     * @return whether this view has a nested scrolling parent
20530     */
20531    public boolean hasNestedScrollingParent() {
20532        return mNestedScrollingParent != null;
20533    }
20534
20535    /**
20536     * Dispatch one step of a nested scroll in progress.
20537     *
20538     * <p>Implementations of views that support nested scrolling should call this to report
20539     * info about a scroll in progress to the current nested scrolling parent. If a nested scroll
20540     * is not currently in progress or nested scrolling is not
20541     * {@link #isNestedScrollingEnabled() enabled} for this view this method does nothing.</p>
20542     *
20543     * <p>Compatible View implementations should also call
20544     * {@link #dispatchNestedPreScroll(int, int, int[], int[]) dispatchNestedPreScroll} before
20545     * consuming a component of the scroll event themselves.</p>
20546     *
20547     * @param dxConsumed Horizontal distance in pixels consumed by this view during this scroll step
20548     * @param dyConsumed Vertical distance in pixels consumed by this view during this scroll step
20549     * @param dxUnconsumed Horizontal scroll distance in pixels not consumed by this view
20550     * @param dyUnconsumed Horizontal scroll distance in pixels not consumed by this view
20551     * @param offsetInWindow Optional. If not null, on return this will contain the offset
20552     *                       in local view coordinates of this view from before this operation
20553     *                       to after it completes. View implementations may use this to adjust
20554     *                       expected input coordinate tracking.
20555     * @return true if the event was dispatched, false if it could not be dispatched.
20556     * @see #dispatchNestedPreScroll(int, int, int[], int[])
20557     */
20558    public boolean dispatchNestedScroll(int dxConsumed, int dyConsumed,
20559            int dxUnconsumed, int dyUnconsumed, @Nullable @Size(2) int[] offsetInWindow) {
20560        if (isNestedScrollingEnabled() && mNestedScrollingParent != null) {
20561            if (dxConsumed != 0 || dyConsumed != 0 || dxUnconsumed != 0 || dyUnconsumed != 0) {
20562                int startX = 0;
20563                int startY = 0;
20564                if (offsetInWindow != null) {
20565                    getLocationInWindow(offsetInWindow);
20566                    startX = offsetInWindow[0];
20567                    startY = offsetInWindow[1];
20568                }
20569
20570                mNestedScrollingParent.onNestedScroll(this, dxConsumed, dyConsumed,
20571                        dxUnconsumed, dyUnconsumed);
20572
20573                if (offsetInWindow != null) {
20574                    getLocationInWindow(offsetInWindow);
20575                    offsetInWindow[0] -= startX;
20576                    offsetInWindow[1] -= startY;
20577                }
20578                return true;
20579            } else if (offsetInWindow != null) {
20580                // No motion, no dispatch. Keep offsetInWindow up to date.
20581                offsetInWindow[0] = 0;
20582                offsetInWindow[1] = 0;
20583            }
20584        }
20585        return false;
20586    }
20587
20588    /**
20589     * Dispatch one step of a nested scroll in progress before this view consumes any portion of it.
20590     *
20591     * <p>Nested pre-scroll events are to nested scroll events what touch intercept is to touch.
20592     * <code>dispatchNestedPreScroll</code> offers an opportunity for the parent view in a nested
20593     * scrolling operation to consume some or all of the scroll operation before the child view
20594     * consumes it.</p>
20595     *
20596     * @param dx Horizontal scroll distance in pixels
20597     * @param dy Vertical scroll distance in pixels
20598     * @param consumed Output. If not null, consumed[0] will contain the consumed component of dx
20599     *                 and consumed[1] the consumed dy.
20600     * @param offsetInWindow Optional. If not null, on return this will contain the offset
20601     *                       in local view coordinates of this view from before this operation
20602     *                       to after it completes. View implementations may use this to adjust
20603     *                       expected input coordinate tracking.
20604     * @return true if the parent consumed some or all of the scroll delta
20605     * @see #dispatchNestedScroll(int, int, int, int, int[])
20606     */
20607    public boolean dispatchNestedPreScroll(int dx, int dy,
20608            @Nullable @Size(2) int[] consumed, @Nullable @Size(2) int[] offsetInWindow) {
20609        if (isNestedScrollingEnabled() && mNestedScrollingParent != null) {
20610            if (dx != 0 || dy != 0) {
20611                int startX = 0;
20612                int startY = 0;
20613                if (offsetInWindow != null) {
20614                    getLocationInWindow(offsetInWindow);
20615                    startX = offsetInWindow[0];
20616                    startY = offsetInWindow[1];
20617                }
20618
20619                if (consumed == null) {
20620                    if (mTempNestedScrollConsumed == null) {
20621                        mTempNestedScrollConsumed = new int[2];
20622                    }
20623                    consumed = mTempNestedScrollConsumed;
20624                }
20625                consumed[0] = 0;
20626                consumed[1] = 0;
20627                mNestedScrollingParent.onNestedPreScroll(this, dx, dy, consumed);
20628
20629                if (offsetInWindow != null) {
20630                    getLocationInWindow(offsetInWindow);
20631                    offsetInWindow[0] -= startX;
20632                    offsetInWindow[1] -= startY;
20633                }
20634                return consumed[0] != 0 || consumed[1] != 0;
20635            } else if (offsetInWindow != null) {
20636                offsetInWindow[0] = 0;
20637                offsetInWindow[1] = 0;
20638            }
20639        }
20640        return false;
20641    }
20642
20643    /**
20644     * Dispatch a fling to a nested scrolling parent.
20645     *
20646     * <p>This method should be used to indicate that a nested scrolling child has detected
20647     * suitable conditions for a fling. Generally this means that a touch scroll has ended with a
20648     * {@link VelocityTracker velocity} in the direction of scrolling that meets or exceeds
20649     * the {@link ViewConfiguration#getScaledMinimumFlingVelocity() minimum fling velocity}
20650     * along a scrollable axis.</p>
20651     *
20652     * <p>If a nested scrolling child view would normally fling but it is at the edge of
20653     * its own content, it can use this method to delegate the fling to its nested scrolling
20654     * parent instead. The parent may optionally consume the fling or observe a child fling.</p>
20655     *
20656     * @param velocityX Horizontal fling velocity in pixels per second
20657     * @param velocityY Vertical fling velocity in pixels per second
20658     * @param consumed true if the child consumed the fling, false otherwise
20659     * @return true if the nested scrolling parent consumed or otherwise reacted to the fling
20660     */
20661    public boolean dispatchNestedFling(float velocityX, float velocityY, boolean consumed) {
20662        if (isNestedScrollingEnabled() && mNestedScrollingParent != null) {
20663            return mNestedScrollingParent.onNestedFling(this, velocityX, velocityY, consumed);
20664        }
20665        return false;
20666    }
20667
20668    /**
20669     * Dispatch a fling to a nested scrolling parent before it is processed by this view.
20670     *
20671     * <p>Nested pre-fling events are to nested fling events what touch intercept is to touch
20672     * and what nested pre-scroll is to nested scroll. <code>dispatchNestedPreFling</code>
20673     * offsets an opportunity for the parent view in a nested fling to fully consume the fling
20674     * before the child view consumes it. If this method returns <code>true</code>, a nested
20675     * parent view consumed the fling and this view should not scroll as a result.</p>
20676     *
20677     * <p>For a better user experience, only one view in a nested scrolling chain should consume
20678     * the fling at a time. If a parent view consumed the fling this method will return false.
20679     * Custom view implementations should account for this in two ways:</p>
20680     *
20681     * <ul>
20682     *     <li>If a custom view is paged and needs to settle to a fixed page-point, do not
20683     *     call <code>dispatchNestedPreFling</code>; consume the fling and settle to a valid
20684     *     position regardless.</li>
20685     *     <li>If a nested parent does consume the fling, this view should not scroll at all,
20686     *     even to settle back to a valid idle position.</li>
20687     * </ul>
20688     *
20689     * <p>Views should also not offer fling velocities to nested parent views along an axis
20690     * where scrolling is not currently supported; a {@link android.widget.ScrollView ScrollView}
20691     * should not offer a horizontal fling velocity to its parents since scrolling along that
20692     * axis is not permitted and carrying velocity along that motion does not make sense.</p>
20693     *
20694     * @param velocityX Horizontal fling velocity in pixels per second
20695     * @param velocityY Vertical fling velocity in pixels per second
20696     * @return true if a nested scrolling parent consumed the fling
20697     */
20698    public boolean dispatchNestedPreFling(float velocityX, float velocityY) {
20699        if (isNestedScrollingEnabled() && mNestedScrollingParent != null) {
20700            return mNestedScrollingParent.onNestedPreFling(this, velocityX, velocityY);
20701        }
20702        return false;
20703    }
20704
20705    /**
20706     * Gets a scale factor that determines the distance the view should scroll
20707     * vertically in response to {@link MotionEvent#ACTION_SCROLL}.
20708     * @return The vertical scroll scale factor.
20709     * @hide
20710     */
20711    protected float getVerticalScrollFactor() {
20712        if (mVerticalScrollFactor == 0) {
20713            TypedValue outValue = new TypedValue();
20714            if (!mContext.getTheme().resolveAttribute(
20715                    com.android.internal.R.attr.listPreferredItemHeight, outValue, true)) {
20716                throw new IllegalStateException(
20717                        "Expected theme to define listPreferredItemHeight.");
20718            }
20719            mVerticalScrollFactor = outValue.getDimension(
20720                    mContext.getResources().getDisplayMetrics());
20721        }
20722        return mVerticalScrollFactor;
20723    }
20724
20725    /**
20726     * Gets a scale factor that determines the distance the view should scroll
20727     * horizontally in response to {@link MotionEvent#ACTION_SCROLL}.
20728     * @return The horizontal scroll scale factor.
20729     * @hide
20730     */
20731    protected float getHorizontalScrollFactor() {
20732        // TODO: Should use something else.
20733        return getVerticalScrollFactor();
20734    }
20735
20736    /**
20737     * Return the value specifying the text direction or policy that was set with
20738     * {@link #setTextDirection(int)}.
20739     *
20740     * @return the defined text direction. It can be one of:
20741     *
20742     * {@link #TEXT_DIRECTION_INHERIT},
20743     * {@link #TEXT_DIRECTION_FIRST_STRONG},
20744     * {@link #TEXT_DIRECTION_ANY_RTL},
20745     * {@link #TEXT_DIRECTION_LTR},
20746     * {@link #TEXT_DIRECTION_RTL},
20747     * {@link #TEXT_DIRECTION_LOCALE},
20748     * {@link #TEXT_DIRECTION_FIRST_STRONG_LTR},
20749     * {@link #TEXT_DIRECTION_FIRST_STRONG_RTL}
20750     *
20751     * @attr ref android.R.styleable#View_textDirection
20752     *
20753     * @hide
20754     */
20755    @ViewDebug.ExportedProperty(category = "text", mapping = {
20756            @ViewDebug.IntToString(from = TEXT_DIRECTION_INHERIT, to = "INHERIT"),
20757            @ViewDebug.IntToString(from = TEXT_DIRECTION_FIRST_STRONG, to = "FIRST_STRONG"),
20758            @ViewDebug.IntToString(from = TEXT_DIRECTION_ANY_RTL, to = "ANY_RTL"),
20759            @ViewDebug.IntToString(from = TEXT_DIRECTION_LTR, to = "LTR"),
20760            @ViewDebug.IntToString(from = TEXT_DIRECTION_RTL, to = "RTL"),
20761            @ViewDebug.IntToString(from = TEXT_DIRECTION_LOCALE, to = "LOCALE"),
20762            @ViewDebug.IntToString(from = TEXT_DIRECTION_FIRST_STRONG_LTR, to = "FIRST_STRONG_LTR"),
20763            @ViewDebug.IntToString(from = TEXT_DIRECTION_FIRST_STRONG_RTL, to = "FIRST_STRONG_RTL")
20764    })
20765    public int getRawTextDirection() {
20766        return (mPrivateFlags2 & PFLAG2_TEXT_DIRECTION_MASK) >> PFLAG2_TEXT_DIRECTION_MASK_SHIFT;
20767    }
20768
20769    /**
20770     * Set the text direction.
20771     *
20772     * @param textDirection the direction to set. Should be one of:
20773     *
20774     * {@link #TEXT_DIRECTION_INHERIT},
20775     * {@link #TEXT_DIRECTION_FIRST_STRONG},
20776     * {@link #TEXT_DIRECTION_ANY_RTL},
20777     * {@link #TEXT_DIRECTION_LTR},
20778     * {@link #TEXT_DIRECTION_RTL},
20779     * {@link #TEXT_DIRECTION_LOCALE}
20780     * {@link #TEXT_DIRECTION_FIRST_STRONG_LTR},
20781     * {@link #TEXT_DIRECTION_FIRST_STRONG_RTL},
20782     *
20783     * Resolution will be done if the value is set to TEXT_DIRECTION_INHERIT. The resolution
20784     * proceeds up the parent chain of the view to get the value. If there is no parent, then it will
20785     * return the default {@link #TEXT_DIRECTION_FIRST_STRONG}.
20786     *
20787     * @attr ref android.R.styleable#View_textDirection
20788     */
20789    public void setTextDirection(int textDirection) {
20790        if (getRawTextDirection() != textDirection) {
20791            // Reset the current text direction and the resolved one
20792            mPrivateFlags2 &= ~PFLAG2_TEXT_DIRECTION_MASK;
20793            resetResolvedTextDirection();
20794            // Set the new text direction
20795            mPrivateFlags2 |= ((textDirection << PFLAG2_TEXT_DIRECTION_MASK_SHIFT) & PFLAG2_TEXT_DIRECTION_MASK);
20796            // Do resolution
20797            resolveTextDirection();
20798            // Notify change
20799            onRtlPropertiesChanged(getLayoutDirection());
20800            // Refresh
20801            requestLayout();
20802            invalidate(true);
20803        }
20804    }
20805
20806    /**
20807     * Return the resolved text direction.
20808     *
20809     * @return the resolved text direction. Returns one of:
20810     *
20811     * {@link #TEXT_DIRECTION_FIRST_STRONG},
20812     * {@link #TEXT_DIRECTION_ANY_RTL},
20813     * {@link #TEXT_DIRECTION_LTR},
20814     * {@link #TEXT_DIRECTION_RTL},
20815     * {@link #TEXT_DIRECTION_LOCALE},
20816     * {@link #TEXT_DIRECTION_FIRST_STRONG_LTR},
20817     * {@link #TEXT_DIRECTION_FIRST_STRONG_RTL}
20818     *
20819     * @attr ref android.R.styleable#View_textDirection
20820     */
20821    @ViewDebug.ExportedProperty(category = "text", mapping = {
20822            @ViewDebug.IntToString(from = TEXT_DIRECTION_INHERIT, to = "INHERIT"),
20823            @ViewDebug.IntToString(from = TEXT_DIRECTION_FIRST_STRONG, to = "FIRST_STRONG"),
20824            @ViewDebug.IntToString(from = TEXT_DIRECTION_ANY_RTL, to = "ANY_RTL"),
20825            @ViewDebug.IntToString(from = TEXT_DIRECTION_LTR, to = "LTR"),
20826            @ViewDebug.IntToString(from = TEXT_DIRECTION_RTL, to = "RTL"),
20827            @ViewDebug.IntToString(from = TEXT_DIRECTION_LOCALE, to = "LOCALE"),
20828            @ViewDebug.IntToString(from = TEXT_DIRECTION_FIRST_STRONG_LTR, to = "FIRST_STRONG_LTR"),
20829            @ViewDebug.IntToString(from = TEXT_DIRECTION_FIRST_STRONG_RTL, to = "FIRST_STRONG_RTL")
20830    })
20831    public int getTextDirection() {
20832        return (mPrivateFlags2 & PFLAG2_TEXT_DIRECTION_RESOLVED_MASK) >> PFLAG2_TEXT_DIRECTION_RESOLVED_MASK_SHIFT;
20833    }
20834
20835    /**
20836     * Resolve the text direction.
20837     *
20838     * @return true if resolution has been done, false otherwise.
20839     *
20840     * @hide
20841     */
20842    public boolean resolveTextDirection() {
20843        // Reset any previous text direction resolution
20844        mPrivateFlags2 &= ~(PFLAG2_TEXT_DIRECTION_RESOLVED | PFLAG2_TEXT_DIRECTION_RESOLVED_MASK);
20845
20846        if (hasRtlSupport()) {
20847            // Set resolved text direction flag depending on text direction flag
20848            final int textDirection = getRawTextDirection();
20849            switch(textDirection) {
20850                case TEXT_DIRECTION_INHERIT:
20851                    if (!canResolveTextDirection()) {
20852                        // We cannot do the resolution if there is no parent, so use the default one
20853                        mPrivateFlags2 |= PFLAG2_TEXT_DIRECTION_RESOLVED_DEFAULT;
20854                        // Resolution will need to happen again later
20855                        return false;
20856                    }
20857
20858                    // Parent has not yet resolved, so we still return the default
20859                    try {
20860                        if (!mParent.isTextDirectionResolved()) {
20861                            mPrivateFlags2 |= PFLAG2_TEXT_DIRECTION_RESOLVED_DEFAULT;
20862                            // Resolution will need to happen again later
20863                            return false;
20864                        }
20865                    } catch (AbstractMethodError e) {
20866                        Log.e(VIEW_LOG_TAG, mParent.getClass().getSimpleName() +
20867                                " does not fully implement ViewParent", e);
20868                        mPrivateFlags2 |= PFLAG2_TEXT_DIRECTION_RESOLVED |
20869                                PFLAG2_TEXT_DIRECTION_RESOLVED_DEFAULT;
20870                        return true;
20871                    }
20872
20873                    // Set current resolved direction to the same value as the parent's one
20874                    int parentResolvedDirection;
20875                    try {
20876                        parentResolvedDirection = mParent.getTextDirection();
20877                    } catch (AbstractMethodError e) {
20878                        Log.e(VIEW_LOG_TAG, mParent.getClass().getSimpleName() +
20879                                " does not fully implement ViewParent", e);
20880                        parentResolvedDirection = TEXT_DIRECTION_LTR;
20881                    }
20882                    switch (parentResolvedDirection) {
20883                        case TEXT_DIRECTION_FIRST_STRONG:
20884                        case TEXT_DIRECTION_ANY_RTL:
20885                        case TEXT_DIRECTION_LTR:
20886                        case TEXT_DIRECTION_RTL:
20887                        case TEXT_DIRECTION_LOCALE:
20888                        case TEXT_DIRECTION_FIRST_STRONG_LTR:
20889                        case TEXT_DIRECTION_FIRST_STRONG_RTL:
20890                            mPrivateFlags2 |=
20891                                    (parentResolvedDirection << PFLAG2_TEXT_DIRECTION_RESOLVED_MASK_SHIFT);
20892                            break;
20893                        default:
20894                            // Default resolved direction is "first strong" heuristic
20895                            mPrivateFlags2 |= PFLAG2_TEXT_DIRECTION_RESOLVED_DEFAULT;
20896                    }
20897                    break;
20898                case TEXT_DIRECTION_FIRST_STRONG:
20899                case TEXT_DIRECTION_ANY_RTL:
20900                case TEXT_DIRECTION_LTR:
20901                case TEXT_DIRECTION_RTL:
20902                case TEXT_DIRECTION_LOCALE:
20903                case TEXT_DIRECTION_FIRST_STRONG_LTR:
20904                case TEXT_DIRECTION_FIRST_STRONG_RTL:
20905                    // Resolved direction is the same as text direction
20906                    mPrivateFlags2 |= (textDirection << PFLAG2_TEXT_DIRECTION_RESOLVED_MASK_SHIFT);
20907                    break;
20908                default:
20909                    // Default resolved direction is "first strong" heuristic
20910                    mPrivateFlags2 |= PFLAG2_TEXT_DIRECTION_RESOLVED_DEFAULT;
20911            }
20912        } else {
20913            // Default resolved direction is "first strong" heuristic
20914            mPrivateFlags2 |= PFLAG2_TEXT_DIRECTION_RESOLVED_DEFAULT;
20915        }
20916
20917        // Set to resolved
20918        mPrivateFlags2 |= PFLAG2_TEXT_DIRECTION_RESOLVED;
20919        return true;
20920    }
20921
20922    /**
20923     * Check if text direction resolution can be done.
20924     *
20925     * @return true if text direction resolution can be done otherwise return false.
20926     */
20927    public boolean canResolveTextDirection() {
20928        switch (getRawTextDirection()) {
20929            case TEXT_DIRECTION_INHERIT:
20930                if (mParent != null) {
20931                    try {
20932                        return mParent.canResolveTextDirection();
20933                    } catch (AbstractMethodError e) {
20934                        Log.e(VIEW_LOG_TAG, mParent.getClass().getSimpleName() +
20935                                " does not fully implement ViewParent", e);
20936                    }
20937                }
20938                return false;
20939
20940            default:
20941                return true;
20942        }
20943    }
20944
20945    /**
20946     * Reset resolved text direction. Text direction will be resolved during a call to
20947     * {@link #onMeasure(int, int)}.
20948     *
20949     * @hide
20950     */
20951    public void resetResolvedTextDirection() {
20952        // Reset any previous text direction resolution
20953        mPrivateFlags2 &= ~(PFLAG2_TEXT_DIRECTION_RESOLVED | PFLAG2_TEXT_DIRECTION_RESOLVED_MASK);
20954        // Set to default value
20955        mPrivateFlags2 |= PFLAG2_TEXT_DIRECTION_RESOLVED_DEFAULT;
20956    }
20957
20958    /**
20959     * @return true if text direction is inherited.
20960     *
20961     * @hide
20962     */
20963    public boolean isTextDirectionInherited() {
20964        return (getRawTextDirection() == TEXT_DIRECTION_INHERIT);
20965    }
20966
20967    /**
20968     * @return true if text direction is resolved.
20969     */
20970    public boolean isTextDirectionResolved() {
20971        return (mPrivateFlags2 & PFLAG2_TEXT_DIRECTION_RESOLVED) == PFLAG2_TEXT_DIRECTION_RESOLVED;
20972    }
20973
20974    /**
20975     * Return the value specifying the text alignment or policy that was set with
20976     * {@link #setTextAlignment(int)}.
20977     *
20978     * @return the defined text alignment. It can be one of:
20979     *
20980     * {@link #TEXT_ALIGNMENT_INHERIT},
20981     * {@link #TEXT_ALIGNMENT_GRAVITY},
20982     * {@link #TEXT_ALIGNMENT_CENTER},
20983     * {@link #TEXT_ALIGNMENT_TEXT_START},
20984     * {@link #TEXT_ALIGNMENT_TEXT_END},
20985     * {@link #TEXT_ALIGNMENT_VIEW_START},
20986     * {@link #TEXT_ALIGNMENT_VIEW_END}
20987     *
20988     * @attr ref android.R.styleable#View_textAlignment
20989     *
20990     * @hide
20991     */
20992    @ViewDebug.ExportedProperty(category = "text", mapping = {
20993            @ViewDebug.IntToString(from = TEXT_ALIGNMENT_INHERIT, to = "INHERIT"),
20994            @ViewDebug.IntToString(from = TEXT_ALIGNMENT_GRAVITY, to = "GRAVITY"),
20995            @ViewDebug.IntToString(from = TEXT_ALIGNMENT_TEXT_START, to = "TEXT_START"),
20996            @ViewDebug.IntToString(from = TEXT_ALIGNMENT_TEXT_END, to = "TEXT_END"),
20997            @ViewDebug.IntToString(from = TEXT_ALIGNMENT_CENTER, to = "CENTER"),
20998            @ViewDebug.IntToString(from = TEXT_ALIGNMENT_VIEW_START, to = "VIEW_START"),
20999            @ViewDebug.IntToString(from = TEXT_ALIGNMENT_VIEW_END, to = "VIEW_END")
21000    })
21001    @TextAlignment
21002    public int getRawTextAlignment() {
21003        return (mPrivateFlags2 & PFLAG2_TEXT_ALIGNMENT_MASK) >> PFLAG2_TEXT_ALIGNMENT_MASK_SHIFT;
21004    }
21005
21006    /**
21007     * Set the text alignment.
21008     *
21009     * @param textAlignment The text alignment to set. Should be one of
21010     *
21011     * {@link #TEXT_ALIGNMENT_INHERIT},
21012     * {@link #TEXT_ALIGNMENT_GRAVITY},
21013     * {@link #TEXT_ALIGNMENT_CENTER},
21014     * {@link #TEXT_ALIGNMENT_TEXT_START},
21015     * {@link #TEXT_ALIGNMENT_TEXT_END},
21016     * {@link #TEXT_ALIGNMENT_VIEW_START},
21017     * {@link #TEXT_ALIGNMENT_VIEW_END}
21018     *
21019     * Resolution will be done if the value is set to TEXT_ALIGNMENT_INHERIT. The resolution
21020     * proceeds up the parent chain of the view to get the value. If there is no parent, then it
21021     * will return the default {@link #TEXT_ALIGNMENT_GRAVITY}.
21022     *
21023     * @attr ref android.R.styleable#View_textAlignment
21024     */
21025    public void setTextAlignment(@TextAlignment int textAlignment) {
21026        if (textAlignment != getRawTextAlignment()) {
21027            // Reset the current and resolved text alignment
21028            mPrivateFlags2 &= ~PFLAG2_TEXT_ALIGNMENT_MASK;
21029            resetResolvedTextAlignment();
21030            // Set the new text alignment
21031            mPrivateFlags2 |=
21032                    ((textAlignment << PFLAG2_TEXT_ALIGNMENT_MASK_SHIFT) & PFLAG2_TEXT_ALIGNMENT_MASK);
21033            // Do resolution
21034            resolveTextAlignment();
21035            // Notify change
21036            onRtlPropertiesChanged(getLayoutDirection());
21037            // Refresh
21038            requestLayout();
21039            invalidate(true);
21040        }
21041    }
21042
21043    /**
21044     * Return the resolved text alignment.
21045     *
21046     * @return the resolved text alignment. Returns one of:
21047     *
21048     * {@link #TEXT_ALIGNMENT_GRAVITY},
21049     * {@link #TEXT_ALIGNMENT_CENTER},
21050     * {@link #TEXT_ALIGNMENT_TEXT_START},
21051     * {@link #TEXT_ALIGNMENT_TEXT_END},
21052     * {@link #TEXT_ALIGNMENT_VIEW_START},
21053     * {@link #TEXT_ALIGNMENT_VIEW_END}
21054     *
21055     * @attr ref android.R.styleable#View_textAlignment
21056     */
21057    @ViewDebug.ExportedProperty(category = "text", mapping = {
21058            @ViewDebug.IntToString(from = TEXT_ALIGNMENT_INHERIT, to = "INHERIT"),
21059            @ViewDebug.IntToString(from = TEXT_ALIGNMENT_GRAVITY, to = "GRAVITY"),
21060            @ViewDebug.IntToString(from = TEXT_ALIGNMENT_TEXT_START, to = "TEXT_START"),
21061            @ViewDebug.IntToString(from = TEXT_ALIGNMENT_TEXT_END, to = "TEXT_END"),
21062            @ViewDebug.IntToString(from = TEXT_ALIGNMENT_CENTER, to = "CENTER"),
21063            @ViewDebug.IntToString(from = TEXT_ALIGNMENT_VIEW_START, to = "VIEW_START"),
21064            @ViewDebug.IntToString(from = TEXT_ALIGNMENT_VIEW_END, to = "VIEW_END")
21065    })
21066    @TextAlignment
21067    public int getTextAlignment() {
21068        return (mPrivateFlags2 & PFLAG2_TEXT_ALIGNMENT_RESOLVED_MASK) >>
21069                PFLAG2_TEXT_ALIGNMENT_RESOLVED_MASK_SHIFT;
21070    }
21071
21072    /**
21073     * Resolve the text alignment.
21074     *
21075     * @return true if resolution has been done, false otherwise.
21076     *
21077     * @hide
21078     */
21079    public boolean resolveTextAlignment() {
21080        // Reset any previous text alignment resolution
21081        mPrivateFlags2 &= ~(PFLAG2_TEXT_ALIGNMENT_RESOLVED | PFLAG2_TEXT_ALIGNMENT_RESOLVED_MASK);
21082
21083        if (hasRtlSupport()) {
21084            // Set resolved text alignment flag depending on text alignment flag
21085            final int textAlignment = getRawTextAlignment();
21086            switch (textAlignment) {
21087                case TEXT_ALIGNMENT_INHERIT:
21088                    // Check if we can resolve the text alignment
21089                    if (!canResolveTextAlignment()) {
21090                        // We cannot do the resolution if there is no parent so use the default
21091                        mPrivateFlags2 |= PFLAG2_TEXT_ALIGNMENT_RESOLVED_DEFAULT;
21092                        // Resolution will need to happen again later
21093                        return false;
21094                    }
21095
21096                    // Parent has not yet resolved, so we still return the default
21097                    try {
21098                        if (!mParent.isTextAlignmentResolved()) {
21099                            mPrivateFlags2 |= PFLAG2_TEXT_ALIGNMENT_RESOLVED_DEFAULT;
21100                            // Resolution will need to happen again later
21101                            return false;
21102                        }
21103                    } catch (AbstractMethodError e) {
21104                        Log.e(VIEW_LOG_TAG, mParent.getClass().getSimpleName() +
21105                                " does not fully implement ViewParent", e);
21106                        mPrivateFlags2 |= PFLAG2_TEXT_ALIGNMENT_RESOLVED |
21107                                PFLAG2_TEXT_ALIGNMENT_RESOLVED_DEFAULT;
21108                        return true;
21109                    }
21110
21111                    int parentResolvedTextAlignment;
21112                    try {
21113                        parentResolvedTextAlignment = mParent.getTextAlignment();
21114                    } catch (AbstractMethodError e) {
21115                        Log.e(VIEW_LOG_TAG, mParent.getClass().getSimpleName() +
21116                                " does not fully implement ViewParent", e);
21117                        parentResolvedTextAlignment = TEXT_ALIGNMENT_GRAVITY;
21118                    }
21119                    switch (parentResolvedTextAlignment) {
21120                        case TEXT_ALIGNMENT_GRAVITY:
21121                        case TEXT_ALIGNMENT_TEXT_START:
21122                        case TEXT_ALIGNMENT_TEXT_END:
21123                        case TEXT_ALIGNMENT_CENTER:
21124                        case TEXT_ALIGNMENT_VIEW_START:
21125                        case TEXT_ALIGNMENT_VIEW_END:
21126                            // Resolved text alignment is the same as the parent resolved
21127                            // text alignment
21128                            mPrivateFlags2 |=
21129                                    (parentResolvedTextAlignment << PFLAG2_TEXT_ALIGNMENT_RESOLVED_MASK_SHIFT);
21130                            break;
21131                        default:
21132                            // Use default resolved text alignment
21133                            mPrivateFlags2 |= PFLAG2_TEXT_ALIGNMENT_RESOLVED_DEFAULT;
21134                    }
21135                    break;
21136                case TEXT_ALIGNMENT_GRAVITY:
21137                case TEXT_ALIGNMENT_TEXT_START:
21138                case TEXT_ALIGNMENT_TEXT_END:
21139                case TEXT_ALIGNMENT_CENTER:
21140                case TEXT_ALIGNMENT_VIEW_START:
21141                case TEXT_ALIGNMENT_VIEW_END:
21142                    // Resolved text alignment is the same as text alignment
21143                    mPrivateFlags2 |= (textAlignment << PFLAG2_TEXT_ALIGNMENT_RESOLVED_MASK_SHIFT);
21144                    break;
21145                default:
21146                    // Use default resolved text alignment
21147                    mPrivateFlags2 |= PFLAG2_TEXT_ALIGNMENT_RESOLVED_DEFAULT;
21148            }
21149        } else {
21150            // Use default resolved text alignment
21151            mPrivateFlags2 |= PFLAG2_TEXT_ALIGNMENT_RESOLVED_DEFAULT;
21152        }
21153
21154        // Set the resolved
21155        mPrivateFlags2 |= PFLAG2_TEXT_ALIGNMENT_RESOLVED;
21156        return true;
21157    }
21158
21159    /**
21160     * Check if text alignment resolution can be done.
21161     *
21162     * @return true if text alignment resolution can be done otherwise return false.
21163     */
21164    public boolean canResolveTextAlignment() {
21165        switch (getRawTextAlignment()) {
21166            case TEXT_DIRECTION_INHERIT:
21167                if (mParent != null) {
21168                    try {
21169                        return mParent.canResolveTextAlignment();
21170                    } catch (AbstractMethodError e) {
21171                        Log.e(VIEW_LOG_TAG, mParent.getClass().getSimpleName() +
21172                                " does not fully implement ViewParent", e);
21173                    }
21174                }
21175                return false;
21176
21177            default:
21178                return true;
21179        }
21180    }
21181
21182    /**
21183     * Reset resolved text alignment. Text alignment will be resolved during a call to
21184     * {@link #onMeasure(int, int)}.
21185     *
21186     * @hide
21187     */
21188    public void resetResolvedTextAlignment() {
21189        // Reset any previous text alignment resolution
21190        mPrivateFlags2 &= ~(PFLAG2_TEXT_ALIGNMENT_RESOLVED | PFLAG2_TEXT_ALIGNMENT_RESOLVED_MASK);
21191        // Set to default
21192        mPrivateFlags2 |= PFLAG2_TEXT_ALIGNMENT_RESOLVED_DEFAULT;
21193    }
21194
21195    /**
21196     * @return true if text alignment is inherited.
21197     *
21198     * @hide
21199     */
21200    public boolean isTextAlignmentInherited() {
21201        return (getRawTextAlignment() == TEXT_ALIGNMENT_INHERIT);
21202    }
21203
21204    /**
21205     * @return true if text alignment is resolved.
21206     */
21207    public boolean isTextAlignmentResolved() {
21208        return (mPrivateFlags2 & PFLAG2_TEXT_ALIGNMENT_RESOLVED) == PFLAG2_TEXT_ALIGNMENT_RESOLVED;
21209    }
21210
21211    /**
21212     * Generate a value suitable for use in {@link #setId(int)}.
21213     * This value will not collide with ID values generated at build time by aapt for R.id.
21214     *
21215     * @return a generated ID value
21216     */
21217    public static int generateViewId() {
21218        for (;;) {
21219            final int result = sNextGeneratedId.get();
21220            // aapt-generated IDs have the high byte nonzero; clamp to the range under that.
21221            int newValue = result + 1;
21222            if (newValue > 0x00FFFFFF) newValue = 1; // Roll over to 1, not 0.
21223            if (sNextGeneratedId.compareAndSet(result, newValue)) {
21224                return result;
21225            }
21226        }
21227    }
21228
21229    /**
21230     * Gets the Views in the hierarchy affected by entering and exiting Activity Scene transitions.
21231     * @param transitioningViews This View will be added to transitioningViews if it is VISIBLE and
21232     *                           a normal View or a ViewGroup with
21233     *                           {@link android.view.ViewGroup#isTransitionGroup()} true.
21234     * @hide
21235     */
21236    public void captureTransitioningViews(List<View> transitioningViews) {
21237        if (getVisibility() == View.VISIBLE) {
21238            transitioningViews.add(this);
21239        }
21240    }
21241
21242    /**
21243     * Adds all Views that have {@link #getTransitionName()} non-null to namedElements.
21244     * @param namedElements Will contain all Views in the hierarchy having a transitionName.
21245     * @hide
21246     */
21247    public void findNamedViews(Map<String, View> namedElements) {
21248        if (getVisibility() == VISIBLE || mGhostView != null) {
21249            String transitionName = getTransitionName();
21250            if (transitionName != null) {
21251                namedElements.put(transitionName, this);
21252            }
21253        }
21254    }
21255
21256    /** @hide */
21257    public int getPointerShape(MotionEvent event, float x, float y) {
21258        final int value = (mPrivateFlags3 & PFLAG3_POINTER_ICON_MASK);
21259        switch (value) {
21260            case PFLAG3_POINTER_ICON_NOT_SPECIFIED:
21261                return PointerIcon.STYLE_NOT_SPECIFIED;
21262            case PFLAG3_POINTER_ICON_NULL:
21263                return PointerIcon.STYLE_NULL;
21264            case PFLAG3_POINTER_ICON_CUSTOM:
21265                return PointerIcon.STYLE_CUSTOM;
21266            default:
21267                return ((value - PFLAG3_POINTER_ICON_VALUE_START) >> PFLAG3_POINTER_ICON_LSHIFT)
21268                        + PointerIcon.STYLE_ARROW;
21269        }
21270    }
21271
21272    /** @hide */
21273    public void setPointerShape(int pointerShape) {
21274        int newValue;
21275        if (pointerShape == PointerIcon.STYLE_NOT_SPECIFIED) {
21276            newValue = PFLAG3_POINTER_ICON_NOT_SPECIFIED;
21277        } else if (pointerShape == PointerIcon.STYLE_NULL) {
21278            newValue = PFLAG3_POINTER_ICON_NULL;
21279        } else if (pointerShape == PointerIcon.STYLE_CUSTOM) {
21280            newValue = PFLAG3_POINTER_ICON_CUSTOM;
21281        } else if (pointerShape >= PointerIcon.STYLE_ARROW
21282                && pointerShape <= PointerIcon.STYLE_GRABBING) {
21283            newValue = ((pointerShape - PointerIcon.STYLE_ARROW) << PFLAG3_POINTER_ICON_LSHIFT)
21284                    + PFLAG3_POINTER_ICON_VALUE_START;
21285        } else {
21286            Log.w(VIEW_LOG_TAG, "Invalid pointer shape " + pointerShape + " is specified.");
21287            return;
21288        }
21289        if (newValue != (mPrivateFlags3 & PFLAG3_POINTER_ICON_MASK)) {
21290            mPrivateFlags3 = (mPrivateFlags3 & ~PFLAG3_POINTER_ICON_MASK) | newValue;
21291        }
21292    }
21293
21294    //
21295    // Properties
21296    //
21297    /**
21298     * A Property wrapper around the <code>alpha</code> functionality handled by the
21299     * {@link View#setAlpha(float)} and {@link View#getAlpha()} methods.
21300     */
21301    public static final Property<View, Float> ALPHA = new FloatProperty<View>("alpha") {
21302        @Override
21303        public void setValue(View object, float value) {
21304            object.setAlpha(value);
21305        }
21306
21307        @Override
21308        public Float get(View object) {
21309            return object.getAlpha();
21310        }
21311    };
21312
21313    /**
21314     * A Property wrapper around the <code>translationX</code> functionality handled by the
21315     * {@link View#setTranslationX(float)} and {@link View#getTranslationX()} methods.
21316     */
21317    public static final Property<View, Float> TRANSLATION_X = new FloatProperty<View>("translationX") {
21318        @Override
21319        public void setValue(View object, float value) {
21320            object.setTranslationX(value);
21321        }
21322
21323                @Override
21324        public Float get(View object) {
21325            return object.getTranslationX();
21326        }
21327    };
21328
21329    /**
21330     * A Property wrapper around the <code>translationY</code> functionality handled by the
21331     * {@link View#setTranslationY(float)} and {@link View#getTranslationY()} methods.
21332     */
21333    public static final Property<View, Float> TRANSLATION_Y = new FloatProperty<View>("translationY") {
21334        @Override
21335        public void setValue(View object, float value) {
21336            object.setTranslationY(value);
21337        }
21338
21339        @Override
21340        public Float get(View object) {
21341            return object.getTranslationY();
21342        }
21343    };
21344
21345    /**
21346     * A Property wrapper around the <code>translationZ</code> functionality handled by the
21347     * {@link View#setTranslationZ(float)} and {@link View#getTranslationZ()} methods.
21348     */
21349    public static final Property<View, Float> TRANSLATION_Z = new FloatProperty<View>("translationZ") {
21350        @Override
21351        public void setValue(View object, float value) {
21352            object.setTranslationZ(value);
21353        }
21354
21355        @Override
21356        public Float get(View object) {
21357            return object.getTranslationZ();
21358        }
21359    };
21360
21361    /**
21362     * A Property wrapper around the <code>x</code> functionality handled by the
21363     * {@link View#setX(float)} and {@link View#getX()} methods.
21364     */
21365    public static final Property<View, Float> X = new FloatProperty<View>("x") {
21366        @Override
21367        public void setValue(View object, float value) {
21368            object.setX(value);
21369        }
21370
21371        @Override
21372        public Float get(View object) {
21373            return object.getX();
21374        }
21375    };
21376
21377    /**
21378     * A Property wrapper around the <code>y</code> functionality handled by the
21379     * {@link View#setY(float)} and {@link View#getY()} methods.
21380     */
21381    public static final Property<View, Float> Y = new FloatProperty<View>("y") {
21382        @Override
21383        public void setValue(View object, float value) {
21384            object.setY(value);
21385        }
21386
21387        @Override
21388        public Float get(View object) {
21389            return object.getY();
21390        }
21391    };
21392
21393    /**
21394     * A Property wrapper around the <code>z</code> functionality handled by the
21395     * {@link View#setZ(float)} and {@link View#getZ()} methods.
21396     */
21397    public static final Property<View, Float> Z = new FloatProperty<View>("z") {
21398        @Override
21399        public void setValue(View object, float value) {
21400            object.setZ(value);
21401        }
21402
21403        @Override
21404        public Float get(View object) {
21405            return object.getZ();
21406        }
21407    };
21408
21409    /**
21410     * A Property wrapper around the <code>rotation</code> functionality handled by the
21411     * {@link View#setRotation(float)} and {@link View#getRotation()} methods.
21412     */
21413    public static final Property<View, Float> ROTATION = new FloatProperty<View>("rotation") {
21414        @Override
21415        public void setValue(View object, float value) {
21416            object.setRotation(value);
21417        }
21418
21419        @Override
21420        public Float get(View object) {
21421            return object.getRotation();
21422        }
21423    };
21424
21425    /**
21426     * A Property wrapper around the <code>rotationX</code> functionality handled by the
21427     * {@link View#setRotationX(float)} and {@link View#getRotationX()} methods.
21428     */
21429    public static final Property<View, Float> ROTATION_X = new FloatProperty<View>("rotationX") {
21430        @Override
21431        public void setValue(View object, float value) {
21432            object.setRotationX(value);
21433        }
21434
21435        @Override
21436        public Float get(View object) {
21437            return object.getRotationX();
21438        }
21439    };
21440
21441    /**
21442     * A Property wrapper around the <code>rotationY</code> functionality handled by the
21443     * {@link View#setRotationY(float)} and {@link View#getRotationY()} methods.
21444     */
21445    public static final Property<View, Float> ROTATION_Y = new FloatProperty<View>("rotationY") {
21446        @Override
21447        public void setValue(View object, float value) {
21448            object.setRotationY(value);
21449        }
21450
21451        @Override
21452        public Float get(View object) {
21453            return object.getRotationY();
21454        }
21455    };
21456
21457    /**
21458     * A Property wrapper around the <code>scaleX</code> functionality handled by the
21459     * {@link View#setScaleX(float)} and {@link View#getScaleX()} methods.
21460     */
21461    public static final Property<View, Float> SCALE_X = new FloatProperty<View>("scaleX") {
21462        @Override
21463        public void setValue(View object, float value) {
21464            object.setScaleX(value);
21465        }
21466
21467        @Override
21468        public Float get(View object) {
21469            return object.getScaleX();
21470        }
21471    };
21472
21473    /**
21474     * A Property wrapper around the <code>scaleY</code> functionality handled by the
21475     * {@link View#setScaleY(float)} and {@link View#getScaleY()} methods.
21476     */
21477    public static final Property<View, Float> SCALE_Y = new FloatProperty<View>("scaleY") {
21478        @Override
21479        public void setValue(View object, float value) {
21480            object.setScaleY(value);
21481        }
21482
21483        @Override
21484        public Float get(View object) {
21485            return object.getScaleY();
21486        }
21487    };
21488
21489    /**
21490     * A MeasureSpec encapsulates the layout requirements passed from parent to child.
21491     * Each MeasureSpec represents a requirement for either the width or the height.
21492     * A MeasureSpec is comprised of a size and a mode. There are three possible
21493     * modes:
21494     * <dl>
21495     * <dt>UNSPECIFIED</dt>
21496     * <dd>
21497     * The parent has not imposed any constraint on the child. It can be whatever size
21498     * it wants.
21499     * </dd>
21500     *
21501     * <dt>EXACTLY</dt>
21502     * <dd>
21503     * The parent has determined an exact size for the child. The child is going to be
21504     * given those bounds regardless of how big it wants to be.
21505     * </dd>
21506     *
21507     * <dt>AT_MOST</dt>
21508     * <dd>
21509     * The child can be as large as it wants up to the specified size.
21510     * </dd>
21511     * </dl>
21512     *
21513     * MeasureSpecs are implemented as ints to reduce object allocation. This class
21514     * is provided to pack and unpack the &lt;size, mode&gt; tuple into the int.
21515     */
21516    public static class MeasureSpec {
21517        private static final int MODE_SHIFT = 30;
21518        private static final int MODE_MASK  = 0x3 << MODE_SHIFT;
21519
21520        /**
21521         * Measure specification mode: The parent has not imposed any constraint
21522         * on the child. It can be whatever size it wants.
21523         */
21524        public static final int UNSPECIFIED = 0 << MODE_SHIFT;
21525
21526        /**
21527         * Measure specification mode: The parent has determined an exact size
21528         * for the child. The child is going to be given those bounds regardless
21529         * of how big it wants to be.
21530         */
21531        public static final int EXACTLY     = 1 << MODE_SHIFT;
21532
21533        /**
21534         * Measure specification mode: The child can be as large as it wants up
21535         * to the specified size.
21536         */
21537        public static final int AT_MOST     = 2 << MODE_SHIFT;
21538
21539        /**
21540         * Creates a measure specification based on the supplied size and mode.
21541         *
21542         * The mode must always be one of the following:
21543         * <ul>
21544         *  <li>{@link android.view.View.MeasureSpec#UNSPECIFIED}</li>
21545         *  <li>{@link android.view.View.MeasureSpec#EXACTLY}</li>
21546         *  <li>{@link android.view.View.MeasureSpec#AT_MOST}</li>
21547         * </ul>
21548         *
21549         * <p><strong>Note:</strong> On API level 17 and lower, makeMeasureSpec's
21550         * implementation was such that the order of arguments did not matter
21551         * and overflow in either value could impact the resulting MeasureSpec.
21552         * {@link android.widget.RelativeLayout} was affected by this bug.
21553         * Apps targeting API levels greater than 17 will get the fixed, more strict
21554         * behavior.</p>
21555         *
21556         * @param size the size of the measure specification
21557         * @param mode the mode of the measure specification
21558         * @return the measure specification based on size and mode
21559         */
21560        public static int makeMeasureSpec(int size, int mode) {
21561            if (sUseBrokenMakeMeasureSpec) {
21562                return size + mode;
21563            } else {
21564                return (size & ~MODE_MASK) | (mode & MODE_MASK);
21565            }
21566        }
21567
21568        /**
21569         * Like {@link #makeMeasureSpec(int, int)}, but any spec with a mode of UNSPECIFIED
21570         * will automatically get a size of 0. Older apps expect this.
21571         *
21572         * @hide internal use only for compatibility with system widgets and older apps
21573         */
21574        public static int makeSafeMeasureSpec(int size, int mode) {
21575            if (sUseZeroUnspecifiedMeasureSpec && mode == UNSPECIFIED) {
21576                return 0;
21577            }
21578            return makeMeasureSpec(size, mode);
21579        }
21580
21581        /**
21582         * Extracts the mode from the supplied measure specification.
21583         *
21584         * @param measureSpec the measure specification to extract the mode from
21585         * @return {@link android.view.View.MeasureSpec#UNSPECIFIED},
21586         *         {@link android.view.View.MeasureSpec#AT_MOST} or
21587         *         {@link android.view.View.MeasureSpec#EXACTLY}
21588         */
21589        public static int getMode(int measureSpec) {
21590            return (measureSpec & MODE_MASK);
21591        }
21592
21593        /**
21594         * Extracts the size from the supplied measure specification.
21595         *
21596         * @param measureSpec the measure specification to extract the size from
21597         * @return the size in pixels defined in the supplied measure specification
21598         */
21599        public static int getSize(int measureSpec) {
21600            return (measureSpec & ~MODE_MASK);
21601        }
21602
21603        static int adjust(int measureSpec, int delta) {
21604            final int mode = getMode(measureSpec);
21605            int size = getSize(measureSpec);
21606            if (mode == UNSPECIFIED) {
21607                // No need to adjust size for UNSPECIFIED mode.
21608                return makeMeasureSpec(size, UNSPECIFIED);
21609            }
21610            size += delta;
21611            if (size < 0) {
21612                Log.e(VIEW_LOG_TAG, "MeasureSpec.adjust: new size would be negative! (" + size +
21613                        ") spec: " + toString(measureSpec) + " delta: " + delta);
21614                size = 0;
21615            }
21616            return makeMeasureSpec(size, mode);
21617        }
21618
21619        /**
21620         * Returns a String representation of the specified measure
21621         * specification.
21622         *
21623         * @param measureSpec the measure specification to convert to a String
21624         * @return a String with the following format: "MeasureSpec: MODE SIZE"
21625         */
21626        public static String toString(int measureSpec) {
21627            int mode = getMode(measureSpec);
21628            int size = getSize(measureSpec);
21629
21630            StringBuilder sb = new StringBuilder("MeasureSpec: ");
21631
21632            if (mode == UNSPECIFIED)
21633                sb.append("UNSPECIFIED ");
21634            else if (mode == EXACTLY)
21635                sb.append("EXACTLY ");
21636            else if (mode == AT_MOST)
21637                sb.append("AT_MOST ");
21638            else
21639                sb.append(mode).append(" ");
21640
21641            sb.append(size);
21642            return sb.toString();
21643        }
21644    }
21645
21646    private final class CheckForLongPress implements Runnable {
21647        private int mOriginalWindowAttachCount;
21648        private float mX;
21649        private float mY;
21650
21651        @Override
21652        public void run() {
21653            if (isPressed() && (mParent != null)
21654                    && mOriginalWindowAttachCount == mWindowAttachCount) {
21655                if (performLongClick(mX, mY)) {
21656                    mHasPerformedLongPress = true;
21657                }
21658            }
21659        }
21660
21661        public void setAnchor(float x, float y) {
21662            mX = x;
21663            mY = y;
21664        }
21665
21666        public void rememberWindowAttachCount() {
21667            mOriginalWindowAttachCount = mWindowAttachCount;
21668        }
21669    }
21670
21671    private final class CheckForTap implements Runnable {
21672        public float x;
21673        public float y;
21674
21675        @Override
21676        public void run() {
21677            mPrivateFlags &= ~PFLAG_PREPRESSED;
21678            setPressed(true, x, y);
21679            checkForLongClick(ViewConfiguration.getTapTimeout(), x, y);
21680        }
21681    }
21682
21683    private final class PerformClick implements Runnable {
21684        @Override
21685        public void run() {
21686            performClick();
21687        }
21688    }
21689
21690    /**
21691     * This method returns a ViewPropertyAnimator object, which can be used to animate
21692     * specific properties on this View.
21693     *
21694     * @return ViewPropertyAnimator The ViewPropertyAnimator associated with this View.
21695     */
21696    public ViewPropertyAnimator animate() {
21697        if (mAnimator == null) {
21698            mAnimator = new ViewPropertyAnimator(this);
21699        }
21700        return mAnimator;
21701    }
21702
21703    /**
21704     * Sets the name of the View to be used to identify Views in Transitions.
21705     * Names should be unique in the View hierarchy.
21706     *
21707     * @param transitionName The name of the View to uniquely identify it for Transitions.
21708     */
21709    public final void setTransitionName(String transitionName) {
21710        mTransitionName = transitionName;
21711    }
21712
21713    /**
21714     * Returns the name of the View to be used to identify Views in Transitions.
21715     * Names should be unique in the View hierarchy.
21716     *
21717     * <p>This returns null if the View has not been given a name.</p>
21718     *
21719     * @return The name used of the View to be used to identify Views in Transitions or null
21720     * if no name has been given.
21721     */
21722    @ViewDebug.ExportedProperty
21723    public String getTransitionName() {
21724        return mTransitionName;
21725    }
21726
21727    /**
21728     * Interface definition for a callback to be invoked when a hardware key event is
21729     * dispatched to this view. The callback will be invoked before the key event is
21730     * given to the view. This is only useful for hardware keyboards; a software input
21731     * method has no obligation to trigger this listener.
21732     */
21733    public interface OnKeyListener {
21734        /**
21735         * Called when a hardware key is dispatched to a view. This allows listeners to
21736         * get a chance to respond before the target view.
21737         * <p>Key presses in software keyboards will generally NOT trigger this method,
21738         * although some may elect to do so in some situations. Do not assume a
21739         * software input method has to be key-based; even if it is, it may use key presses
21740         * in a different way than you expect, so there is no way to reliably catch soft
21741         * input key presses.
21742         *
21743         * @param v The view the key has been dispatched to.
21744         * @param keyCode The code for the physical key that was pressed
21745         * @param event The KeyEvent object containing full information about
21746         *        the event.
21747         * @return True if the listener has consumed the event, false otherwise.
21748         */
21749        boolean onKey(View v, int keyCode, KeyEvent event);
21750    }
21751
21752    /**
21753     * Interface definition for a callback to be invoked when a touch event is
21754     * dispatched to this view. The callback will be invoked before the touch
21755     * event is given to the view.
21756     */
21757    public interface OnTouchListener {
21758        /**
21759         * Called when a touch event is dispatched to a view. This allows listeners to
21760         * get a chance to respond before the target view.
21761         *
21762         * @param v The view the touch event has been dispatched to.
21763         * @param event The MotionEvent object containing full information about
21764         *        the event.
21765         * @return True if the listener has consumed the event, false otherwise.
21766         */
21767        boolean onTouch(View v, MotionEvent event);
21768    }
21769
21770    /**
21771     * Interface definition for a callback to be invoked when a hover event is
21772     * dispatched to this view. The callback will be invoked before the hover
21773     * event is given to the view.
21774     */
21775    public interface OnHoverListener {
21776        /**
21777         * Called when a hover event is dispatched to a view. This allows listeners to
21778         * get a chance to respond before the target view.
21779         *
21780         * @param v The view the hover event has been dispatched to.
21781         * @param event The MotionEvent object containing full information about
21782         *        the event.
21783         * @return True if the listener has consumed the event, false otherwise.
21784         */
21785        boolean onHover(View v, MotionEvent event);
21786    }
21787
21788    /**
21789     * Interface definition for a callback to be invoked when a generic motion event is
21790     * dispatched to this view. The callback will be invoked before the generic motion
21791     * event is given to the view.
21792     */
21793    public interface OnGenericMotionListener {
21794        /**
21795         * Called when a generic motion event is dispatched to a view. This allows listeners to
21796         * get a chance to respond before the target view.
21797         *
21798         * @param v The view the generic motion event has been dispatched to.
21799         * @param event The MotionEvent object containing full information about
21800         *        the event.
21801         * @return True if the listener has consumed the event, false otherwise.
21802         */
21803        boolean onGenericMotion(View v, MotionEvent event);
21804    }
21805
21806    /**
21807     * Interface definition for a callback to be invoked when a view has been clicked and held.
21808     */
21809    public interface OnLongClickListener {
21810        /**
21811         * Called when a view has been clicked and held.
21812         *
21813         * @param v The view that was clicked and held.
21814         *
21815         * @return true if the callback consumed the long click, false otherwise.
21816         */
21817        boolean onLongClick(View v);
21818    }
21819
21820    /**
21821     * Interface definition for a callback to be invoked when a drag is being dispatched
21822     * to this view.  The callback will be invoked before the hosting view's own
21823     * onDrag(event) method.  If the listener wants to fall back to the hosting view's
21824     * onDrag(event) behavior, it should return 'false' from this callback.
21825     *
21826     * <div class="special reference">
21827     * <h3>Developer Guides</h3>
21828     * <p>For a guide to implementing drag and drop features, read the
21829     * <a href="{@docRoot}guide/topics/ui/drag-drop.html">Drag and Drop</a> developer guide.</p>
21830     * </div>
21831     */
21832    public interface OnDragListener {
21833        /**
21834         * Called when a drag event is dispatched to a view. This allows listeners
21835         * to get a chance to override base View behavior.
21836         *
21837         * @param v The View that received the drag event.
21838         * @param event The {@link android.view.DragEvent} object for the drag event.
21839         * @return {@code true} if the drag event was handled successfully, or {@code false}
21840         * if the drag event was not handled. Note that {@code false} will trigger the View
21841         * to call its {@link #onDragEvent(DragEvent) onDragEvent()} handler.
21842         */
21843        boolean onDrag(View v, DragEvent event);
21844    }
21845
21846    /**
21847     * Interface definition for a callback to be invoked when the focus state of
21848     * a view changed.
21849     */
21850    public interface OnFocusChangeListener {
21851        /**
21852         * Called when the focus state of a view has changed.
21853         *
21854         * @param v The view whose state has changed.
21855         * @param hasFocus The new focus state of v.
21856         */
21857        void onFocusChange(View v, boolean hasFocus);
21858    }
21859
21860    /**
21861     * Interface definition for a callback to be invoked when a view is clicked.
21862     */
21863    public interface OnClickListener {
21864        /**
21865         * Called when a view has been clicked.
21866         *
21867         * @param v The view that was clicked.
21868         */
21869        void onClick(View v);
21870    }
21871
21872    /**
21873     * Interface definition for a callback to be invoked when a view is context clicked.
21874     */
21875    public interface OnContextClickListener {
21876        /**
21877         * Called when a view is context clicked.
21878         *
21879         * @param v The view that has been context clicked.
21880         * @return true if the callback consumed the context click, false otherwise.
21881         */
21882        boolean onContextClick(View v);
21883    }
21884
21885    /**
21886     * Interface definition for a callback to be invoked when the context menu
21887     * for this view is being built.
21888     */
21889    public interface OnCreateContextMenuListener {
21890        /**
21891         * Called when the context menu for this view is being built. It is not
21892         * safe to hold onto the menu after this method returns.
21893         *
21894         * @param menu The context menu that is being built
21895         * @param v The view for which the context menu is being built
21896         * @param menuInfo Extra information about the item for which the
21897         *            context menu should be shown. This information will vary
21898         *            depending on the class of v.
21899         */
21900        void onCreateContextMenu(ContextMenu menu, View v, ContextMenuInfo menuInfo);
21901    }
21902
21903    /**
21904     * Interface definition for a callback to be invoked when the status bar changes
21905     * visibility.  This reports <strong>global</strong> changes to the system UI
21906     * state, not what the application is requesting.
21907     *
21908     * @see View#setOnSystemUiVisibilityChangeListener(android.view.View.OnSystemUiVisibilityChangeListener)
21909     */
21910    public interface OnSystemUiVisibilityChangeListener {
21911        /**
21912         * Called when the status bar changes visibility because of a call to
21913         * {@link View#setSystemUiVisibility(int)}.
21914         *
21915         * @param visibility  Bitwise-or of flags {@link #SYSTEM_UI_FLAG_LOW_PROFILE},
21916         * {@link #SYSTEM_UI_FLAG_HIDE_NAVIGATION}, and {@link #SYSTEM_UI_FLAG_FULLSCREEN}.
21917         * This tells you the <strong>global</strong> state of these UI visibility
21918         * flags, not what your app is currently applying.
21919         */
21920        public void onSystemUiVisibilityChange(int visibility);
21921    }
21922
21923    /**
21924     * Interface definition for a callback to be invoked when this view is attached
21925     * or detached from its window.
21926     */
21927    public interface OnAttachStateChangeListener {
21928        /**
21929         * Called when the view is attached to a window.
21930         * @param v The view that was attached
21931         */
21932        public void onViewAttachedToWindow(View v);
21933        /**
21934         * Called when the view is detached from a window.
21935         * @param v The view that was detached
21936         */
21937        public void onViewDetachedFromWindow(View v);
21938    }
21939
21940    /**
21941     * Listener for applying window insets on a view in a custom way.
21942     *
21943     * <p>Apps may choose to implement this interface if they want to apply custom policy
21944     * to the way that window insets are treated for a view. If an OnApplyWindowInsetsListener
21945     * is set, its
21946     * {@link OnApplyWindowInsetsListener#onApplyWindowInsets(View, WindowInsets) onApplyWindowInsets}
21947     * method will be called instead of the View's own
21948     * {@link #onApplyWindowInsets(WindowInsets) onApplyWindowInsets} method. The listener
21949     * may optionally call the parameter View's <code>onApplyWindowInsets</code> method to apply
21950     * the View's normal behavior as part of its own.</p>
21951     */
21952    public interface OnApplyWindowInsetsListener {
21953        /**
21954         * When {@link View#setOnApplyWindowInsetsListener(View.OnApplyWindowInsetsListener) set}
21955         * on a View, this listener method will be called instead of the view's own
21956         * {@link View#onApplyWindowInsets(WindowInsets) onApplyWindowInsets} method.
21957         *
21958         * @param v The view applying window insets
21959         * @param insets The insets to apply
21960         * @return The insets supplied, minus any insets that were consumed
21961         */
21962        public WindowInsets onApplyWindowInsets(View v, WindowInsets insets);
21963    }
21964
21965    private final class UnsetPressedState implements Runnable {
21966        @Override
21967        public void run() {
21968            setPressed(false);
21969        }
21970    }
21971
21972    /**
21973     * Base class for derived classes that want to save and restore their own
21974     * state in {@link android.view.View#onSaveInstanceState()}.
21975     */
21976    public static class BaseSavedState extends AbsSavedState {
21977        String mStartActivityRequestWhoSaved;
21978
21979        /**
21980         * Constructor used when reading from a parcel. Reads the state of the superclass.
21981         *
21982         * @param source
21983         */
21984        public BaseSavedState(Parcel source) {
21985            super(source);
21986            mStartActivityRequestWhoSaved = source.readString();
21987        }
21988
21989        /**
21990         * Constructor called by derived classes when creating their SavedState objects
21991         *
21992         * @param superState The state of the superclass of this view
21993         */
21994        public BaseSavedState(Parcelable superState) {
21995            super(superState);
21996        }
21997
21998        @Override
21999        public void writeToParcel(Parcel out, int flags) {
22000            super.writeToParcel(out, flags);
22001            out.writeString(mStartActivityRequestWhoSaved);
22002        }
22003
22004        public static final Parcelable.Creator<BaseSavedState> CREATOR =
22005                new Parcelable.Creator<BaseSavedState>() {
22006            public BaseSavedState createFromParcel(Parcel in) {
22007                return new BaseSavedState(in);
22008            }
22009
22010            public BaseSavedState[] newArray(int size) {
22011                return new BaseSavedState[size];
22012            }
22013        };
22014    }
22015
22016    /**
22017     * A set of information given to a view when it is attached to its parent
22018     * window.
22019     */
22020    final static class AttachInfo {
22021        interface Callbacks {
22022            void playSoundEffect(int effectId);
22023            boolean performHapticFeedback(int effectId, boolean always);
22024            void schedulePartialLayout();
22025        }
22026
22027        /**
22028         * InvalidateInfo is used to post invalidate(int, int, int, int) messages
22029         * to a Handler. This class contains the target (View) to invalidate and
22030         * the coordinates of the dirty rectangle.
22031         *
22032         * For performance purposes, this class also implements a pool of up to
22033         * POOL_LIMIT objects that get reused. This reduces memory allocations
22034         * whenever possible.
22035         */
22036        static class InvalidateInfo {
22037            private static final int POOL_LIMIT = 10;
22038
22039            private static final SynchronizedPool<InvalidateInfo> sPool =
22040                    new SynchronizedPool<InvalidateInfo>(POOL_LIMIT);
22041
22042            View target;
22043
22044            int left;
22045            int top;
22046            int right;
22047            int bottom;
22048
22049            public static InvalidateInfo obtain() {
22050                InvalidateInfo instance = sPool.acquire();
22051                return (instance != null) ? instance : new InvalidateInfo();
22052            }
22053
22054            public void recycle() {
22055                target = null;
22056                sPool.release(this);
22057            }
22058        }
22059
22060        final IWindowSession mSession;
22061
22062        final IWindow mWindow;
22063
22064        final IBinder mWindowToken;
22065
22066        final Display mDisplay;
22067
22068        final Callbacks mRootCallbacks;
22069
22070        IWindowId mIWindowId;
22071        WindowId mWindowId;
22072
22073        /**
22074         * The top view of the hierarchy.
22075         */
22076        View mRootView;
22077
22078        IBinder mPanelParentWindowToken;
22079
22080        boolean mHardwareAccelerated;
22081        boolean mHardwareAccelerationRequested;
22082        ThreadedRenderer mHardwareRenderer;
22083        List<RenderNode> mPendingAnimatingRenderNodes;
22084
22085        /**
22086         * The state of the display to which the window is attached, as reported
22087         * by {@link Display#getState()}.  Note that the display state constants
22088         * declared by {@link Display} do not exactly line up with the screen state
22089         * constants declared by {@link View} (there are more display states than
22090         * screen states).
22091         */
22092        int mDisplayState = Display.STATE_UNKNOWN;
22093
22094        /**
22095         * Scale factor used by the compatibility mode
22096         */
22097        float mApplicationScale;
22098
22099        /**
22100         * Indicates whether the application is in compatibility mode
22101         */
22102        boolean mScalingRequired;
22103
22104        /**
22105         * Left position of this view's window
22106         */
22107        int mWindowLeft;
22108
22109        /**
22110         * Top position of this view's window
22111         */
22112        int mWindowTop;
22113
22114        /**
22115         * Indicates whether views need to use 32-bit drawing caches
22116         */
22117        boolean mUse32BitDrawingCache;
22118
22119        /**
22120         * For windows that are full-screen but using insets to layout inside
22121         * of the screen areas, these are the current insets to appear inside
22122         * the overscan area of the display.
22123         */
22124        final Rect mOverscanInsets = new Rect();
22125
22126        /**
22127         * For windows that are full-screen but using insets to layout inside
22128         * of the screen decorations, these are the current insets for the
22129         * content of the window.
22130         */
22131        final Rect mContentInsets = new Rect();
22132
22133        /**
22134         * For windows that are full-screen but using insets to layout inside
22135         * of the screen decorations, these are the current insets for the
22136         * actual visible parts of the window.
22137         */
22138        final Rect mVisibleInsets = new Rect();
22139
22140        /**
22141         * For windows that are full-screen but using insets to layout inside
22142         * of the screen decorations, these are the current insets for the
22143         * stable system windows.
22144         */
22145        final Rect mStableInsets = new Rect();
22146
22147        /**
22148         * For windows that include areas that are not covered by real surface these are the outsets
22149         * for real surface.
22150         */
22151        final Rect mOutsets = new Rect();
22152
22153        /**
22154         * The internal insets given by this window.  This value is
22155         * supplied by the client (through
22156         * {@link ViewTreeObserver.OnComputeInternalInsetsListener}) and will
22157         * be given to the window manager when changed to be used in laying
22158         * out windows behind it.
22159         */
22160        final ViewTreeObserver.InternalInsetsInfo mGivenInternalInsets
22161                = new ViewTreeObserver.InternalInsetsInfo();
22162
22163        /**
22164         * Set to true when mGivenInternalInsets is non-empty.
22165         */
22166        boolean mHasNonEmptyGivenInternalInsets;
22167
22168        /**
22169         * All views in the window's hierarchy that serve as scroll containers,
22170         * used to determine if the window can be resized or must be panned
22171         * to adjust for a soft input area.
22172         */
22173        final ArrayList<View> mScrollContainers = new ArrayList<View>();
22174
22175        final KeyEvent.DispatcherState mKeyDispatchState
22176                = new KeyEvent.DispatcherState();
22177
22178        /**
22179         * Indicates whether the view's window currently has the focus.
22180         */
22181        boolean mHasWindowFocus;
22182
22183        /**
22184         * The current visibility of the window.
22185         */
22186        int mWindowVisibility;
22187
22188        /**
22189         * Indicates the time at which drawing started to occur.
22190         */
22191        long mDrawingTime;
22192
22193        /**
22194         * Indicates whether or not ignoring the DIRTY_MASK flags.
22195         */
22196        boolean mIgnoreDirtyState;
22197
22198        /**
22199         * This flag tracks when the mIgnoreDirtyState flag is set during draw(),
22200         * to avoid clearing that flag prematurely.
22201         */
22202        boolean mSetIgnoreDirtyState = false;
22203
22204        /**
22205         * Indicates whether the view's window is currently in touch mode.
22206         */
22207        boolean mInTouchMode;
22208
22209        /**
22210         * Indicates whether the view has requested unbuffered input dispatching for the current
22211         * event stream.
22212         */
22213        boolean mUnbufferedDispatchRequested;
22214
22215        /**
22216         * Indicates that ViewAncestor should trigger a global layout change
22217         * the next time it performs a traversal
22218         */
22219        boolean mRecomputeGlobalAttributes;
22220
22221        /**
22222         * Always report new attributes at next traversal.
22223         */
22224        boolean mForceReportNewAttributes;
22225
22226        /**
22227         * Set during a traveral if any views want to keep the screen on.
22228         */
22229        boolean mKeepScreenOn;
22230
22231        /**
22232         * Bitwise-or of all of the values that views have passed to setSystemUiVisibility().
22233         */
22234        int mSystemUiVisibility;
22235
22236        /**
22237         * Hack to force certain system UI visibility flags to be cleared.
22238         */
22239        int mDisabledSystemUiVisibility;
22240
22241        /**
22242         * Last global system UI visibility reported by the window manager.
22243         */
22244        int mGlobalSystemUiVisibility;
22245
22246        /**
22247         * True if a view in this hierarchy has an OnSystemUiVisibilityChangeListener
22248         * attached.
22249         */
22250        boolean mHasSystemUiListeners;
22251
22252        /**
22253         * Set if the window has requested to extend into the overscan region
22254         * via WindowManager.LayoutParams.FLAG_LAYOUT_IN_OVERSCAN.
22255         */
22256        boolean mOverscanRequested;
22257
22258        /**
22259         * Set if the visibility of any views has changed.
22260         */
22261        boolean mViewVisibilityChanged;
22262
22263        /**
22264         * Set to true if a view has been scrolled.
22265         */
22266        boolean mViewScrollChanged;
22267
22268        /**
22269         * Set to true if high contrast mode enabled
22270         */
22271        boolean mHighContrastText;
22272
22273        /**
22274         * Global to the view hierarchy used as a temporary for dealing with
22275         * x/y points in the transparent region computations.
22276         */
22277        final int[] mTransparentLocation = new int[2];
22278
22279        /**
22280         * Global to the view hierarchy used as a temporary for dealing with
22281         * x/y points in the ViewGroup.invalidateChild implementation.
22282         */
22283        final int[] mInvalidateChildLocation = new int[2];
22284
22285        /**
22286         * Global to the view hierarchy used as a temporary for dealng with
22287         * computing absolute on-screen location.
22288         */
22289        final int[] mTmpLocation = new int[2];
22290
22291        /**
22292         * Global to the view hierarchy used as a temporary for dealing with
22293         * x/y location when view is transformed.
22294         */
22295        final float[] mTmpTransformLocation = new float[2];
22296
22297        /**
22298         * The view tree observer used to dispatch global events like
22299         * layout, pre-draw, touch mode change, etc.
22300         */
22301        final ViewTreeObserver mTreeObserver = new ViewTreeObserver();
22302
22303        /**
22304         * A Canvas used by the view hierarchy to perform bitmap caching.
22305         */
22306        Canvas mCanvas;
22307
22308        /**
22309         * The view root impl.
22310         */
22311        final ViewRootImpl mViewRootImpl;
22312
22313        /**
22314         * A Handler supplied by a view's {@link android.view.ViewRootImpl}. This
22315         * handler can be used to pump events in the UI events queue.
22316         */
22317        final Handler mHandler;
22318
22319        /**
22320         * Temporary for use in computing invalidate rectangles while
22321         * calling up the hierarchy.
22322         */
22323        final Rect mTmpInvalRect = new Rect();
22324
22325        /**
22326         * Temporary for use in computing hit areas with transformed views
22327         */
22328        final RectF mTmpTransformRect = new RectF();
22329
22330        /**
22331         * Temporary for use in computing hit areas with transformed views
22332         */
22333        final RectF mTmpTransformRect1 = new RectF();
22334
22335        /**
22336         * Temporary list of rectanges.
22337         */
22338        final List<RectF> mTmpRectList = new ArrayList<>();
22339
22340        /**
22341         * Temporary for use in transforming invalidation rect
22342         */
22343        final Matrix mTmpMatrix = new Matrix();
22344
22345        /**
22346         * Temporary for use in transforming invalidation rect
22347         */
22348        final Transformation mTmpTransformation = new Transformation();
22349
22350        /**
22351         * Temporary for use in querying outlines from OutlineProviders
22352         */
22353        final Outline mTmpOutline = new Outline();
22354
22355        /**
22356         * Temporary list for use in collecting focusable descendents of a view.
22357         */
22358        final ArrayList<View> mTempArrayList = new ArrayList<View>(24);
22359
22360        /**
22361         * The id of the window for accessibility purposes.
22362         */
22363        int mAccessibilityWindowId = AccessibilityNodeInfo.UNDEFINED_ITEM_ID;
22364
22365        /**
22366         * Flags related to accessibility processing.
22367         *
22368         * @see AccessibilityNodeInfo#FLAG_INCLUDE_NOT_IMPORTANT_VIEWS
22369         * @see AccessibilityNodeInfo#FLAG_REPORT_VIEW_IDS
22370         */
22371        int mAccessibilityFetchFlags;
22372
22373        /**
22374         * The drawable for highlighting accessibility focus.
22375         */
22376        Drawable mAccessibilityFocusDrawable;
22377
22378        /**
22379         * Show where the margins, bounds and layout bounds are for each view.
22380         */
22381        boolean mDebugLayout = SystemProperties.getBoolean(DEBUG_LAYOUT_PROPERTY, false);
22382
22383        /**
22384         * Point used to compute visible regions.
22385         */
22386        final Point mPoint = new Point();
22387
22388        /**
22389         * Used to track which View originated a requestLayout() call, used when
22390         * requestLayout() is called during layout.
22391         */
22392        View mViewRequestingLayout;
22393
22394        /**
22395         * Used to track views that need (at least) a partial relayout at their current size
22396         * during the next traversal.
22397         */
22398        List<View> mPartialLayoutViews = new ArrayList<>();
22399
22400        /**
22401         * Swapped with mPartialLayoutViews during layout to avoid concurrent
22402         * modification. Lazily assigned during ViewRootImpl layout.
22403         */
22404        List<View> mEmptyPartialLayoutViews;
22405
22406        /**
22407         * Used to track the identity of the current drag operation.
22408         */
22409        IBinder mDragToken;
22410
22411        /**
22412         * The drag shadow surface for the current drag operation.
22413         */
22414        public Surface mDragSurface;
22415
22416        /**
22417         * Creates a new set of attachment information with the specified
22418         * events handler and thread.
22419         *
22420         * @param handler the events handler the view must use
22421         */
22422        AttachInfo(IWindowSession session, IWindow window, Display display,
22423                ViewRootImpl viewRootImpl, Handler handler, Callbacks effectPlayer) {
22424            mSession = session;
22425            mWindow = window;
22426            mWindowToken = window.asBinder();
22427            mDisplay = display;
22428            mViewRootImpl = viewRootImpl;
22429            mHandler = handler;
22430            mRootCallbacks = effectPlayer;
22431        }
22432    }
22433
22434    /**
22435     * <p>ScrollabilityCache holds various fields used by a View when scrolling
22436     * is supported. This avoids keeping too many unused fields in most
22437     * instances of View.</p>
22438     */
22439    private static class ScrollabilityCache implements Runnable {
22440
22441        /**
22442         * Scrollbars are not visible
22443         */
22444        public static final int OFF = 0;
22445
22446        /**
22447         * Scrollbars are visible
22448         */
22449        public static final int ON = 1;
22450
22451        /**
22452         * Scrollbars are fading away
22453         */
22454        public static final int FADING = 2;
22455
22456        public boolean fadeScrollBars;
22457
22458        public int fadingEdgeLength;
22459        public int scrollBarDefaultDelayBeforeFade;
22460        public int scrollBarFadeDuration;
22461
22462        public int scrollBarSize;
22463        public ScrollBarDrawable scrollBar;
22464        public float[] interpolatorValues;
22465        public View host;
22466
22467        public final Paint paint;
22468        public final Matrix matrix;
22469        public Shader shader;
22470
22471        public final Interpolator scrollBarInterpolator = new Interpolator(1, 2);
22472
22473        private static final float[] OPAQUE = { 255 };
22474        private static final float[] TRANSPARENT = { 0.0f };
22475
22476        /**
22477         * When fading should start. This time moves into the future every time
22478         * a new scroll happens. Measured based on SystemClock.uptimeMillis()
22479         */
22480        public long fadeStartTime;
22481
22482
22483        /**
22484         * The current state of the scrollbars: ON, OFF, or FADING
22485         */
22486        public int state = OFF;
22487
22488        private int mLastColor;
22489
22490        public ScrollabilityCache(ViewConfiguration configuration, View host) {
22491            fadingEdgeLength = configuration.getScaledFadingEdgeLength();
22492            scrollBarSize = configuration.getScaledScrollBarSize();
22493            scrollBarDefaultDelayBeforeFade = ViewConfiguration.getScrollDefaultDelay();
22494            scrollBarFadeDuration = ViewConfiguration.getScrollBarFadeDuration();
22495
22496            paint = new Paint();
22497            matrix = new Matrix();
22498            // use use a height of 1, and then wack the matrix each time we
22499            // actually use it.
22500            shader = new LinearGradient(0, 0, 0, 1, 0xFF000000, 0, Shader.TileMode.CLAMP);
22501            paint.setShader(shader);
22502            paint.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.DST_OUT));
22503
22504            this.host = host;
22505        }
22506
22507        public void setFadeColor(int color) {
22508            if (color != mLastColor) {
22509                mLastColor = color;
22510
22511                if (color != 0) {
22512                    shader = new LinearGradient(0, 0, 0, 1, color | 0xFF000000,
22513                            color & 0x00FFFFFF, Shader.TileMode.CLAMP);
22514                    paint.setShader(shader);
22515                    // Restore the default transfer mode (src_over)
22516                    paint.setXfermode(null);
22517                } else {
22518                    shader = new LinearGradient(0, 0, 0, 1, 0xFF000000, 0, Shader.TileMode.CLAMP);
22519                    paint.setShader(shader);
22520                    paint.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.DST_OUT));
22521                }
22522            }
22523        }
22524
22525        public void run() {
22526            long now = AnimationUtils.currentAnimationTimeMillis();
22527            if (now >= fadeStartTime) {
22528
22529                // the animation fades the scrollbars out by changing
22530                // the opacity (alpha) from fully opaque to fully
22531                // transparent
22532                int nextFrame = (int) now;
22533                int framesCount = 0;
22534
22535                Interpolator interpolator = scrollBarInterpolator;
22536
22537                // Start opaque
22538                interpolator.setKeyFrame(framesCount++, nextFrame, OPAQUE);
22539
22540                // End transparent
22541                nextFrame += scrollBarFadeDuration;
22542                interpolator.setKeyFrame(framesCount, nextFrame, TRANSPARENT);
22543
22544                state = FADING;
22545
22546                // Kick off the fade animation
22547                host.invalidate(true);
22548            }
22549        }
22550    }
22551
22552    /**
22553     * Resuable callback for sending
22554     * {@link AccessibilityEvent#TYPE_VIEW_SCROLLED} accessibility event.
22555     */
22556    private class SendViewScrolledAccessibilityEvent implements Runnable {
22557        public volatile boolean mIsPending;
22558
22559        public void run() {
22560            sendAccessibilityEvent(AccessibilityEvent.TYPE_VIEW_SCROLLED);
22561            mIsPending = false;
22562        }
22563    }
22564
22565    /**
22566     * <p>
22567     * This class represents a delegate that can be registered in a {@link View}
22568     * to enhance accessibility support via composition rather via inheritance.
22569     * It is specifically targeted to widget developers that extend basic View
22570     * classes i.e. classes in package android.view, that would like their
22571     * applications to be backwards compatible.
22572     * </p>
22573     * <div class="special reference">
22574     * <h3>Developer Guides</h3>
22575     * <p>For more information about making applications accessible, read the
22576     * <a href="{@docRoot}guide/topics/ui/accessibility/index.html">Accessibility</a>
22577     * developer guide.</p>
22578     * </div>
22579     * <p>
22580     * A scenario in which a developer would like to use an accessibility delegate
22581     * is overriding a method introduced in a later API version then the minimal API
22582     * version supported by the application. For example, the method
22583     * {@link View#onInitializeAccessibilityNodeInfo(AccessibilityNodeInfo)} is not available
22584     * in API version 4 when the accessibility APIs were first introduced. If a
22585     * developer would like his application to run on API version 4 devices (assuming
22586     * all other APIs used by the application are version 4 or lower) and take advantage
22587     * of this method, instead of overriding the method which would break the application's
22588     * backwards compatibility, he can override the corresponding method in this
22589     * delegate and register the delegate in the target View if the API version of
22590     * the system is high enough i.e. the API version is same or higher to the API
22591     * version that introduced
22592     * {@link View#onInitializeAccessibilityNodeInfo(AccessibilityNodeInfo)}.
22593     * </p>
22594     * <p>
22595     * Here is an example implementation:
22596     * </p>
22597     * <code><pre><p>
22598     * if (Build.VERSION.SDK_INT >= 14) {
22599     *     // If the API version is equal of higher than the version in
22600     *     // which onInitializeAccessibilityNodeInfo was introduced we
22601     *     // register a delegate with a customized implementation.
22602     *     View view = findViewById(R.id.view_id);
22603     *     view.setAccessibilityDelegate(new AccessibilityDelegate() {
22604     *         public void onInitializeAccessibilityNodeInfo(View host,
22605     *                 AccessibilityNodeInfo info) {
22606     *             // Let the default implementation populate the info.
22607     *             super.onInitializeAccessibilityNodeInfo(host, info);
22608     *             // Set some other information.
22609     *             info.setEnabled(host.isEnabled());
22610     *         }
22611     *     });
22612     * }
22613     * </code></pre></p>
22614     * <p>
22615     * This delegate contains methods that correspond to the accessibility methods
22616     * in View. If a delegate has been specified the implementation in View hands
22617     * off handling to the corresponding method in this delegate. The default
22618     * implementation the delegate methods behaves exactly as the corresponding
22619     * method in View for the case of no accessibility delegate been set. Hence,
22620     * to customize the behavior of a View method, clients can override only the
22621     * corresponding delegate method without altering the behavior of the rest
22622     * accessibility related methods of the host view.
22623     * </p>
22624     * <p>
22625     * <strong>Note:</strong> On platform versions prior to
22626     * {@link android.os.Build.VERSION_CODES#M API 23}, delegate methods on
22627     * views in the {@code android.widget.*} package are called <i>before</i>
22628     * host methods. This prevents certain properties such as class name from
22629     * being modified by overriding
22630     * {@link AccessibilityDelegate#onInitializeAccessibilityNodeInfo(View, AccessibilityNodeInfo)},
22631     * as any changes will be overwritten by the host class.
22632     * <p>
22633     * Starting in {@link android.os.Build.VERSION_CODES#M API 23}, delegate
22634     * methods are called <i>after</i> host methods, which all properties to be
22635     * modified without being overwritten by the host class.
22636     */
22637    public static class AccessibilityDelegate {
22638
22639        /**
22640         * Sends an accessibility event of the given type. If accessibility is not
22641         * enabled this method has no effect.
22642         * <p>
22643         * The default implementation behaves as {@link View#sendAccessibilityEvent(int)
22644         *  View#sendAccessibilityEvent(int)} for the case of no accessibility delegate
22645         * been set.
22646         * </p>
22647         *
22648         * @param host The View hosting the delegate.
22649         * @param eventType The type of the event to send.
22650         *
22651         * @see View#sendAccessibilityEvent(int) View#sendAccessibilityEvent(int)
22652         */
22653        public void sendAccessibilityEvent(View host, int eventType) {
22654            host.sendAccessibilityEventInternal(eventType);
22655        }
22656
22657        /**
22658         * Performs the specified accessibility action on the view. For
22659         * possible accessibility actions look at {@link AccessibilityNodeInfo}.
22660         * <p>
22661         * The default implementation behaves as
22662         * {@link View#performAccessibilityAction(int, Bundle)
22663         *  View#performAccessibilityAction(int, Bundle)} for the case of
22664         *  no accessibility delegate been set.
22665         * </p>
22666         *
22667         * @param action The action to perform.
22668         * @return Whether the action was performed.
22669         *
22670         * @see View#performAccessibilityAction(int, Bundle)
22671         *      View#performAccessibilityAction(int, Bundle)
22672         */
22673        public boolean performAccessibilityAction(View host, int action, Bundle args) {
22674            return host.performAccessibilityActionInternal(action, args);
22675        }
22676
22677        /**
22678         * Sends an accessibility event. This method behaves exactly as
22679         * {@link #sendAccessibilityEvent(View, int)} but takes as an argument an
22680         * empty {@link AccessibilityEvent} and does not perform a check whether
22681         * accessibility is enabled.
22682         * <p>
22683         * The default implementation behaves as
22684         * {@link View#sendAccessibilityEventUnchecked(AccessibilityEvent)
22685         *  View#sendAccessibilityEventUnchecked(AccessibilityEvent)} for
22686         * the case of no accessibility delegate been set.
22687         * </p>
22688         *
22689         * @param host The View hosting the delegate.
22690         * @param event The event to send.
22691         *
22692         * @see View#sendAccessibilityEventUnchecked(AccessibilityEvent)
22693         *      View#sendAccessibilityEventUnchecked(AccessibilityEvent)
22694         */
22695        public void sendAccessibilityEventUnchecked(View host, AccessibilityEvent event) {
22696            host.sendAccessibilityEventUncheckedInternal(event);
22697        }
22698
22699        /**
22700         * Dispatches an {@link AccessibilityEvent} to the host {@link View} first and then
22701         * to its children for adding their text content to the event.
22702         * <p>
22703         * The default implementation behaves as
22704         * {@link View#dispatchPopulateAccessibilityEvent(AccessibilityEvent)
22705         *  View#dispatchPopulateAccessibilityEvent(AccessibilityEvent)} for
22706         * the case of no accessibility delegate been set.
22707         * </p>
22708         *
22709         * @param host The View hosting the delegate.
22710         * @param event The event.
22711         * @return True if the event population was completed.
22712         *
22713         * @see View#dispatchPopulateAccessibilityEvent(AccessibilityEvent)
22714         *      View#dispatchPopulateAccessibilityEvent(AccessibilityEvent)
22715         */
22716        public boolean dispatchPopulateAccessibilityEvent(View host, AccessibilityEvent event) {
22717            return host.dispatchPopulateAccessibilityEventInternal(event);
22718        }
22719
22720        /**
22721         * Gives a chance to the host View to populate the accessibility event with its
22722         * text content.
22723         * <p>
22724         * The default implementation behaves as
22725         * {@link View#onPopulateAccessibilityEvent(AccessibilityEvent)
22726         *  View#onPopulateAccessibilityEvent(AccessibilityEvent)} for
22727         * the case of no accessibility delegate been set.
22728         * </p>
22729         *
22730         * @param host The View hosting the delegate.
22731         * @param event The accessibility event which to populate.
22732         *
22733         * @see View#onPopulateAccessibilityEvent(AccessibilityEvent)
22734         *      View#onPopulateAccessibilityEvent(AccessibilityEvent)
22735         */
22736        public void onPopulateAccessibilityEvent(View host, AccessibilityEvent event) {
22737            host.onPopulateAccessibilityEventInternal(event);
22738        }
22739
22740        /**
22741         * Initializes an {@link AccessibilityEvent} with information about the
22742         * the host View which is the event source.
22743         * <p>
22744         * The default implementation behaves as
22745         * {@link View#onInitializeAccessibilityEvent(AccessibilityEvent)
22746         *  View#onInitializeAccessibilityEvent(AccessibilityEvent)} for
22747         * the case of no accessibility delegate been set.
22748         * </p>
22749         *
22750         * @param host The View hosting the delegate.
22751         * @param event The event to initialize.
22752         *
22753         * @see View#onInitializeAccessibilityEvent(AccessibilityEvent)
22754         *      View#onInitializeAccessibilityEvent(AccessibilityEvent)
22755         */
22756        public void onInitializeAccessibilityEvent(View host, AccessibilityEvent event) {
22757            host.onInitializeAccessibilityEventInternal(event);
22758        }
22759
22760        /**
22761         * Initializes an {@link AccessibilityNodeInfo} with information about the host view.
22762         * <p>
22763         * The default implementation behaves as
22764         * {@link View#onInitializeAccessibilityNodeInfo(AccessibilityNodeInfo)
22765         *  View#onInitializeAccessibilityNodeInfo(AccessibilityNodeInfo)} for
22766         * the case of no accessibility delegate been set.
22767         * </p>
22768         *
22769         * @param host The View hosting the delegate.
22770         * @param info The instance to initialize.
22771         *
22772         * @see View#onInitializeAccessibilityNodeInfo(AccessibilityNodeInfo)
22773         *      View#onInitializeAccessibilityNodeInfo(AccessibilityNodeInfo)
22774         */
22775        public void onInitializeAccessibilityNodeInfo(View host, AccessibilityNodeInfo info) {
22776            host.onInitializeAccessibilityNodeInfoInternal(info);
22777        }
22778
22779        /**
22780         * Called when a child of the host View has requested sending an
22781         * {@link AccessibilityEvent} and gives an opportunity to the parent (the host)
22782         * to augment the event.
22783         * <p>
22784         * The default implementation behaves as
22785         * {@link ViewGroup#onRequestSendAccessibilityEvent(View, AccessibilityEvent)
22786         *  ViewGroup#onRequestSendAccessibilityEvent(View, AccessibilityEvent)} for
22787         * the case of no accessibility delegate been set.
22788         * </p>
22789         *
22790         * @param host The View hosting the delegate.
22791         * @param child The child which requests sending the event.
22792         * @param event The event to be sent.
22793         * @return True if the event should be sent
22794         *
22795         * @see ViewGroup#onRequestSendAccessibilityEvent(View, AccessibilityEvent)
22796         *      ViewGroup#onRequestSendAccessibilityEvent(View, AccessibilityEvent)
22797         */
22798        public boolean onRequestSendAccessibilityEvent(ViewGroup host, View child,
22799                AccessibilityEvent event) {
22800            return host.onRequestSendAccessibilityEventInternal(child, event);
22801        }
22802
22803        /**
22804         * Gets the provider for managing a virtual view hierarchy rooted at this View
22805         * and reported to {@link android.accessibilityservice.AccessibilityService}s
22806         * that explore the window content.
22807         * <p>
22808         * The default implementation behaves as
22809         * {@link View#getAccessibilityNodeProvider() View#getAccessibilityNodeProvider()} for
22810         * the case of no accessibility delegate been set.
22811         * </p>
22812         *
22813         * @return The provider.
22814         *
22815         * @see AccessibilityNodeProvider
22816         */
22817        public AccessibilityNodeProvider getAccessibilityNodeProvider(View host) {
22818            return null;
22819        }
22820
22821        /**
22822         * Returns an {@link AccessibilityNodeInfo} representing the host view from the
22823         * point of view of an {@link android.accessibilityservice.AccessibilityService}.
22824         * This method is responsible for obtaining an accessibility node info from a
22825         * pool of reusable instances and calling
22826         * {@link #onInitializeAccessibilityNodeInfo(AccessibilityNodeInfo)} on the host
22827         * view to initialize the former.
22828         * <p>
22829         * <strong>Note:</strong> The client is responsible for recycling the obtained
22830         * instance by calling {@link AccessibilityNodeInfo#recycle()} to minimize object
22831         * creation.
22832         * </p>
22833         * <p>
22834         * The default implementation behaves as
22835         * {@link View#createAccessibilityNodeInfo() View#createAccessibilityNodeInfo()} for
22836         * the case of no accessibility delegate been set.
22837         * </p>
22838         * @return A populated {@link AccessibilityNodeInfo}.
22839         *
22840         * @see AccessibilityNodeInfo
22841         *
22842         * @hide
22843         */
22844        public AccessibilityNodeInfo createAccessibilityNodeInfo(View host) {
22845            return host.createAccessibilityNodeInfoInternal();
22846        }
22847    }
22848
22849    private class MatchIdPredicate implements Predicate<View> {
22850        public int mId;
22851
22852        @Override
22853        public boolean apply(View view) {
22854            return (view.mID == mId);
22855        }
22856    }
22857
22858    private class MatchLabelForPredicate implements Predicate<View> {
22859        private int mLabeledId;
22860
22861        @Override
22862        public boolean apply(View view) {
22863            return (view.mLabelForId == mLabeledId);
22864        }
22865    }
22866
22867    private class SendViewStateChangedAccessibilityEvent implements Runnable {
22868        private int mChangeTypes = 0;
22869        private boolean mPosted;
22870        private boolean mPostedWithDelay;
22871        private long mLastEventTimeMillis;
22872
22873        @Override
22874        public void run() {
22875            mPosted = false;
22876            mPostedWithDelay = false;
22877            mLastEventTimeMillis = SystemClock.uptimeMillis();
22878            if (AccessibilityManager.getInstance(mContext).isEnabled()) {
22879                final AccessibilityEvent event = AccessibilityEvent.obtain();
22880                event.setEventType(AccessibilityEvent.TYPE_WINDOW_CONTENT_CHANGED);
22881                event.setContentChangeTypes(mChangeTypes);
22882                sendAccessibilityEventUnchecked(event);
22883            }
22884            mChangeTypes = 0;
22885        }
22886
22887        public void runOrPost(int changeType) {
22888            mChangeTypes |= changeType;
22889
22890            // If this is a live region or the child of a live region, collect
22891            // all events from this frame and send them on the next frame.
22892            if (inLiveRegion()) {
22893                // If we're already posted with a delay, remove that.
22894                if (mPostedWithDelay) {
22895                    removeCallbacks(this);
22896                    mPostedWithDelay = false;
22897                }
22898                // Only post if we're not already posted.
22899                if (!mPosted) {
22900                    post(this);
22901                    mPosted = true;
22902                }
22903                return;
22904            }
22905
22906            if (mPosted) {
22907                return;
22908            }
22909
22910            final long timeSinceLastMillis = SystemClock.uptimeMillis() - mLastEventTimeMillis;
22911            final long minEventIntevalMillis =
22912                    ViewConfiguration.getSendRecurringAccessibilityEventsInterval();
22913            if (timeSinceLastMillis >= minEventIntevalMillis) {
22914                removeCallbacks(this);
22915                run();
22916            } else {
22917                postDelayed(this, minEventIntevalMillis - timeSinceLastMillis);
22918                mPostedWithDelay = true;
22919            }
22920        }
22921    }
22922
22923    private boolean inLiveRegion() {
22924        if (getAccessibilityLiveRegion() != View.ACCESSIBILITY_LIVE_REGION_NONE) {
22925            return true;
22926        }
22927
22928        ViewParent parent = getParent();
22929        while (parent instanceof View) {
22930            if (((View) parent).getAccessibilityLiveRegion()
22931                    != View.ACCESSIBILITY_LIVE_REGION_NONE) {
22932                return true;
22933            }
22934            parent = parent.getParent();
22935        }
22936
22937        return false;
22938    }
22939
22940    /**
22941     * Dump all private flags in readable format, useful for documentation and
22942     * sanity checking.
22943     */
22944    private static void dumpFlags() {
22945        final HashMap<String, String> found = Maps.newHashMap();
22946        try {
22947            for (Field field : View.class.getDeclaredFields()) {
22948                final int modifiers = field.getModifiers();
22949                if (Modifier.isStatic(modifiers) && Modifier.isFinal(modifiers)) {
22950                    if (field.getType().equals(int.class)) {
22951                        final int value = field.getInt(null);
22952                        dumpFlag(found, field.getName(), value);
22953                    } else if (field.getType().equals(int[].class)) {
22954                        final int[] values = (int[]) field.get(null);
22955                        for (int i = 0; i < values.length; i++) {
22956                            dumpFlag(found, field.getName() + "[" + i + "]", values[i]);
22957                        }
22958                    }
22959                }
22960            }
22961        } catch (IllegalAccessException e) {
22962            throw new RuntimeException(e);
22963        }
22964
22965        final ArrayList<String> keys = Lists.newArrayList();
22966        keys.addAll(found.keySet());
22967        Collections.sort(keys);
22968        for (String key : keys) {
22969            Log.d(VIEW_LOG_TAG, found.get(key));
22970        }
22971    }
22972
22973    private static void dumpFlag(HashMap<String, String> found, String name, int value) {
22974        // Sort flags by prefix, then by bits, always keeping unique keys
22975        final String bits = String.format("%32s", Integer.toBinaryString(value)).replace('0', ' ');
22976        final int prefix = name.indexOf('_');
22977        final String key = (prefix > 0 ? name.substring(0, prefix) : name) + bits + name;
22978        final String output = bits + " " + name;
22979        found.put(key, output);
22980    }
22981
22982    /** {@hide} */
22983    public void encode(@NonNull ViewHierarchyEncoder stream) {
22984        stream.beginObject(this);
22985        encodeProperties(stream);
22986        stream.endObject();
22987    }
22988
22989    /** {@hide} */
22990    @CallSuper
22991    protected void encodeProperties(@NonNull ViewHierarchyEncoder stream) {
22992        Object resolveId = ViewDebug.resolveId(getContext(), mID);
22993        if (resolveId instanceof String) {
22994            stream.addProperty("id", (String) resolveId);
22995        } else {
22996            stream.addProperty("id", mID);
22997        }
22998
22999        stream.addProperty("misc:transformation.alpha",
23000                mTransformationInfo != null ? mTransformationInfo.mAlpha : 0);
23001        stream.addProperty("misc:transitionName", getTransitionName());
23002
23003        // layout
23004        stream.addProperty("layout:left", mLeft);
23005        stream.addProperty("layout:right", mRight);
23006        stream.addProperty("layout:top", mTop);
23007        stream.addProperty("layout:bottom", mBottom);
23008        stream.addProperty("layout:width", getWidth());
23009        stream.addProperty("layout:height", getHeight());
23010        stream.addProperty("layout:layoutDirection", getLayoutDirection());
23011        stream.addProperty("layout:layoutRtl", isLayoutRtl());
23012        stream.addProperty("layout:hasTransientState", hasTransientState());
23013        stream.addProperty("layout:baseline", getBaseline());
23014
23015        // layout params
23016        ViewGroup.LayoutParams layoutParams = getLayoutParams();
23017        if (layoutParams != null) {
23018            stream.addPropertyKey("layoutParams");
23019            layoutParams.encode(stream);
23020        }
23021
23022        // scrolling
23023        stream.addProperty("scrolling:scrollX", mScrollX);
23024        stream.addProperty("scrolling:scrollY", mScrollY);
23025
23026        // padding
23027        stream.addProperty("padding:paddingLeft", mPaddingLeft);
23028        stream.addProperty("padding:paddingRight", mPaddingRight);
23029        stream.addProperty("padding:paddingTop", mPaddingTop);
23030        stream.addProperty("padding:paddingBottom", mPaddingBottom);
23031        stream.addProperty("padding:userPaddingRight", mUserPaddingRight);
23032        stream.addProperty("padding:userPaddingLeft", mUserPaddingLeft);
23033        stream.addProperty("padding:userPaddingBottom", mUserPaddingBottom);
23034        stream.addProperty("padding:userPaddingStart", mUserPaddingStart);
23035        stream.addProperty("padding:userPaddingEnd", mUserPaddingEnd);
23036
23037        // measurement
23038        stream.addProperty("measurement:minHeight", mMinHeight);
23039        stream.addProperty("measurement:minWidth", mMinWidth);
23040        stream.addProperty("measurement:measuredWidth", mMeasuredWidth);
23041        stream.addProperty("measurement:measuredHeight", mMeasuredHeight);
23042
23043        // drawing
23044        stream.addProperty("drawing:elevation", getElevation());
23045        stream.addProperty("drawing:translationX", getTranslationX());
23046        stream.addProperty("drawing:translationY", getTranslationY());
23047        stream.addProperty("drawing:translationZ", getTranslationZ());
23048        stream.addProperty("drawing:rotation", getRotation());
23049        stream.addProperty("drawing:rotationX", getRotationX());
23050        stream.addProperty("drawing:rotationY", getRotationY());
23051        stream.addProperty("drawing:scaleX", getScaleX());
23052        stream.addProperty("drawing:scaleY", getScaleY());
23053        stream.addProperty("drawing:pivotX", getPivotX());
23054        stream.addProperty("drawing:pivotY", getPivotY());
23055        stream.addProperty("drawing:opaque", isOpaque());
23056        stream.addProperty("drawing:alpha", getAlpha());
23057        stream.addProperty("drawing:transitionAlpha", getTransitionAlpha());
23058        stream.addProperty("drawing:shadow", hasShadow());
23059        stream.addProperty("drawing:solidColor", getSolidColor());
23060        stream.addProperty("drawing:layerType", mLayerType);
23061        stream.addProperty("drawing:willNotDraw", willNotDraw());
23062        stream.addProperty("drawing:hardwareAccelerated", isHardwareAccelerated());
23063        stream.addProperty("drawing:willNotCacheDrawing", willNotCacheDrawing());
23064        stream.addProperty("drawing:drawingCacheEnabled", isDrawingCacheEnabled());
23065        stream.addProperty("drawing:overlappingRendering", hasOverlappingRendering());
23066
23067        // focus
23068        stream.addProperty("focus:hasFocus", hasFocus());
23069        stream.addProperty("focus:isFocused", isFocused());
23070        stream.addProperty("focus:isFocusable", isFocusable());
23071        stream.addProperty("focus:isFocusableInTouchMode", isFocusableInTouchMode());
23072
23073        stream.addProperty("misc:clickable", isClickable());
23074        stream.addProperty("misc:pressed", isPressed());
23075        stream.addProperty("misc:selected", isSelected());
23076        stream.addProperty("misc:touchMode", isInTouchMode());
23077        stream.addProperty("misc:hovered", isHovered());
23078        stream.addProperty("misc:activated", isActivated());
23079
23080        stream.addProperty("misc:visibility", getVisibility());
23081        stream.addProperty("misc:fitsSystemWindows", getFitsSystemWindows());
23082        stream.addProperty("misc:filterTouchesWhenObscured", getFilterTouchesWhenObscured());
23083
23084        stream.addProperty("misc:enabled", isEnabled());
23085        stream.addProperty("misc:soundEffectsEnabled", isSoundEffectsEnabled());
23086        stream.addProperty("misc:hapticFeedbackEnabled", isHapticFeedbackEnabled());
23087
23088        // theme attributes
23089        Resources.Theme theme = getContext().getTheme();
23090        if (theme != null) {
23091            stream.addPropertyKey("theme");
23092            theme.encode(stream);
23093        }
23094
23095        // view attribute information
23096        int n = mAttributes != null ? mAttributes.length : 0;
23097        stream.addProperty("meta:__attrCount__", n/2);
23098        for (int i = 0; i < n; i += 2) {
23099            stream.addProperty("meta:__attr__" + mAttributes[i], mAttributes[i+1]);
23100        }
23101
23102        stream.addProperty("misc:scrollBarStyle", getScrollBarStyle());
23103
23104        // text
23105        stream.addProperty("text:textDirection", getTextDirection());
23106        stream.addProperty("text:textAlignment", getTextAlignment());
23107
23108        // accessibility
23109        CharSequence contentDescription = getContentDescription();
23110        stream.addProperty("accessibility:contentDescription",
23111                contentDescription == null ? "" : contentDescription.toString());
23112        stream.addProperty("accessibility:labelFor", getLabelFor());
23113        stream.addProperty("accessibility:importantForAccessibility", getImportantForAccessibility());
23114    }
23115}
23116