• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 
17 package android.view;
18 
19 import android.animation.AnimatorInflater;
20 import android.animation.StateListAnimator;
21 import android.annotation.CallSuper;
22 import android.annotation.ColorInt;
23 import android.annotation.DrawableRes;
24 import android.annotation.FloatRange;
25 import android.annotation.IdRes;
26 import android.annotation.IntDef;
27 import android.annotation.LayoutRes;
28 import android.annotation.NonNull;
29 import android.annotation.Nullable;
30 import android.annotation.Size;
31 import android.annotation.UiThread;
32 import android.content.ClipData;
33 import android.content.Context;
34 import android.content.ContextWrapper;
35 import android.content.Intent;
36 import android.content.res.ColorStateList;
37 import android.content.res.Configuration;
38 import android.content.res.Resources;
39 import android.content.res.TypedArray;
40 import android.graphics.Bitmap;
41 import android.graphics.Canvas;
42 import android.graphics.Insets;
43 import android.graphics.Interpolator;
44 import android.graphics.LinearGradient;
45 import android.graphics.Matrix;
46 import android.graphics.Outline;
47 import android.graphics.Paint;
48 import android.graphics.PixelFormat;
49 import android.graphics.Point;
50 import android.graphics.PorterDuff;
51 import android.graphics.PorterDuffXfermode;
52 import android.graphics.Rect;
53 import android.graphics.RectF;
54 import android.graphics.Region;
55 import android.graphics.Shader;
56 import android.graphics.drawable.ColorDrawable;
57 import android.graphics.drawable.Drawable;
58 import android.hardware.display.DisplayManagerGlobal;
59 import android.os.Build.VERSION_CODES;
60 import android.os.Bundle;
61 import android.os.Handler;
62 import android.os.IBinder;
63 import android.os.Parcel;
64 import android.os.Parcelable;
65 import android.os.RemoteException;
66 import android.os.SystemClock;
67 import android.os.SystemProperties;
68 import android.os.Trace;
69 import android.text.TextUtils;
70 import android.util.AttributeSet;
71 import android.util.FloatProperty;
72 import android.util.LayoutDirection;
73 import android.util.Log;
74 import android.util.LongSparseLongArray;
75 import android.util.Pools.SynchronizedPool;
76 import android.util.Property;
77 import android.util.SparseArray;
78 import android.util.StateSet;
79 import android.util.SuperNotCalledException;
80 import android.util.TypedValue;
81 import android.view.ContextMenu.ContextMenuInfo;
82 import android.view.AccessibilityIterators.TextSegmentIterator;
83 import android.view.AccessibilityIterators.CharacterTextSegmentIterator;
84 import android.view.AccessibilityIterators.WordTextSegmentIterator;
85 import android.view.AccessibilityIterators.ParagraphTextSegmentIterator;
86 import android.view.accessibility.AccessibilityEvent;
87 import android.view.accessibility.AccessibilityEventSource;
88 import android.view.accessibility.AccessibilityManager;
89 import android.view.accessibility.AccessibilityNodeInfo;
90 import android.view.accessibility.AccessibilityNodeInfo.AccessibilityAction;
91 import android.view.accessibility.AccessibilityNodeProvider;
92 import android.view.animation.Animation;
93 import android.view.animation.AnimationUtils;
94 import android.view.animation.Transformation;
95 import android.view.inputmethod.EditorInfo;
96 import android.view.inputmethod.InputConnection;
97 import android.view.inputmethod.InputMethodManager;
98 import android.widget.Checkable;
99 import android.widget.FrameLayout;
100 import android.widget.ScrollBarDrawable;
101 
102 import static android.os.Build.VERSION_CODES.*;
103 import static java.lang.Math.max;
104 
105 import com.android.internal.R;
106 import com.android.internal.util.Predicate;
107 import com.android.internal.view.menu.MenuBuilder;
108 import com.google.android.collect.Lists;
109 import com.google.android.collect.Maps;
110 
111 import java.lang.annotation.Retention;
112 import java.lang.annotation.RetentionPolicy;
113 import java.lang.ref.WeakReference;
114 import java.lang.reflect.Field;
115 import java.lang.reflect.InvocationTargetException;
116 import java.lang.reflect.Method;
117 import java.lang.reflect.Modifier;
118 import java.util.ArrayList;
119 import java.util.Arrays;
120 import java.util.Collections;
121 import java.util.HashMap;
122 import java.util.List;
123 import java.util.Locale;
124 import java.util.Map;
125 import java.util.concurrent.CopyOnWriteArrayList;
126 import java.util.concurrent.atomic.AtomicInteger;
127 
128 /**
129  * <p>
130  * This class represents the basic building block for user interface components. A View
131  * occupies a rectangular area on the screen and is responsible for drawing and
132  * event handling. View is the base class for <em>widgets</em>, which are
133  * used to create interactive UI components (buttons, text fields, etc.). The
134  * {@link android.view.ViewGroup} subclass is the base class for <em>layouts</em>, which
135  * are invisible containers that hold other Views (or other ViewGroups) and define
136  * their layout properties.
137  * </p>
138  *
139  * <div class="special reference">
140  * <h3>Developer Guides</h3>
141  * <p>For information about using this class to develop your application's user interface,
142  * read the <a href="{@docRoot}guide/topics/ui/index.html">User Interface</a> developer guide.
143  * </div>
144  *
145  * <a name="Using"></a>
146  * <h3>Using Views</h3>
147  * <p>
148  * All of the views in a window are arranged in a single tree. You can add views
149  * either from code or by specifying a tree of views in one or more XML layout
150  * files. There are many specialized subclasses of views that act as controls or
151  * are capable of displaying text, images, or other content.
152  * </p>
153  * <p>
154  * Once you have created a tree of views, there are typically a few types of
155  * common operations you may wish to perform:
156  * <ul>
157  * <li><strong>Set properties:</strong> for example setting the text of a
158  * {@link android.widget.TextView}. The available properties and the methods
159  * that set them will vary among the different subclasses of views. Note that
160  * properties that are known at build time can be set in the XML layout
161  * files.</li>
162  * <li><strong>Set focus:</strong> The framework will handled moving focus in
163  * response to user input. To force focus to a specific view, call
164  * {@link #requestFocus}.</li>
165  * <li><strong>Set up listeners:</strong> Views allow clients to set listeners
166  * that will be notified when something interesting happens to the view. For
167  * example, all views will let you set a listener to be notified when the view
168  * gains or loses focus. You can register such a listener using
169  * {@link #setOnFocusChangeListener(android.view.View.OnFocusChangeListener)}.
170  * Other view subclasses offer more specialized listeners. For example, a Button
171  * exposes a listener to notify clients when the button is clicked.</li>
172  * <li><strong>Set visibility:</strong> You can hide or show views using
173  * {@link #setVisibility(int)}.</li>
174  * </ul>
175  * </p>
176  * <p><em>
177  * Note: The Android framework is responsible for measuring, laying out and
178  * drawing views. You should not call methods that perform these actions on
179  * views yourself unless you are actually implementing a
180  * {@link android.view.ViewGroup}.
181  * </em></p>
182  *
183  * <a name="Lifecycle"></a>
184  * <h3>Implementing a Custom View</h3>
185  *
186  * <p>
187  * To implement a custom view, you will usually begin by providing overrides for
188  * some of the standard methods that the framework calls on all views. You do
189  * not need to override all of these methods. In fact, you can start by just
190  * overriding {@link #onDraw(android.graphics.Canvas)}.
191  * <table border="2" width="85%" align="center" cellpadding="5">
192  *     <thead>
193  *         <tr><th>Category</th> <th>Methods</th> <th>Description</th></tr>
194  *     </thead>
195  *
196  *     <tbody>
197  *     <tr>
198  *         <td rowspan="2">Creation</td>
199  *         <td>Constructors</td>
200  *         <td>There is a form of the constructor that are called when the view
201  *         is created from code and a form that is called when the view is
202  *         inflated from a layout file. The second form should parse and apply
203  *         any attributes defined in the layout file.
204  *         </td>
205  *     </tr>
206  *     <tr>
207  *         <td><code>{@link #onFinishInflate()}</code></td>
208  *         <td>Called after a view and all of its children has been inflated
209  *         from XML.</td>
210  *     </tr>
211  *
212  *     <tr>
213  *         <td rowspan="3">Layout</td>
214  *         <td><code>{@link #onMeasure(int, int)}</code></td>
215  *         <td>Called to determine the size requirements for this view and all
216  *         of its children.
217  *         </td>
218  *     </tr>
219  *     <tr>
220  *         <td><code>{@link #onLayout(boolean, int, int, int, int)}</code></td>
221  *         <td>Called when this view should assign a size and position to all
222  *         of its children.
223  *         </td>
224  *     </tr>
225  *     <tr>
226  *         <td><code>{@link #onSizeChanged(int, int, int, int)}</code></td>
227  *         <td>Called when the size of this view has changed.
228  *         </td>
229  *     </tr>
230  *
231  *     <tr>
232  *         <td>Drawing</td>
233  *         <td><code>{@link #onDraw(android.graphics.Canvas)}</code></td>
234  *         <td>Called when the view should render its content.
235  *         </td>
236  *     </tr>
237  *
238  *     <tr>
239  *         <td rowspan="4">Event processing</td>
240  *         <td><code>{@link #onKeyDown(int, KeyEvent)}</code></td>
241  *         <td>Called when a new hardware key event occurs.
242  *         </td>
243  *     </tr>
244  *     <tr>
245  *         <td><code>{@link #onKeyUp(int, KeyEvent)}</code></td>
246  *         <td>Called when a hardware key up event occurs.
247  *         </td>
248  *     </tr>
249  *     <tr>
250  *         <td><code>{@link #onTrackballEvent(MotionEvent)}</code></td>
251  *         <td>Called when a trackball motion event occurs.
252  *         </td>
253  *     </tr>
254  *     <tr>
255  *         <td><code>{@link #onTouchEvent(MotionEvent)}</code></td>
256  *         <td>Called when a touch screen motion event occurs.
257  *         </td>
258  *     </tr>
259  *
260  *     <tr>
261  *         <td rowspan="2">Focus</td>
262  *         <td><code>{@link #onFocusChanged(boolean, int, android.graphics.Rect)}</code></td>
263  *         <td>Called when the view gains or loses focus.
264  *         </td>
265  *     </tr>
266  *
267  *     <tr>
268  *         <td><code>{@link #onWindowFocusChanged(boolean)}</code></td>
269  *         <td>Called when the window containing the view gains or loses focus.
270  *         </td>
271  *     </tr>
272  *
273  *     <tr>
274  *         <td rowspan="3">Attaching</td>
275  *         <td><code>{@link #onAttachedToWindow()}</code></td>
276  *         <td>Called when the view is attached to a window.
277  *         </td>
278  *     </tr>
279  *
280  *     <tr>
281  *         <td><code>{@link #onDetachedFromWindow}</code></td>
282  *         <td>Called when the view is detached from its window.
283  *         </td>
284  *     </tr>
285  *
286  *     <tr>
287  *         <td><code>{@link #onWindowVisibilityChanged(int)}</code></td>
288  *         <td>Called when the visibility of the window containing the view
289  *         has changed.
290  *         </td>
291  *     </tr>
292  *     </tbody>
293  *
294  * </table>
295  * </p>
296  *
297  * <a name="IDs"></a>
298  * <h3>IDs</h3>
299  * Views may have an integer id associated with them. These ids are typically
300  * assigned in the layout XML files, and are used to find specific views within
301  * the view tree. A common pattern is to:
302  * <ul>
303  * <li>Define a Button in the layout file and assign it a unique ID.
304  * <pre>
305  * &lt;Button
306  *     android:id="@+id/my_button"
307  *     android:layout_width="wrap_content"
308  *     android:layout_height="wrap_content"
309  *     android:text="@string/my_button_text"/&gt;
310  * </pre></li>
311  * <li>From the onCreate method of an Activity, find the Button
312  * <pre class="prettyprint">
313  *      Button myButton = (Button) findViewById(R.id.my_button);
314  * </pre></li>
315  * </ul>
316  * <p>
317  * View IDs need not be unique throughout the tree, but it is good practice to
318  * ensure that they are at least unique within the part of the tree you are
319  * searching.
320  * </p>
321  *
322  * <a name="Position"></a>
323  * <h3>Position</h3>
324  * <p>
325  * The geometry of a view is that of a rectangle. A view has a location,
326  * expressed as a pair of <em>left</em> and <em>top</em> coordinates, and
327  * two dimensions, expressed as a width and a height. The unit for location
328  * and dimensions is the pixel.
329  * </p>
330  *
331  * <p>
332  * It is possible to retrieve the location of a view by invoking the methods
333  * {@link #getLeft()} and {@link #getTop()}. The former returns the left, or X,
334  * coordinate of the rectangle representing the view. The latter returns the
335  * top, or Y, coordinate of the rectangle representing the view. These methods
336  * both return the location of the view relative to its parent. For instance,
337  * when getLeft() returns 20, that means the view is located 20 pixels to the
338  * right of the left edge of its direct parent.
339  * </p>
340  *
341  * <p>
342  * In addition, several convenience methods are offered to avoid unnecessary
343  * computations, namely {@link #getRight()} and {@link #getBottom()}.
344  * These methods return the coordinates of the right and bottom edges of the
345  * rectangle representing the view. For instance, calling {@link #getRight()}
346  * is similar to the following computation: <code>getLeft() + getWidth()</code>
347  * (see <a href="#SizePaddingMargins">Size</a> for more information about the width.)
348  * </p>
349  *
350  * <a name="SizePaddingMargins"></a>
351  * <h3>Size, padding and margins</h3>
352  * <p>
353  * The size of a view is expressed with a width and a height. A view actually
354  * possess two pairs of width and height values.
355  * </p>
356  *
357  * <p>
358  * The first pair is known as <em>measured width</em> and
359  * <em>measured height</em>. These dimensions define how big a view wants to be
360  * within its parent (see <a href="#Layout">Layout</a> for more details.) The
361  * measured dimensions can be obtained by calling {@link #getMeasuredWidth()}
362  * and {@link #getMeasuredHeight()}.
363  * </p>
364  *
365  * <p>
366  * The second pair is simply known as <em>width</em> and <em>height</em>, or
367  * sometimes <em>drawing width</em> and <em>drawing height</em>. These
368  * dimensions define the actual size of the view on screen, at drawing time and
369  * after layout. These values may, but do not have to, be different from the
370  * measured width and height. The width and height can be obtained by calling
371  * {@link #getWidth()} and {@link #getHeight()}.
372  * </p>
373  *
374  * <p>
375  * To measure its dimensions, a view takes into account its padding. The padding
376  * is expressed in pixels for the left, top, right and bottom parts of the view.
377  * Padding can be used to offset the content of the view by a specific amount of
378  * pixels. For instance, a left padding of 2 will push the view's content by
379  * 2 pixels to the right of the left edge. Padding can be set using the
380  * {@link #setPadding(int, int, int, int)} or {@link #setPaddingRelative(int, int, int, int)}
381  * method and queried by calling {@link #getPaddingLeft()}, {@link #getPaddingTop()},
382  * {@link #getPaddingRight()}, {@link #getPaddingBottom()}, {@link #getPaddingStart()},
383  * {@link #getPaddingEnd()}.
384  * </p>
385  *
386  * <p>
387  * Even though a view can define a padding, it does not provide any support for
388  * margins. However, view groups provide such a support. Refer to
389  * {@link android.view.ViewGroup} and
390  * {@link android.view.ViewGroup.MarginLayoutParams} for further information.
391  * </p>
392  *
393  * <a name="Layout"></a>
394  * <h3>Layout</h3>
395  * <p>
396  * Layout is a two pass process: a measure pass and a layout pass. The measuring
397  * pass is implemented in {@link #measure(int, int)} and is a top-down traversal
398  * of the view tree. Each view pushes dimension specifications down the tree
399  * during the recursion. At the end of the measure pass, every view has stored
400  * its measurements. The second pass happens in
401  * {@link #layout(int,int,int,int)} and is also top-down. During
402  * this pass each parent is responsible for positioning all of its children
403  * using the sizes computed in the measure pass.
404  * </p>
405  *
406  * <p>
407  * When a view's measure() method returns, its {@link #getMeasuredWidth()} and
408  * {@link #getMeasuredHeight()} values must be set, along with those for all of
409  * that view's descendants. A view's measured width and measured height values
410  * must respect the constraints imposed by the view's parents. This guarantees
411  * that at the end of the measure pass, all parents accept all of their
412  * children's measurements. A parent view may call measure() more than once on
413  * its children. For example, the parent may measure each child once with
414  * unspecified dimensions to find out how big they want to be, then call
415  * measure() on them again with actual numbers if the sum of all the children's
416  * unconstrained sizes is too big or too small.
417  * </p>
418  *
419  * <p>
420  * The measure pass uses two classes to communicate dimensions. The
421  * {@link MeasureSpec} class is used by views to tell their parents how they
422  * want to be measured and positioned. The base LayoutParams class just
423  * describes how big the view wants to be for both width and height. For each
424  * dimension, it can specify one of:
425  * <ul>
426  * <li> an exact number
427  * <li>MATCH_PARENT, which means the view wants to be as big as its parent
428  * (minus padding)
429  * <li> WRAP_CONTENT, which means that the view wants to be just big enough to
430  * enclose its content (plus padding).
431  * </ul>
432  * There are subclasses of LayoutParams for different subclasses of ViewGroup.
433  * For example, AbsoluteLayout has its own subclass of LayoutParams which adds
434  * an X and Y value.
435  * </p>
436  *
437  * <p>
438  * MeasureSpecs are used to push requirements down the tree from parent to
439  * child. A MeasureSpec can be in one of three modes:
440  * <ul>
441  * <li>UNSPECIFIED: This is used by a parent to determine the desired dimension
442  * of a child view. For example, a LinearLayout may call measure() on its child
443  * with the height set to UNSPECIFIED and a width of EXACTLY 240 to find out how
444  * tall the child view wants to be given a width of 240 pixels.
445  * <li>EXACTLY: This is used by the parent to impose an exact size on the
446  * child. The child must use this size, and guarantee that all of its
447  * descendants will fit within this size.
448  * <li>AT_MOST: This is used by the parent to impose a maximum size on the
449  * child. The child must guarantee that it and all of its descendants will fit
450  * within this size.
451  * </ul>
452  * </p>
453  *
454  * <p>
455  * To initiate a layout, call {@link #requestLayout}. This method is typically
456  * called by a view on itself when it believes that is can no longer fit within
457  * its current bounds.
458  * </p>
459  *
460  * <a name="Drawing"></a>
461  * <h3>Drawing</h3>
462  * <p>
463  * Drawing is handled by walking the tree and recording the drawing commands of
464  * any View that needs to update. After this, the drawing commands of the
465  * entire tree are issued to screen, clipped to the newly damaged area.
466  * </p>
467  *
468  * <p>
469  * The tree is largely recorded and drawn in order, with parents drawn before
470  * (i.e., behind) their children, with siblings drawn in the order they appear
471  * in the tree. If you set a background drawable for a View, then the View will
472  * draw it before calling back to its <code>onDraw()</code> method. The child
473  * drawing order can be overridden with
474  * {@link ViewGroup#setChildrenDrawingOrderEnabled(boolean) custom child drawing order}
475  * in a ViewGroup, and with {@link #setZ(float)} custom Z values} set on Views.
476  * </p>
477  *
478  * <p>
479  * To force a view to draw, call {@link #invalidate()}.
480  * </p>
481  *
482  * <a name="EventHandlingThreading"></a>
483  * <h3>Event Handling and Threading</h3>
484  * <p>
485  * The basic cycle of a view is as follows:
486  * <ol>
487  * <li>An event comes in and is dispatched to the appropriate view. The view
488  * handles the event and notifies any listeners.</li>
489  * <li>If in the course of processing the event, the view's bounds may need
490  * to be changed, the view will call {@link #requestLayout()}.</li>
491  * <li>Similarly, if in the course of processing the event the view's appearance
492  * may need to be changed, the view will call {@link #invalidate()}.</li>
493  * <li>If either {@link #requestLayout()} or {@link #invalidate()} were called,
494  * the framework will take care of measuring, laying out, and drawing the tree
495  * as appropriate.</li>
496  * </ol>
497  * </p>
498  *
499  * <p><em>Note: The entire view tree is single threaded. You must always be on
500  * the UI thread when calling any method on any view.</em>
501  * If you are doing work on other threads and want to update the state of a view
502  * from that thread, you should use a {@link Handler}.
503  * </p>
504  *
505  * <a name="FocusHandling"></a>
506  * <h3>Focus Handling</h3>
507  * <p>
508  * The framework will handle routine focus movement in response to user input.
509  * This includes changing the focus as views are removed or hidden, or as new
510  * views become available. Views indicate their willingness to take focus
511  * through the {@link #isFocusable} method. To change whether a view can take
512  * focus, call {@link #setFocusable(boolean)}.  When in touch mode (see notes below)
513  * views indicate whether they still would like focus via {@link #isFocusableInTouchMode}
514  * and can change this via {@link #setFocusableInTouchMode(boolean)}.
515  * </p>
516  * <p>
517  * Focus movement is based on an algorithm which finds the nearest neighbor in a
518  * given direction. In rare cases, the default algorithm may not match the
519  * intended behavior of the developer. In these situations, you can provide
520  * explicit overrides by using these XML attributes in the layout file:
521  * <pre>
522  * nextFocusDown
523  * nextFocusLeft
524  * nextFocusRight
525  * nextFocusUp
526  * </pre>
527  * </p>
528  *
529  *
530  * <p>
531  * To get a particular view to take focus, call {@link #requestFocus()}.
532  * </p>
533  *
534  * <a name="TouchMode"></a>
535  * <h3>Touch Mode</h3>
536  * <p>
537  * When a user is navigating a user interface via directional keys such as a D-pad, it is
538  * necessary to give focus to actionable items such as buttons so the user can see
539  * what will take input.  If the device has touch capabilities, however, and the user
540  * begins interacting with the interface by touching it, it is no longer necessary to
541  * always highlight, or give focus to, a particular view.  This motivates a mode
542  * for interaction named 'touch mode'.
543  * </p>
544  * <p>
545  * For a touch capable device, once the user touches the screen, the device
546  * will enter touch mode.  From this point onward, only views for which
547  * {@link #isFocusableInTouchMode} is true will be focusable, such as text editing widgets.
548  * Other views that are touchable, like buttons, will not take focus when touched; they will
549  * only fire the on click listeners.
550  * </p>
551  * <p>
552  * Any time a user hits a directional key, such as a D-pad direction, the view device will
553  * exit touch mode, and find a view to take focus, so that the user may resume interacting
554  * with the user interface without touching the screen again.
555  * </p>
556  * <p>
557  * The touch mode state is maintained across {@link android.app.Activity}s.  Call
558  * {@link #isInTouchMode} to see whether the device is currently in touch mode.
559  * </p>
560  *
561  * <a name="Scrolling"></a>
562  * <h3>Scrolling</h3>
563  * <p>
564  * The framework provides basic support for views that wish to internally
565  * scroll their content. This includes keeping track of the X and Y scroll
566  * offset as well as mechanisms for drawing scrollbars. See
567  * {@link #scrollBy(int, int)}, {@link #scrollTo(int, int)}, and
568  * {@link #awakenScrollBars()} for more details.
569  * </p>
570  *
571  * <a name="Tags"></a>
572  * <h3>Tags</h3>
573  * <p>
574  * Unlike IDs, tags are not used to identify views. Tags are essentially an
575  * extra piece of information that can be associated with a view. They are most
576  * often used as a convenience to store data related to views in the views
577  * themselves rather than by putting them in a separate structure.
578  * </p>
579  *
580  * <a name="Properties"></a>
581  * <h3>Properties</h3>
582  * <p>
583  * The View class exposes an {@link #ALPHA} property, as well as several transform-related
584  * properties, such as {@link #TRANSLATION_X} and {@link #TRANSLATION_Y}. These properties are
585  * available both in the {@link Property} form as well as in similarly-named setter/getter
586  * methods (such as {@link #setAlpha(float)} for {@link #ALPHA}). These properties can
587  * be used to set persistent state associated with these rendering-related properties on the view.
588  * The properties and methods can also be used in conjunction with
589  * {@link android.animation.Animator Animator}-based animations, described more in the
590  * <a href="#Animation">Animation</a> section.
591  * </p>
592  *
593  * <a name="Animation"></a>
594  * <h3>Animation</h3>
595  * <p>
596  * Starting with Android 3.0, the preferred way of animating views is to use the
597  * {@link android.animation} package APIs. These {@link android.animation.Animator Animator}-based
598  * classes change actual properties of the View object, such as {@link #setAlpha(float) alpha} and
599  * {@link #setTranslationX(float) translationX}. This behavior is contrasted to that of the pre-3.0
600  * {@link android.view.animation.Animation Animation}-based classes, which instead animate only
601  * how the view is drawn on the display. In particular, the {@link ViewPropertyAnimator} class
602  * makes animating these View properties particularly easy and efficient.
603  * </p>
604  * <p>
605  * Alternatively, you can use the pre-3.0 animation classes to animate how Views are rendered.
606  * You can attach an {@link Animation} object to a view using
607  * {@link #setAnimation(Animation)} or
608  * {@link #startAnimation(Animation)}. The animation can alter the scale,
609  * rotation, translation and alpha of a view over time. If the animation is
610  * attached to a view that has children, the animation will affect the entire
611  * subtree rooted by that node. When an animation is started, the framework will
612  * take care of redrawing the appropriate views until the animation completes.
613  * </p>
614  *
615  * <a name="Security"></a>
616  * <h3>Security</h3>
617  * <p>
618  * Sometimes it is essential that an application be able to verify that an action
619  * is being performed with the full knowledge and consent of the user, such as
620  * granting a permission request, making a purchase or clicking on an advertisement.
621  * Unfortunately, a malicious application could try to spoof the user into
622  * performing these actions, unaware, by concealing the intended purpose of the view.
623  * As a remedy, the framework offers a touch filtering mechanism that can be used to
624  * improve the security of views that provide access to sensitive functionality.
625  * </p><p>
626  * To enable touch filtering, call {@link #setFilterTouchesWhenObscured(boolean)} or set the
627  * android:filterTouchesWhenObscured layout attribute to true.  When enabled, the framework
628  * will discard touches that are received whenever the view's window is obscured by
629  * another visible window.  As a result, the view will not receive touches whenever a
630  * toast, dialog or other window appears above the view's window.
631  * </p><p>
632  * For more fine-grained control over security, consider overriding the
633  * {@link #onFilterTouchEventForSecurity(MotionEvent)} method to implement your own
634  * security policy. See also {@link MotionEvent#FLAG_WINDOW_IS_OBSCURED}.
635  * </p>
636  *
637  * @attr ref android.R.styleable#View_alpha
638  * @attr ref android.R.styleable#View_background
639  * @attr ref android.R.styleable#View_clickable
640  * @attr ref android.R.styleable#View_contentDescription
641  * @attr ref android.R.styleable#View_drawingCacheQuality
642  * @attr ref android.R.styleable#View_duplicateParentState
643  * @attr ref android.R.styleable#View_id
644  * @attr ref android.R.styleable#View_requiresFadingEdge
645  * @attr ref android.R.styleable#View_fadeScrollbars
646  * @attr ref android.R.styleable#View_fadingEdgeLength
647  * @attr ref android.R.styleable#View_filterTouchesWhenObscured
648  * @attr ref android.R.styleable#View_fitsSystemWindows
649  * @attr ref android.R.styleable#View_isScrollContainer
650  * @attr ref android.R.styleable#View_focusable
651  * @attr ref android.R.styleable#View_focusableInTouchMode
652  * @attr ref android.R.styleable#View_hapticFeedbackEnabled
653  * @attr ref android.R.styleable#View_keepScreenOn
654  * @attr ref android.R.styleable#View_layerType
655  * @attr ref android.R.styleable#View_layoutDirection
656  * @attr ref android.R.styleable#View_longClickable
657  * @attr ref android.R.styleable#View_minHeight
658  * @attr ref android.R.styleable#View_minWidth
659  * @attr ref android.R.styleable#View_nextFocusDown
660  * @attr ref android.R.styleable#View_nextFocusLeft
661  * @attr ref android.R.styleable#View_nextFocusRight
662  * @attr ref android.R.styleable#View_nextFocusUp
663  * @attr ref android.R.styleable#View_onClick
664  * @attr ref android.R.styleable#View_padding
665  * @attr ref android.R.styleable#View_paddingBottom
666  * @attr ref android.R.styleable#View_paddingLeft
667  * @attr ref android.R.styleable#View_paddingRight
668  * @attr ref android.R.styleable#View_paddingTop
669  * @attr ref android.R.styleable#View_paddingStart
670  * @attr ref android.R.styleable#View_paddingEnd
671  * @attr ref android.R.styleable#View_saveEnabled
672  * @attr ref android.R.styleable#View_rotation
673  * @attr ref android.R.styleable#View_rotationX
674  * @attr ref android.R.styleable#View_rotationY
675  * @attr ref android.R.styleable#View_scaleX
676  * @attr ref android.R.styleable#View_scaleY
677  * @attr ref android.R.styleable#View_scrollX
678  * @attr ref android.R.styleable#View_scrollY
679  * @attr ref android.R.styleable#View_scrollbarSize
680  * @attr ref android.R.styleable#View_scrollbarStyle
681  * @attr ref android.R.styleable#View_scrollbars
682  * @attr ref android.R.styleable#View_scrollbarDefaultDelayBeforeFade
683  * @attr ref android.R.styleable#View_scrollbarFadeDuration
684  * @attr ref android.R.styleable#View_scrollbarTrackHorizontal
685  * @attr ref android.R.styleable#View_scrollbarThumbHorizontal
686  * @attr ref android.R.styleable#View_scrollbarThumbVertical
687  * @attr ref android.R.styleable#View_scrollbarTrackVertical
688  * @attr ref android.R.styleable#View_scrollbarAlwaysDrawHorizontalTrack
689  * @attr ref android.R.styleable#View_scrollbarAlwaysDrawVerticalTrack
690  * @attr ref android.R.styleable#View_stateListAnimator
691  * @attr ref android.R.styleable#View_transitionName
692  * @attr ref android.R.styleable#View_soundEffectsEnabled
693  * @attr ref android.R.styleable#View_tag
694  * @attr ref android.R.styleable#View_textAlignment
695  * @attr ref android.R.styleable#View_textDirection
696  * @attr ref android.R.styleable#View_transformPivotX
697  * @attr ref android.R.styleable#View_transformPivotY
698  * @attr ref android.R.styleable#View_translationX
699  * @attr ref android.R.styleable#View_translationY
700  * @attr ref android.R.styleable#View_translationZ
701  * @attr ref android.R.styleable#View_visibility
702  *
703  * @see android.view.ViewGroup
704  */
705 @UiThread
706 public class View implements Drawable.Callback, KeyEvent.Callback,
707         AccessibilityEventSource {
708     private static final boolean DBG = false;
709 
710     /**
711      * The logging tag used by this class with android.util.Log.
712      */
713     protected static final String VIEW_LOG_TAG = "View";
714 
715     /**
716      * When set to true, apps will draw debugging information about their layouts.
717      *
718      * @hide
719      */
720     public static final String DEBUG_LAYOUT_PROPERTY = "debug.layout";
721 
722     /**
723      * When set to true, this view will save its attribute data.
724      *
725      * @hide
726      */
727     public static boolean mDebugViewAttributes = false;
728 
729     /**
730      * Used to mark a View that has no ID.
731      */
732     public static final int NO_ID = -1;
733 
734     /**
735      * Signals that compatibility booleans have been initialized according to
736      * target SDK versions.
737      */
738     private static boolean sCompatibilityDone = false;
739 
740     /**
741      * Use the old (broken) way of building MeasureSpecs.
742      */
743     private static boolean sUseBrokenMakeMeasureSpec = false;
744 
745     /**
746      * Always return a size of 0 for MeasureSpec values with a mode of UNSPECIFIED
747      */
748     static boolean sUseZeroUnspecifiedMeasureSpec = false;
749 
750     /**
751      * Ignore any optimizations using the measure cache.
752      */
753     private static boolean sIgnoreMeasureCache = false;
754 
755     /**
756      * This view does not want keystrokes. Use with TAKES_FOCUS_MASK when
757      * calling setFlags.
758      */
759     private static final int NOT_FOCUSABLE = 0x00000000;
760 
761     /**
762      * This view wants keystrokes. Use with TAKES_FOCUS_MASK when calling
763      * setFlags.
764      */
765     private static final int FOCUSABLE = 0x00000001;
766 
767     /**
768      * Mask for use with setFlags indicating bits used for focus.
769      */
770     private static final int FOCUSABLE_MASK = 0x00000001;
771 
772     /**
773      * This view will adjust its padding to fit sytem windows (e.g. status bar)
774      */
775     private static final int FITS_SYSTEM_WINDOWS = 0x00000002;
776 
777     /** @hide */
778     @IntDef({VISIBLE, INVISIBLE, GONE})
779     @Retention(RetentionPolicy.SOURCE)
780     public @interface Visibility {}
781 
782     /**
783      * This view is visible.
784      * Use with {@link #setVisibility} and <a href="#attr_android:visibility">{@code
785      * android:visibility}.
786      */
787     public static final int VISIBLE = 0x00000000;
788 
789     /**
790      * This view is invisible, but it still takes up space for layout purposes.
791      * Use with {@link #setVisibility} and <a href="#attr_android:visibility">{@code
792      * android:visibility}.
793      */
794     public static final int INVISIBLE = 0x00000004;
795 
796     /**
797      * This view is invisible, and it doesn't take any space for layout
798      * purposes. Use with {@link #setVisibility} and <a href="#attr_android:visibility">{@code
799      * android:visibility}.
800      */
801     public static final int GONE = 0x00000008;
802 
803     /**
804      * Mask for use with setFlags indicating bits used for visibility.
805      * {@hide}
806      */
807     static final int VISIBILITY_MASK = 0x0000000C;
808 
809     private static final int[] VISIBILITY_FLAGS = {VISIBLE, INVISIBLE, GONE};
810 
811     /**
812      * This view is enabled. Interpretation varies by subclass.
813      * Use with ENABLED_MASK when calling setFlags.
814      * {@hide}
815      */
816     static final int ENABLED = 0x00000000;
817 
818     /**
819      * This view is disabled. Interpretation varies by subclass.
820      * Use with ENABLED_MASK when calling setFlags.
821      * {@hide}
822      */
823     static final int DISABLED = 0x00000020;
824 
825    /**
826     * Mask for use with setFlags indicating bits used for indicating whether
827     * this view is enabled
828     * {@hide}
829     */
830     static final int ENABLED_MASK = 0x00000020;
831 
832     /**
833      * This view won't draw. {@link #onDraw(android.graphics.Canvas)} won't be
834      * called and further optimizations will be performed. It is okay to have
835      * this flag set and a background. Use with DRAW_MASK when calling setFlags.
836      * {@hide}
837      */
838     static final int WILL_NOT_DRAW = 0x00000080;
839 
840     /**
841      * Mask for use with setFlags indicating bits used for indicating whether
842      * this view is will draw
843      * {@hide}
844      */
845     static final int DRAW_MASK = 0x00000080;
846 
847     /**
848      * <p>This view doesn't show scrollbars.</p>
849      * {@hide}
850      */
851     static final int SCROLLBARS_NONE = 0x00000000;
852 
853     /**
854      * <p>This view shows horizontal scrollbars.</p>
855      * {@hide}
856      */
857     static final int SCROLLBARS_HORIZONTAL = 0x00000100;
858 
859     /**
860      * <p>This view shows vertical scrollbars.</p>
861      * {@hide}
862      */
863     static final int SCROLLBARS_VERTICAL = 0x00000200;
864 
865     /**
866      * <p>Mask for use with setFlags indicating bits used for indicating which
867      * scrollbars are enabled.</p>
868      * {@hide}
869      */
870     static final int SCROLLBARS_MASK = 0x00000300;
871 
872     /**
873      * Indicates that the view should filter touches when its window is obscured.
874      * Refer to the class comments for more information about this security feature.
875      * {@hide}
876      */
877     static final int FILTER_TOUCHES_WHEN_OBSCURED = 0x00000400;
878 
879     /**
880      * Set for framework elements that use FITS_SYSTEM_WINDOWS, to indicate
881      * that they are optional and should be skipped if the window has
882      * requested system UI flags that ignore those insets for layout.
883      */
884     static final int OPTIONAL_FITS_SYSTEM_WINDOWS = 0x00000800;
885 
886     /**
887      * <p>This view doesn't show fading edges.</p>
888      * {@hide}
889      */
890     static final int FADING_EDGE_NONE = 0x00000000;
891 
892     /**
893      * <p>This view shows horizontal fading edges.</p>
894      * {@hide}
895      */
896     static final int FADING_EDGE_HORIZONTAL = 0x00001000;
897 
898     /**
899      * <p>This view shows vertical fading edges.</p>
900      * {@hide}
901      */
902     static final int FADING_EDGE_VERTICAL = 0x00002000;
903 
904     /**
905      * <p>Mask for use with setFlags indicating bits used for indicating which
906      * fading edges are enabled.</p>
907      * {@hide}
908      */
909     static final int FADING_EDGE_MASK = 0x00003000;
910 
911     /**
912      * <p>Indicates this view can be clicked. When clickable, a View reacts
913      * to clicks by notifying the OnClickListener.<p>
914      * {@hide}
915      */
916     static final int CLICKABLE = 0x00004000;
917 
918     /**
919      * <p>Indicates this view is caching its drawing into a bitmap.</p>
920      * {@hide}
921      */
922     static final int DRAWING_CACHE_ENABLED = 0x00008000;
923 
924     /**
925      * <p>Indicates that no icicle should be saved for this view.<p>
926      * {@hide}
927      */
928     static final int SAVE_DISABLED = 0x000010000;
929 
930     /**
931      * <p>Mask for use with setFlags indicating bits used for the saveEnabled
932      * property.</p>
933      * {@hide}
934      */
935     static final int SAVE_DISABLED_MASK = 0x000010000;
936 
937     /**
938      * <p>Indicates that no drawing cache should ever be created for this view.<p>
939      * {@hide}
940      */
941     static final int WILL_NOT_CACHE_DRAWING = 0x000020000;
942 
943     /**
944      * <p>Indicates this view can take / keep focus when int touch mode.</p>
945      * {@hide}
946      */
947     static final int FOCUSABLE_IN_TOUCH_MODE = 0x00040000;
948 
949     /** @hide */
950     @Retention(RetentionPolicy.SOURCE)
951     @IntDef({DRAWING_CACHE_QUALITY_LOW, DRAWING_CACHE_QUALITY_HIGH, DRAWING_CACHE_QUALITY_AUTO})
952     public @interface DrawingCacheQuality {}
953 
954     /**
955      * <p>Enables low quality mode for the drawing cache.</p>
956      */
957     public static final int DRAWING_CACHE_QUALITY_LOW = 0x00080000;
958 
959     /**
960      * <p>Enables high quality mode for the drawing cache.</p>
961      */
962     public static final int DRAWING_CACHE_QUALITY_HIGH = 0x00100000;
963 
964     /**
965      * <p>Enables automatic quality mode for the drawing cache.</p>
966      */
967     public static final int DRAWING_CACHE_QUALITY_AUTO = 0x00000000;
968 
969     private static final int[] DRAWING_CACHE_QUALITY_FLAGS = {
970             DRAWING_CACHE_QUALITY_AUTO, DRAWING_CACHE_QUALITY_LOW, DRAWING_CACHE_QUALITY_HIGH
971     };
972 
973     /**
974      * <p>Mask for use with setFlags indicating bits used for the cache
975      * quality property.</p>
976      * {@hide}
977      */
978     static final int DRAWING_CACHE_QUALITY_MASK = 0x00180000;
979 
980     /**
981      * <p>
982      * Indicates this view can be long clicked. When long clickable, a View
983      * reacts to long clicks by notifying the OnLongClickListener or showing a
984      * context menu.
985      * </p>
986      * {@hide}
987      */
988     static final int LONG_CLICKABLE = 0x00200000;
989 
990     /**
991      * <p>Indicates that this view gets its drawable states from its direct parent
992      * and ignores its original internal states.</p>
993      *
994      * @hide
995      */
996     static final int DUPLICATE_PARENT_STATE = 0x00400000;
997 
998     /**
999      * <p>
1000      * Indicates this view can be context clicked. When context clickable, a View reacts to a
1001      * context click (e.g. a primary stylus button press or right mouse click) by notifying the
1002      * OnContextClickListener.
1003      * </p>
1004      * {@hide}
1005      */
1006     static final int CONTEXT_CLICKABLE = 0x00800000;
1007 
1008 
1009     /** @hide */
1010     @IntDef({
1011         SCROLLBARS_INSIDE_OVERLAY,
1012         SCROLLBARS_INSIDE_INSET,
1013         SCROLLBARS_OUTSIDE_OVERLAY,
1014         SCROLLBARS_OUTSIDE_INSET
1015     })
1016     @Retention(RetentionPolicy.SOURCE)
1017     public @interface ScrollBarStyle {}
1018 
1019     /**
1020      * The scrollbar style to display the scrollbars inside the content area,
1021      * without increasing the padding. The scrollbars will be overlaid with
1022      * translucency on the view's content.
1023      */
1024     public static final int SCROLLBARS_INSIDE_OVERLAY = 0;
1025 
1026     /**
1027      * The scrollbar style to display the scrollbars inside the padded area,
1028      * increasing the padding of the view. The scrollbars will not overlap the
1029      * content area of the view.
1030      */
1031     public static final int SCROLLBARS_INSIDE_INSET = 0x01000000;
1032 
1033     /**
1034      * The scrollbar style to display the scrollbars at the edge of the view,
1035      * without increasing the padding. The scrollbars will be overlaid with
1036      * translucency.
1037      */
1038     public static final int SCROLLBARS_OUTSIDE_OVERLAY = 0x02000000;
1039 
1040     /**
1041      * The scrollbar style to display the scrollbars at the edge of the view,
1042      * increasing the padding of the view. The scrollbars will only overlap the
1043      * background, if any.
1044      */
1045     public static final int SCROLLBARS_OUTSIDE_INSET = 0x03000000;
1046 
1047     /**
1048      * Mask to check if the scrollbar style is overlay or inset.
1049      * {@hide}
1050      */
1051     static final int SCROLLBARS_INSET_MASK = 0x01000000;
1052 
1053     /**
1054      * Mask to check if the scrollbar style is inside or outside.
1055      * {@hide}
1056      */
1057     static final int SCROLLBARS_OUTSIDE_MASK = 0x02000000;
1058 
1059     /**
1060      * Mask for scrollbar style.
1061      * {@hide}
1062      */
1063     static final int SCROLLBARS_STYLE_MASK = 0x03000000;
1064 
1065     /**
1066      * View flag indicating that the screen should remain on while the
1067      * window containing this view is visible to the user.  This effectively
1068      * takes care of automatically setting the WindowManager's
1069      * {@link WindowManager.LayoutParams#FLAG_KEEP_SCREEN_ON}.
1070      */
1071     public static final int KEEP_SCREEN_ON = 0x04000000;
1072 
1073     /**
1074      * View flag indicating whether this view should have sound effects enabled
1075      * for events such as clicking and touching.
1076      */
1077     public static final int SOUND_EFFECTS_ENABLED = 0x08000000;
1078 
1079     /**
1080      * View flag indicating whether this view should have haptic feedback
1081      * enabled for events such as long presses.
1082      */
1083     public static final int HAPTIC_FEEDBACK_ENABLED = 0x10000000;
1084 
1085     /**
1086      * <p>Indicates that the view hierarchy should stop saving state when
1087      * it reaches this view.  If state saving is initiated immediately at
1088      * the view, it will be allowed.
1089      * {@hide}
1090      */
1091     static final int PARENT_SAVE_DISABLED = 0x20000000;
1092 
1093     /**
1094      * <p>Mask for use with setFlags indicating bits used for PARENT_SAVE_DISABLED.</p>
1095      * {@hide}
1096      */
1097     static final int PARENT_SAVE_DISABLED_MASK = 0x20000000;
1098 
1099     /** @hide */
1100     @IntDef(flag = true,
1101             value = {
1102                 FOCUSABLES_ALL,
1103                 FOCUSABLES_TOUCH_MODE
1104             })
1105     @Retention(RetentionPolicy.SOURCE)
1106     public @interface FocusableMode {}
1107 
1108     /**
1109      * View flag indicating whether {@link #addFocusables(ArrayList, int, int)}
1110      * should add all focusable Views regardless if they are focusable in touch mode.
1111      */
1112     public static final int FOCUSABLES_ALL = 0x00000000;
1113 
1114     /**
1115      * View flag indicating whether {@link #addFocusables(ArrayList, int, int)}
1116      * should add only Views focusable in touch mode.
1117      */
1118     public static final int FOCUSABLES_TOUCH_MODE = 0x00000001;
1119 
1120     /** @hide */
1121     @IntDef({
1122             FOCUS_BACKWARD,
1123             FOCUS_FORWARD,
1124             FOCUS_LEFT,
1125             FOCUS_UP,
1126             FOCUS_RIGHT,
1127             FOCUS_DOWN
1128     })
1129     @Retention(RetentionPolicy.SOURCE)
1130     public @interface FocusDirection {}
1131 
1132     /** @hide */
1133     @IntDef({
1134             FOCUS_LEFT,
1135             FOCUS_UP,
1136             FOCUS_RIGHT,
1137             FOCUS_DOWN
1138     })
1139     @Retention(RetentionPolicy.SOURCE)
1140     public @interface FocusRealDirection {} // Like @FocusDirection, but without forward/backward
1141 
1142     /**
1143      * Use with {@link #focusSearch(int)}. Move focus to the previous selectable
1144      * item.
1145      */
1146     public static final int FOCUS_BACKWARD = 0x00000001;
1147 
1148     /**
1149      * Use with {@link #focusSearch(int)}. Move focus to the next selectable
1150      * item.
1151      */
1152     public static final int FOCUS_FORWARD = 0x00000002;
1153 
1154     /**
1155      * Use with {@link #focusSearch(int)}. Move focus to the left.
1156      */
1157     public static final int FOCUS_LEFT = 0x00000011;
1158 
1159     /**
1160      * Use with {@link #focusSearch(int)}. Move focus up.
1161      */
1162     public static final int FOCUS_UP = 0x00000021;
1163 
1164     /**
1165      * Use with {@link #focusSearch(int)}. Move focus to the right.
1166      */
1167     public static final int FOCUS_RIGHT = 0x00000042;
1168 
1169     /**
1170      * Use with {@link #focusSearch(int)}. Move focus down.
1171      */
1172     public static final int FOCUS_DOWN = 0x00000082;
1173 
1174     /**
1175      * Bits of {@link #getMeasuredWidthAndState()} and
1176      * {@link #getMeasuredWidthAndState()} that provide the actual measured size.
1177      */
1178     public static final int MEASURED_SIZE_MASK = 0x00ffffff;
1179 
1180     /**
1181      * Bits of {@link #getMeasuredWidthAndState()} and
1182      * {@link #getMeasuredWidthAndState()} that provide the additional state bits.
1183      */
1184     public static final int MEASURED_STATE_MASK = 0xff000000;
1185 
1186     /**
1187      * Bit shift of {@link #MEASURED_STATE_MASK} to get to the height bits
1188      * for functions that combine both width and height into a single int,
1189      * such as {@link #getMeasuredState()} and the childState argument of
1190      * {@link #resolveSizeAndState(int, int, int)}.
1191      */
1192     public static final int MEASURED_HEIGHT_STATE_SHIFT = 16;
1193 
1194     /**
1195      * Bit of {@link #getMeasuredWidthAndState()} and
1196      * {@link #getMeasuredWidthAndState()} that indicates the measured size
1197      * is smaller that the space the view would like to have.
1198      */
1199     public static final int MEASURED_STATE_TOO_SMALL = 0x01000000;
1200 
1201     /**
1202      * Base View state sets
1203      */
1204     // Singles
1205     /**
1206      * Indicates the view has no states set. States are used with
1207      * {@link android.graphics.drawable.Drawable} to change the drawing of the
1208      * view depending on its state.
1209      *
1210      * @see android.graphics.drawable.Drawable
1211      * @see #getDrawableState()
1212      */
1213     protected static final int[] EMPTY_STATE_SET;
1214     /**
1215      * Indicates the view is enabled. States are used with
1216      * {@link android.graphics.drawable.Drawable} to change the drawing of the
1217      * view depending on its state.
1218      *
1219      * @see android.graphics.drawable.Drawable
1220      * @see #getDrawableState()
1221      */
1222     protected static final int[] ENABLED_STATE_SET;
1223     /**
1224      * Indicates the view is focused. States are used with
1225      * {@link android.graphics.drawable.Drawable} to change the drawing of the
1226      * view depending on its state.
1227      *
1228      * @see android.graphics.drawable.Drawable
1229      * @see #getDrawableState()
1230      */
1231     protected static final int[] FOCUSED_STATE_SET;
1232     /**
1233      * Indicates the view is selected. States are used with
1234      * {@link android.graphics.drawable.Drawable} to change the drawing of the
1235      * view depending on its state.
1236      *
1237      * @see android.graphics.drawable.Drawable
1238      * @see #getDrawableState()
1239      */
1240     protected static final int[] SELECTED_STATE_SET;
1241     /**
1242      * Indicates the view is pressed. States are used with
1243      * {@link android.graphics.drawable.Drawable} to change the drawing of the
1244      * view depending on its state.
1245      *
1246      * @see android.graphics.drawable.Drawable
1247      * @see #getDrawableState()
1248      */
1249     protected static final int[] PRESSED_STATE_SET;
1250     /**
1251      * Indicates the view's window has focus. States are used with
1252      * {@link android.graphics.drawable.Drawable} to change the drawing of the
1253      * view depending on its state.
1254      *
1255      * @see android.graphics.drawable.Drawable
1256      * @see #getDrawableState()
1257      */
1258     protected static final int[] WINDOW_FOCUSED_STATE_SET;
1259     // Doubles
1260     /**
1261      * Indicates the view is enabled and has the focus.
1262      *
1263      * @see #ENABLED_STATE_SET
1264      * @see #FOCUSED_STATE_SET
1265      */
1266     protected static final int[] ENABLED_FOCUSED_STATE_SET;
1267     /**
1268      * Indicates the view is enabled and selected.
1269      *
1270      * @see #ENABLED_STATE_SET
1271      * @see #SELECTED_STATE_SET
1272      */
1273     protected static final int[] ENABLED_SELECTED_STATE_SET;
1274     /**
1275      * Indicates the view is enabled and that its window has focus.
1276      *
1277      * @see #ENABLED_STATE_SET
1278      * @see #WINDOW_FOCUSED_STATE_SET
1279      */
1280     protected static final int[] ENABLED_WINDOW_FOCUSED_STATE_SET;
1281     /**
1282      * Indicates the view is focused and selected.
1283      *
1284      * @see #FOCUSED_STATE_SET
1285      * @see #SELECTED_STATE_SET
1286      */
1287     protected static final int[] FOCUSED_SELECTED_STATE_SET;
1288     /**
1289      * Indicates the view has the focus and that its window has the focus.
1290      *
1291      * @see #FOCUSED_STATE_SET
1292      * @see #WINDOW_FOCUSED_STATE_SET
1293      */
1294     protected static final int[] FOCUSED_WINDOW_FOCUSED_STATE_SET;
1295     /**
1296      * Indicates the view is selected and that its window has the focus.
1297      *
1298      * @see #SELECTED_STATE_SET
1299      * @see #WINDOW_FOCUSED_STATE_SET
1300      */
1301     protected static final int[] SELECTED_WINDOW_FOCUSED_STATE_SET;
1302     // Triples
1303     /**
1304      * Indicates the view is enabled, focused and selected.
1305      *
1306      * @see #ENABLED_STATE_SET
1307      * @see #FOCUSED_STATE_SET
1308      * @see #SELECTED_STATE_SET
1309      */
1310     protected static final int[] ENABLED_FOCUSED_SELECTED_STATE_SET;
1311     /**
1312      * Indicates the view is enabled, focused and its window has the focus.
1313      *
1314      * @see #ENABLED_STATE_SET
1315      * @see #FOCUSED_STATE_SET
1316      * @see #WINDOW_FOCUSED_STATE_SET
1317      */
1318     protected static final int[] ENABLED_FOCUSED_WINDOW_FOCUSED_STATE_SET;
1319     /**
1320      * Indicates the view is enabled, selected and its window has the focus.
1321      *
1322      * @see #ENABLED_STATE_SET
1323      * @see #SELECTED_STATE_SET
1324      * @see #WINDOW_FOCUSED_STATE_SET
1325      */
1326     protected static final int[] ENABLED_SELECTED_WINDOW_FOCUSED_STATE_SET;
1327     /**
1328      * Indicates the view is focused, selected and its window has the focus.
1329      *
1330      * @see #FOCUSED_STATE_SET
1331      * @see #SELECTED_STATE_SET
1332      * @see #WINDOW_FOCUSED_STATE_SET
1333      */
1334     protected static final int[] FOCUSED_SELECTED_WINDOW_FOCUSED_STATE_SET;
1335     /**
1336      * Indicates the view is enabled, focused, selected and its window
1337      * has the focus.
1338      *
1339      * @see #ENABLED_STATE_SET
1340      * @see #FOCUSED_STATE_SET
1341      * @see #SELECTED_STATE_SET
1342      * @see #WINDOW_FOCUSED_STATE_SET
1343      */
1344     protected static final int[] ENABLED_FOCUSED_SELECTED_WINDOW_FOCUSED_STATE_SET;
1345     /**
1346      * Indicates the view is pressed and its window has the focus.
1347      *
1348      * @see #PRESSED_STATE_SET
1349      * @see #WINDOW_FOCUSED_STATE_SET
1350      */
1351     protected static final int[] PRESSED_WINDOW_FOCUSED_STATE_SET;
1352     /**
1353      * Indicates the view is pressed and selected.
1354      *
1355      * @see #PRESSED_STATE_SET
1356      * @see #SELECTED_STATE_SET
1357      */
1358     protected static final int[] PRESSED_SELECTED_STATE_SET;
1359     /**
1360      * Indicates the view is pressed, selected and its window has the focus.
1361      *
1362      * @see #PRESSED_STATE_SET
1363      * @see #SELECTED_STATE_SET
1364      * @see #WINDOW_FOCUSED_STATE_SET
1365      */
1366     protected static final int[] PRESSED_SELECTED_WINDOW_FOCUSED_STATE_SET;
1367     /**
1368      * Indicates the view is pressed and focused.
1369      *
1370      * @see #PRESSED_STATE_SET
1371      * @see #FOCUSED_STATE_SET
1372      */
1373     protected static final int[] PRESSED_FOCUSED_STATE_SET;
1374     /**
1375      * Indicates the view is pressed, focused and its window has the focus.
1376      *
1377      * @see #PRESSED_STATE_SET
1378      * @see #FOCUSED_STATE_SET
1379      * @see #WINDOW_FOCUSED_STATE_SET
1380      */
1381     protected static final int[] PRESSED_FOCUSED_WINDOW_FOCUSED_STATE_SET;
1382     /**
1383      * Indicates the view is pressed, focused and selected.
1384      *
1385      * @see #PRESSED_STATE_SET
1386      * @see #SELECTED_STATE_SET
1387      * @see #FOCUSED_STATE_SET
1388      */
1389     protected static final int[] PRESSED_FOCUSED_SELECTED_STATE_SET;
1390     /**
1391      * Indicates the view is pressed, focused, selected and its window has the focus.
1392      *
1393      * @see #PRESSED_STATE_SET
1394      * @see #FOCUSED_STATE_SET
1395      * @see #SELECTED_STATE_SET
1396      * @see #WINDOW_FOCUSED_STATE_SET
1397      */
1398     protected static final int[] PRESSED_FOCUSED_SELECTED_WINDOW_FOCUSED_STATE_SET;
1399     /**
1400      * Indicates the view is pressed and enabled.
1401      *
1402      * @see #PRESSED_STATE_SET
1403      * @see #ENABLED_STATE_SET
1404      */
1405     protected static final int[] PRESSED_ENABLED_STATE_SET;
1406     /**
1407      * Indicates the view is pressed, enabled and its window has the focus.
1408      *
1409      * @see #PRESSED_STATE_SET
1410      * @see #ENABLED_STATE_SET
1411      * @see #WINDOW_FOCUSED_STATE_SET
1412      */
1413     protected static final int[] PRESSED_ENABLED_WINDOW_FOCUSED_STATE_SET;
1414     /**
1415      * Indicates the view is pressed, enabled and selected.
1416      *
1417      * @see #PRESSED_STATE_SET
1418      * @see #ENABLED_STATE_SET
1419      * @see #SELECTED_STATE_SET
1420      */
1421     protected static final int[] PRESSED_ENABLED_SELECTED_STATE_SET;
1422     /**
1423      * Indicates the view is pressed, enabled, selected and its window has the
1424      * focus.
1425      *
1426      * @see #PRESSED_STATE_SET
1427      * @see #ENABLED_STATE_SET
1428      * @see #SELECTED_STATE_SET
1429      * @see #WINDOW_FOCUSED_STATE_SET
1430      */
1431     protected static final int[] PRESSED_ENABLED_SELECTED_WINDOW_FOCUSED_STATE_SET;
1432     /**
1433      * Indicates the view is pressed, enabled and focused.
1434      *
1435      * @see #PRESSED_STATE_SET
1436      * @see #ENABLED_STATE_SET
1437      * @see #FOCUSED_STATE_SET
1438      */
1439     protected static final int[] PRESSED_ENABLED_FOCUSED_STATE_SET;
1440     /**
1441      * Indicates the view is pressed, enabled, focused and its window has the
1442      * focus.
1443      *
1444      * @see #PRESSED_STATE_SET
1445      * @see #ENABLED_STATE_SET
1446      * @see #FOCUSED_STATE_SET
1447      * @see #WINDOW_FOCUSED_STATE_SET
1448      */
1449     protected static final int[] PRESSED_ENABLED_FOCUSED_WINDOW_FOCUSED_STATE_SET;
1450     /**
1451      * Indicates the view is pressed, enabled, focused and selected.
1452      *
1453      * @see #PRESSED_STATE_SET
1454      * @see #ENABLED_STATE_SET
1455      * @see #SELECTED_STATE_SET
1456      * @see #FOCUSED_STATE_SET
1457      */
1458     protected static final int[] PRESSED_ENABLED_FOCUSED_SELECTED_STATE_SET;
1459     /**
1460      * Indicates the view is pressed, enabled, focused, selected and its window
1461      * has the focus.
1462      *
1463      * @see #PRESSED_STATE_SET
1464      * @see #ENABLED_STATE_SET
1465      * @see #SELECTED_STATE_SET
1466      * @see #FOCUSED_STATE_SET
1467      * @see #WINDOW_FOCUSED_STATE_SET
1468      */
1469     protected static final int[] PRESSED_ENABLED_FOCUSED_SELECTED_WINDOW_FOCUSED_STATE_SET;
1470 
1471     static {
1472         EMPTY_STATE_SET = StateSet.get(0);
1473 
1474         WINDOW_FOCUSED_STATE_SET = StateSet.get(StateSet.VIEW_STATE_WINDOW_FOCUSED);
1475 
1476         SELECTED_STATE_SET = StateSet.get(StateSet.VIEW_STATE_SELECTED);
1477         SELECTED_WINDOW_FOCUSED_STATE_SET = StateSet.get(
1478                 StateSet.VIEW_STATE_WINDOW_FOCUSED | StateSet.VIEW_STATE_SELECTED);
1479 
1480         FOCUSED_STATE_SET = StateSet.get(StateSet.VIEW_STATE_FOCUSED);
1481         FOCUSED_WINDOW_FOCUSED_STATE_SET = StateSet.get(
1482                 StateSet.VIEW_STATE_WINDOW_FOCUSED | StateSet.VIEW_STATE_FOCUSED);
1483         FOCUSED_SELECTED_STATE_SET = StateSet.get(
1484                 StateSet.VIEW_STATE_SELECTED | StateSet.VIEW_STATE_FOCUSED);
1485         FOCUSED_SELECTED_WINDOW_FOCUSED_STATE_SET = StateSet.get(
1486                 StateSet.VIEW_STATE_WINDOW_FOCUSED | StateSet.VIEW_STATE_SELECTED
1487                         | StateSet.VIEW_STATE_FOCUSED);
1488 
1489         ENABLED_STATE_SET = StateSet.get(StateSet.VIEW_STATE_ENABLED);
1490         ENABLED_WINDOW_FOCUSED_STATE_SET = StateSet.get(
1491                 StateSet.VIEW_STATE_WINDOW_FOCUSED | StateSet.VIEW_STATE_ENABLED);
1492         ENABLED_SELECTED_STATE_SET = StateSet.get(
1493                 StateSet.VIEW_STATE_SELECTED | StateSet.VIEW_STATE_ENABLED);
1494         ENABLED_SELECTED_WINDOW_FOCUSED_STATE_SET = StateSet.get(
1495                 StateSet.VIEW_STATE_WINDOW_FOCUSED | StateSet.VIEW_STATE_SELECTED
1496                         | StateSet.VIEW_STATE_ENABLED);
1497         ENABLED_FOCUSED_STATE_SET = StateSet.get(
1498                 StateSet.VIEW_STATE_FOCUSED | StateSet.VIEW_STATE_ENABLED);
1499         ENABLED_FOCUSED_WINDOW_FOCUSED_STATE_SET = StateSet.get(
1500                 StateSet.VIEW_STATE_WINDOW_FOCUSED | StateSet.VIEW_STATE_FOCUSED
1501                         | StateSet.VIEW_STATE_ENABLED);
1502         ENABLED_FOCUSED_SELECTED_STATE_SET = StateSet.get(
1503                 StateSet.VIEW_STATE_SELECTED | StateSet.VIEW_STATE_FOCUSED
1504                         | StateSet.VIEW_STATE_ENABLED);
1505         ENABLED_FOCUSED_SELECTED_WINDOW_FOCUSED_STATE_SET = StateSet.get(
1506                 StateSet.VIEW_STATE_WINDOW_FOCUSED | StateSet.VIEW_STATE_SELECTED
1507                         | StateSet.VIEW_STATE_FOCUSED| StateSet.VIEW_STATE_ENABLED);
1508 
1509         PRESSED_STATE_SET = StateSet.get(StateSet.VIEW_STATE_PRESSED);
1510         PRESSED_WINDOW_FOCUSED_STATE_SET = StateSet.get(
1511                 StateSet.VIEW_STATE_WINDOW_FOCUSED | StateSet.VIEW_STATE_PRESSED);
1512         PRESSED_SELECTED_STATE_SET = StateSet.get(
1513                 StateSet.VIEW_STATE_SELECTED | StateSet.VIEW_STATE_PRESSED);
1514         PRESSED_SELECTED_WINDOW_FOCUSED_STATE_SET = StateSet.get(
1515                 StateSet.VIEW_STATE_WINDOW_FOCUSED | StateSet.VIEW_STATE_SELECTED
1516                         | StateSet.VIEW_STATE_PRESSED);
1517         PRESSED_FOCUSED_STATE_SET = StateSet.get(
1518                 StateSet.VIEW_STATE_FOCUSED | StateSet.VIEW_STATE_PRESSED);
1519         PRESSED_FOCUSED_WINDOW_FOCUSED_STATE_SET = StateSet.get(
1520                 StateSet.VIEW_STATE_WINDOW_FOCUSED | StateSet.VIEW_STATE_FOCUSED
1521                         | StateSet.VIEW_STATE_PRESSED);
1522         PRESSED_FOCUSED_SELECTED_STATE_SET = StateSet.get(
1523                 StateSet.VIEW_STATE_SELECTED | StateSet.VIEW_STATE_FOCUSED
1524                         | StateSet.VIEW_STATE_PRESSED);
1525         PRESSED_FOCUSED_SELECTED_WINDOW_FOCUSED_STATE_SET = StateSet.get(
1526                 StateSet.VIEW_STATE_WINDOW_FOCUSED | StateSet.VIEW_STATE_SELECTED
1527                         | StateSet.VIEW_STATE_FOCUSED | StateSet.VIEW_STATE_PRESSED);
1528         PRESSED_ENABLED_STATE_SET = StateSet.get(
1529                 StateSet.VIEW_STATE_ENABLED | StateSet.VIEW_STATE_PRESSED);
1530         PRESSED_ENABLED_WINDOW_FOCUSED_STATE_SET = StateSet.get(
1531                 StateSet.VIEW_STATE_WINDOW_FOCUSED | StateSet.VIEW_STATE_ENABLED
1532                         | StateSet.VIEW_STATE_PRESSED);
1533         PRESSED_ENABLED_SELECTED_STATE_SET = StateSet.get(
1534                 StateSet.VIEW_STATE_SELECTED | StateSet.VIEW_STATE_ENABLED
1535                         | StateSet.VIEW_STATE_PRESSED);
1536         PRESSED_ENABLED_SELECTED_WINDOW_FOCUSED_STATE_SET = StateSet.get(
1537                 StateSet.VIEW_STATE_WINDOW_FOCUSED | StateSet.VIEW_STATE_SELECTED
1538                         | StateSet.VIEW_STATE_ENABLED | StateSet.VIEW_STATE_PRESSED);
1539         PRESSED_ENABLED_FOCUSED_STATE_SET = StateSet.get(
1540                 StateSet.VIEW_STATE_FOCUSED | StateSet.VIEW_STATE_ENABLED
1541                         | StateSet.VIEW_STATE_PRESSED);
1542         PRESSED_ENABLED_FOCUSED_WINDOW_FOCUSED_STATE_SET = StateSet.get(
1543                 StateSet.VIEW_STATE_WINDOW_FOCUSED | StateSet.VIEW_STATE_FOCUSED
1544                         | StateSet.VIEW_STATE_ENABLED | StateSet.VIEW_STATE_PRESSED);
1545         PRESSED_ENABLED_FOCUSED_SELECTED_STATE_SET = StateSet.get(
1546                 StateSet.VIEW_STATE_SELECTED | StateSet.VIEW_STATE_FOCUSED
1547                         | StateSet.VIEW_STATE_ENABLED | StateSet.VIEW_STATE_PRESSED);
1548         PRESSED_ENABLED_FOCUSED_SELECTED_WINDOW_FOCUSED_STATE_SET = StateSet.get(
1549                 StateSet.VIEW_STATE_WINDOW_FOCUSED | StateSet.VIEW_STATE_SELECTED
1550                         | StateSet.VIEW_STATE_FOCUSED| StateSet.VIEW_STATE_ENABLED
1551                         | StateSet.VIEW_STATE_PRESSED);
1552     }
1553 
1554     /**
1555      * Accessibility event types that are dispatched for text population.
1556      */
1557     private static final int POPULATING_ACCESSIBILITY_EVENT_TYPES =
1558             AccessibilityEvent.TYPE_VIEW_CLICKED
1559             | AccessibilityEvent.TYPE_VIEW_LONG_CLICKED
1560             | AccessibilityEvent.TYPE_VIEW_SELECTED
1561             | AccessibilityEvent.TYPE_VIEW_FOCUSED
1562             | AccessibilityEvent.TYPE_WINDOW_STATE_CHANGED
1563             | AccessibilityEvent.TYPE_VIEW_HOVER_ENTER
1564             | AccessibilityEvent.TYPE_VIEW_HOVER_EXIT
1565             | AccessibilityEvent.TYPE_VIEW_TEXT_CHANGED
1566             | AccessibilityEvent.TYPE_VIEW_TEXT_SELECTION_CHANGED
1567             | AccessibilityEvent.TYPE_VIEW_ACCESSIBILITY_FOCUSED
1568             | AccessibilityEvent.TYPE_VIEW_TEXT_TRAVERSED_AT_MOVEMENT_GRANULARITY;
1569 
1570     /**
1571      * Temporary Rect currently for use in setBackground().  This will probably
1572      * be extended in the future to hold our own class with more than just
1573      * a Rect. :)
1574      */
1575     static final ThreadLocal<Rect> sThreadLocal = new ThreadLocal<Rect>();
1576 
1577     /**
1578      * Map used to store views' tags.
1579      */
1580     private SparseArray<Object> mKeyedTags;
1581 
1582     /**
1583      * The next available accessibility id.
1584      */
1585     private static int sNextAccessibilityViewId;
1586 
1587     /**
1588      * The animation currently associated with this view.
1589      * @hide
1590      */
1591     protected Animation mCurrentAnimation = null;
1592 
1593     /**
1594      * Width as measured during measure pass.
1595      * {@hide}
1596      */
1597     @ViewDebug.ExportedProperty(category = "measurement")
1598     int mMeasuredWidth;
1599 
1600     /**
1601      * Height as measured during measure pass.
1602      * {@hide}
1603      */
1604     @ViewDebug.ExportedProperty(category = "measurement")
1605     int mMeasuredHeight;
1606 
1607     /**
1608      * Flag to indicate that this view was marked INVALIDATED, or had its display list
1609      * invalidated, prior to the current drawing iteration. If true, the view must re-draw
1610      * its display list. This flag, used only when hw accelerated, allows us to clear the
1611      * flag while retaining this information until it's needed (at getDisplayList() time and
1612      * in drawChild(), when we decide to draw a view's children's display lists into our own).
1613      *
1614      * {@hide}
1615      */
1616     boolean mRecreateDisplayList = false;
1617 
1618     /**
1619      * The view's identifier.
1620      * {@hide}
1621      *
1622      * @see #setId(int)
1623      * @see #getId()
1624      */
1625     @IdRes
1626     @ViewDebug.ExportedProperty(resolveId = true)
1627     int mID = NO_ID;
1628 
1629     /**
1630      * The stable ID of this view for accessibility purposes.
1631      */
1632     int mAccessibilityViewId = NO_ID;
1633 
1634     private int mAccessibilityCursorPosition = ACCESSIBILITY_CURSOR_POSITION_UNDEFINED;
1635 
1636     SendViewStateChangedAccessibilityEvent mSendViewStateChangedAccessibilityEvent;
1637 
1638     /**
1639      * The view's tag.
1640      * {@hide}
1641      *
1642      * @see #setTag(Object)
1643      * @see #getTag()
1644      */
1645     protected Object mTag = null;
1646 
1647     // for mPrivateFlags:
1648     /** {@hide} */
1649     static final int PFLAG_WANTS_FOCUS                 = 0x00000001;
1650     /** {@hide} */
1651     static final int PFLAG_FOCUSED                     = 0x00000002;
1652     /** {@hide} */
1653     static final int PFLAG_SELECTED                    = 0x00000004;
1654     /** {@hide} */
1655     static final int PFLAG_IS_ROOT_NAMESPACE           = 0x00000008;
1656     /** {@hide} */
1657     static final int PFLAG_HAS_BOUNDS                  = 0x00000010;
1658     /** {@hide} */
1659     static final int PFLAG_DRAWN                       = 0x00000020;
1660     /**
1661      * When this flag is set, this view is running an animation on behalf of its
1662      * children and should therefore not cancel invalidate requests, even if they
1663      * lie outside of this view's bounds.
1664      *
1665      * {@hide}
1666      */
1667     static final int PFLAG_DRAW_ANIMATION              = 0x00000040;
1668     /** {@hide} */
1669     static final int PFLAG_SKIP_DRAW                   = 0x00000080;
1670     /** {@hide} */
1671     static final int PFLAG_REQUEST_TRANSPARENT_REGIONS = 0x00000200;
1672     /** {@hide} */
1673     static final int PFLAG_DRAWABLE_STATE_DIRTY        = 0x00000400;
1674     /** {@hide} */
1675     static final int PFLAG_MEASURED_DIMENSION_SET      = 0x00000800;
1676     /** {@hide} */
1677     static final int PFLAG_FORCE_LAYOUT                = 0x00001000;
1678     /** {@hide} */
1679     static final int PFLAG_LAYOUT_REQUIRED             = 0x00002000;
1680 
1681     private static final int PFLAG_PRESSED             = 0x00004000;
1682 
1683     /** {@hide} */
1684     static final int PFLAG_DRAWING_CACHE_VALID         = 0x00008000;
1685     /**
1686      * Flag used to indicate that this view should be drawn once more (and only once
1687      * more) after its animation has completed.
1688      * {@hide}
1689      */
1690     static final int PFLAG_ANIMATION_STARTED           = 0x00010000;
1691 
1692     private static final int PFLAG_SAVE_STATE_CALLED   = 0x00020000;
1693 
1694     /**
1695      * Indicates that the View returned true when onSetAlpha() was called and that
1696      * the alpha must be restored.
1697      * {@hide}
1698      */
1699     static final int PFLAG_ALPHA_SET                   = 0x00040000;
1700 
1701     /**
1702      * Set by {@link #setScrollContainer(boolean)}.
1703      */
1704     static final int PFLAG_SCROLL_CONTAINER            = 0x00080000;
1705 
1706     /**
1707      * Set by {@link #setScrollContainer(boolean)}.
1708      */
1709     static final int PFLAG_SCROLL_CONTAINER_ADDED      = 0x00100000;
1710 
1711     /**
1712      * View flag indicating whether this view was invalidated (fully or partially.)
1713      *
1714      * @hide
1715      */
1716     static final int PFLAG_DIRTY                       = 0x00200000;
1717 
1718     /**
1719      * View flag indicating whether this view was invalidated by an opaque
1720      * invalidate request.
1721      *
1722      * @hide
1723      */
1724     static final int PFLAG_DIRTY_OPAQUE                = 0x00400000;
1725 
1726     /**
1727      * Mask for {@link #PFLAG_DIRTY} and {@link #PFLAG_DIRTY_OPAQUE}.
1728      *
1729      * @hide
1730      */
1731     static final int PFLAG_DIRTY_MASK                  = 0x00600000;
1732 
1733     /**
1734      * Indicates whether the background is opaque.
1735      *
1736      * @hide
1737      */
1738     static final int PFLAG_OPAQUE_BACKGROUND           = 0x00800000;
1739 
1740     /**
1741      * Indicates whether the scrollbars are opaque.
1742      *
1743      * @hide
1744      */
1745     static final int PFLAG_OPAQUE_SCROLLBARS           = 0x01000000;
1746 
1747     /**
1748      * Indicates whether the view is opaque.
1749      *
1750      * @hide
1751      */
1752     static final int PFLAG_OPAQUE_MASK                 = 0x01800000;
1753 
1754     /**
1755      * Indicates a prepressed state;
1756      * the short time between ACTION_DOWN and recognizing
1757      * a 'real' press. Prepressed is used to recognize quick taps
1758      * even when they are shorter than ViewConfiguration.getTapTimeout().
1759      *
1760      * @hide
1761      */
1762     private static final int PFLAG_PREPRESSED          = 0x02000000;
1763 
1764     /**
1765      * Indicates whether the view is temporarily detached.
1766      *
1767      * @hide
1768      */
1769     static final int PFLAG_CANCEL_NEXT_UP_EVENT        = 0x04000000;
1770 
1771     /**
1772      * Indicates that we should awaken scroll bars once attached
1773      *
1774      * PLEASE NOTE: This flag is now unused as we now send onVisibilityChanged
1775      * during window attachment and it is no longer needed. Feel free to repurpose it.
1776      *
1777      * @hide
1778      */
1779     private static final int PFLAG_AWAKEN_SCROLL_BARS_ON_ATTACH = 0x08000000;
1780 
1781     /**
1782      * Indicates that the view has received HOVER_ENTER.  Cleared on HOVER_EXIT.
1783      * @hide
1784      */
1785     private static final int PFLAG_HOVERED             = 0x10000000;
1786 
1787     /**
1788      * no longer needed, should be reused
1789      */
1790     private static final int PFLAG_DOES_NOTHING_REUSE_PLEASE = 0x20000000;
1791 
1792     /** {@hide} */
1793     static final int PFLAG_ACTIVATED                   = 0x40000000;
1794 
1795     /**
1796      * Indicates that this view was specifically invalidated, not just dirtied because some
1797      * child view was invalidated. The flag is used to determine when we need to recreate
1798      * a view's display list (as opposed to just returning a reference to its existing
1799      * display list).
1800      *
1801      * @hide
1802      */
1803     static final int PFLAG_INVALIDATED                 = 0x80000000;
1804 
1805     /**
1806      * Masks for mPrivateFlags2, as generated by dumpFlags():
1807      *
1808      * |-------|-------|-------|-------|
1809      *                                 1 PFLAG2_DRAG_CAN_ACCEPT
1810      *                                1  PFLAG2_DRAG_HOVERED
1811      *                              11   PFLAG2_LAYOUT_DIRECTION_MASK
1812      *                             1     PFLAG2_LAYOUT_DIRECTION_RESOLVED_RTL
1813      *                            1      PFLAG2_LAYOUT_DIRECTION_RESOLVED
1814      *                            11     PFLAG2_LAYOUT_DIRECTION_RESOLVED_MASK
1815      *                           1       PFLAG2_TEXT_DIRECTION_FLAGS[1]
1816      *                          1        PFLAG2_TEXT_DIRECTION_FLAGS[2]
1817      *                          11       PFLAG2_TEXT_DIRECTION_FLAGS[3]
1818      *                         1         PFLAG2_TEXT_DIRECTION_FLAGS[4]
1819      *                         1 1       PFLAG2_TEXT_DIRECTION_FLAGS[5]
1820      *                         11        PFLAG2_TEXT_DIRECTION_FLAGS[6]
1821      *                         111       PFLAG2_TEXT_DIRECTION_FLAGS[7]
1822      *                         111       PFLAG2_TEXT_DIRECTION_MASK
1823      *                        1          PFLAG2_TEXT_DIRECTION_RESOLVED
1824      *                       1           PFLAG2_TEXT_DIRECTION_RESOLVED_DEFAULT
1825      *                     111           PFLAG2_TEXT_DIRECTION_RESOLVED_MASK
1826      *                    1              PFLAG2_TEXT_ALIGNMENT_FLAGS[1]
1827      *                   1               PFLAG2_TEXT_ALIGNMENT_FLAGS[2]
1828      *                   11              PFLAG2_TEXT_ALIGNMENT_FLAGS[3]
1829      *                  1                PFLAG2_TEXT_ALIGNMENT_FLAGS[4]
1830      *                  1 1              PFLAG2_TEXT_ALIGNMENT_FLAGS[5]
1831      *                  11               PFLAG2_TEXT_ALIGNMENT_FLAGS[6]
1832      *                  111              PFLAG2_TEXT_ALIGNMENT_MASK
1833      *                 1                 PFLAG2_TEXT_ALIGNMENT_RESOLVED
1834      *                1                  PFLAG2_TEXT_ALIGNMENT_RESOLVED_DEFAULT
1835      *              111                  PFLAG2_TEXT_ALIGNMENT_RESOLVED_MASK
1836      *           111                     PFLAG2_IMPORTANT_FOR_ACCESSIBILITY_MASK
1837      *         11                        PFLAG2_ACCESSIBILITY_LIVE_REGION_MASK
1838      *       1                           PFLAG2_ACCESSIBILITY_FOCUSED
1839      *      1                            PFLAG2_SUBTREE_ACCESSIBILITY_STATE_CHANGED
1840      *     1                             PFLAG2_VIEW_QUICK_REJECTED
1841      *    1                              PFLAG2_PADDING_RESOLVED
1842      *   1                               PFLAG2_DRAWABLE_RESOLVED
1843      *  1                                PFLAG2_HAS_TRANSIENT_STATE
1844      * |-------|-------|-------|-------|
1845      */
1846 
1847     /**
1848      * Indicates that this view has reported that it can accept the current drag's content.
1849      * Cleared when the drag operation concludes.
1850      * @hide
1851      */
1852     static final int PFLAG2_DRAG_CAN_ACCEPT            = 0x00000001;
1853 
1854     /**
1855      * Indicates that this view is currently directly under the drag location in a
1856      * drag-and-drop operation involving content that it can accept.  Cleared when
1857      * the drag exits the view, or when the drag operation concludes.
1858      * @hide
1859      */
1860     static final int PFLAG2_DRAG_HOVERED               = 0x00000002;
1861 
1862     /** @hide */
1863     @IntDef({
1864         LAYOUT_DIRECTION_LTR,
1865         LAYOUT_DIRECTION_RTL,
1866         LAYOUT_DIRECTION_INHERIT,
1867         LAYOUT_DIRECTION_LOCALE
1868     })
1869     @Retention(RetentionPolicy.SOURCE)
1870     // Not called LayoutDirection to avoid conflict with android.util.LayoutDirection
1871     public @interface LayoutDir {}
1872 
1873     /** @hide */
1874     @IntDef({
1875         LAYOUT_DIRECTION_LTR,
1876         LAYOUT_DIRECTION_RTL
1877     })
1878     @Retention(RetentionPolicy.SOURCE)
1879     public @interface ResolvedLayoutDir {}
1880 
1881     /**
1882      * A flag to indicate that the layout direction of this view has not been defined yet.
1883      * @hide
1884      */
1885     public static final int LAYOUT_DIRECTION_UNDEFINED = LayoutDirection.UNDEFINED;
1886 
1887     /**
1888      * Horizontal layout direction of this view is from Left to Right.
1889      * Use with {@link #setLayoutDirection}.
1890      */
1891     public static final int LAYOUT_DIRECTION_LTR = LayoutDirection.LTR;
1892 
1893     /**
1894      * Horizontal layout direction of this view is from Right to Left.
1895      * Use with {@link #setLayoutDirection}.
1896      */
1897     public static final int LAYOUT_DIRECTION_RTL = LayoutDirection.RTL;
1898 
1899     /**
1900      * Horizontal layout direction of this view is inherited from its parent.
1901      * Use with {@link #setLayoutDirection}.
1902      */
1903     public static final int LAYOUT_DIRECTION_INHERIT = LayoutDirection.INHERIT;
1904 
1905     /**
1906      * Horizontal layout direction of this view is from deduced from the default language
1907      * script for the locale. Use with {@link #setLayoutDirection}.
1908      */
1909     public static final int LAYOUT_DIRECTION_LOCALE = LayoutDirection.LOCALE;
1910 
1911     /**
1912      * Bit shift to get the horizontal layout direction. (bits after DRAG_HOVERED)
1913      * @hide
1914      */
1915     static final int PFLAG2_LAYOUT_DIRECTION_MASK_SHIFT = 2;
1916 
1917     /**
1918      * Mask for use with private flags indicating bits used for horizontal layout direction.
1919      * @hide
1920      */
1921     static final int PFLAG2_LAYOUT_DIRECTION_MASK = 0x00000003 << PFLAG2_LAYOUT_DIRECTION_MASK_SHIFT;
1922 
1923     /**
1924      * Indicates whether the view horizontal layout direction has been resolved and drawn to the
1925      * right-to-left direction.
1926      * @hide
1927      */
1928     static final int PFLAG2_LAYOUT_DIRECTION_RESOLVED_RTL = 4 << PFLAG2_LAYOUT_DIRECTION_MASK_SHIFT;
1929 
1930     /**
1931      * Indicates whether the view horizontal layout direction has been resolved.
1932      * @hide
1933      */
1934     static final int PFLAG2_LAYOUT_DIRECTION_RESOLVED = 8 << PFLAG2_LAYOUT_DIRECTION_MASK_SHIFT;
1935 
1936     /**
1937      * Mask for use with private flags indicating bits used for resolved horizontal layout direction.
1938      * @hide
1939      */
1940     static final int PFLAG2_LAYOUT_DIRECTION_RESOLVED_MASK = 0x0000000C
1941             << PFLAG2_LAYOUT_DIRECTION_MASK_SHIFT;
1942 
1943     /*
1944      * Array of horizontal layout direction flags for mapping attribute "layoutDirection" to correct
1945      * flag value.
1946      * @hide
1947      */
1948     private static final int[] LAYOUT_DIRECTION_FLAGS = {
1949             LAYOUT_DIRECTION_LTR,
1950             LAYOUT_DIRECTION_RTL,
1951             LAYOUT_DIRECTION_INHERIT,
1952             LAYOUT_DIRECTION_LOCALE
1953     };
1954 
1955     /**
1956      * Default horizontal layout direction.
1957      */
1958     private static final int LAYOUT_DIRECTION_DEFAULT = LAYOUT_DIRECTION_INHERIT;
1959 
1960     /**
1961      * Default horizontal layout direction.
1962      * @hide
1963      */
1964     static final int LAYOUT_DIRECTION_RESOLVED_DEFAULT = LAYOUT_DIRECTION_LTR;
1965 
1966     /**
1967      * Text direction is inherited through {@link ViewGroup}
1968      */
1969     public static final int TEXT_DIRECTION_INHERIT = 0;
1970 
1971     /**
1972      * Text direction is using "first strong algorithm". The first strong directional character
1973      * determines the paragraph direction. If there is no strong directional character, the
1974      * paragraph direction is the view's resolved layout direction.
1975      */
1976     public static final int TEXT_DIRECTION_FIRST_STRONG = 1;
1977 
1978     /**
1979      * Text direction is using "any-RTL" algorithm. The paragraph direction is RTL if it contains
1980      * any strong RTL character, otherwise it is LTR if it contains any strong LTR characters.
1981      * If there are neither, the paragraph direction is the view's resolved layout direction.
1982      */
1983     public static final int TEXT_DIRECTION_ANY_RTL = 2;
1984 
1985     /**
1986      * Text direction is forced to LTR.
1987      */
1988     public static final int TEXT_DIRECTION_LTR = 3;
1989 
1990     /**
1991      * Text direction is forced to RTL.
1992      */
1993     public static final int TEXT_DIRECTION_RTL = 4;
1994 
1995     /**
1996      * Text direction is coming from the system Locale.
1997      */
1998     public static final int TEXT_DIRECTION_LOCALE = 5;
1999 
2000     /**
2001      * Text direction is using "first strong algorithm". The first strong directional character
2002      * determines the paragraph direction. If there is no strong directional character, the
2003      * paragraph direction is LTR.
2004      */
2005     public static final int TEXT_DIRECTION_FIRST_STRONG_LTR = 6;
2006 
2007     /**
2008      * Text direction is using "first strong algorithm". The first strong directional character
2009      * determines the paragraph direction. If there is no strong directional character, the
2010      * paragraph direction is RTL.
2011      */
2012     public static final int TEXT_DIRECTION_FIRST_STRONG_RTL = 7;
2013 
2014     /**
2015      * Default text direction is inherited
2016      */
2017     private static final int TEXT_DIRECTION_DEFAULT = TEXT_DIRECTION_INHERIT;
2018 
2019     /**
2020      * Default resolved text direction
2021      * @hide
2022      */
2023     static final int TEXT_DIRECTION_RESOLVED_DEFAULT = TEXT_DIRECTION_FIRST_STRONG;
2024 
2025     /**
2026      * Bit shift to get the horizontal layout direction. (bits after LAYOUT_DIRECTION_RESOLVED)
2027      * @hide
2028      */
2029     static final int PFLAG2_TEXT_DIRECTION_MASK_SHIFT = 6;
2030 
2031     /**
2032      * Mask for use with private flags indicating bits used for text direction.
2033      * @hide
2034      */
2035     static final int PFLAG2_TEXT_DIRECTION_MASK = 0x00000007
2036             << PFLAG2_TEXT_DIRECTION_MASK_SHIFT;
2037 
2038     /**
2039      * Array of text direction flags for mapping attribute "textDirection" to correct
2040      * flag value.
2041      * @hide
2042      */
2043     private static final int[] PFLAG2_TEXT_DIRECTION_FLAGS = {
2044             TEXT_DIRECTION_INHERIT << PFLAG2_TEXT_DIRECTION_MASK_SHIFT,
2045             TEXT_DIRECTION_FIRST_STRONG << PFLAG2_TEXT_DIRECTION_MASK_SHIFT,
2046             TEXT_DIRECTION_ANY_RTL << PFLAG2_TEXT_DIRECTION_MASK_SHIFT,
2047             TEXT_DIRECTION_LTR << PFLAG2_TEXT_DIRECTION_MASK_SHIFT,
2048             TEXT_DIRECTION_RTL << PFLAG2_TEXT_DIRECTION_MASK_SHIFT,
2049             TEXT_DIRECTION_LOCALE << PFLAG2_TEXT_DIRECTION_MASK_SHIFT,
2050             TEXT_DIRECTION_FIRST_STRONG_LTR << PFLAG2_TEXT_DIRECTION_MASK_SHIFT,
2051             TEXT_DIRECTION_FIRST_STRONG_RTL << PFLAG2_TEXT_DIRECTION_MASK_SHIFT
2052     };
2053 
2054     /**
2055      * Indicates whether the view text direction has been resolved.
2056      * @hide
2057      */
2058     static final int PFLAG2_TEXT_DIRECTION_RESOLVED = 0x00000008
2059             << PFLAG2_TEXT_DIRECTION_MASK_SHIFT;
2060 
2061     /**
2062      * Bit shift to get the horizontal layout direction. (bits after DRAG_HOVERED)
2063      * @hide
2064      */
2065     static final int PFLAG2_TEXT_DIRECTION_RESOLVED_MASK_SHIFT = 10;
2066 
2067     /**
2068      * Mask for use with private flags indicating bits used for resolved text direction.
2069      * @hide
2070      */
2071     static final int PFLAG2_TEXT_DIRECTION_RESOLVED_MASK = 0x00000007
2072             << PFLAG2_TEXT_DIRECTION_RESOLVED_MASK_SHIFT;
2073 
2074     /**
2075      * Indicates whether the view text direction has been resolved to the "first strong" heuristic.
2076      * @hide
2077      */
2078     static final int PFLAG2_TEXT_DIRECTION_RESOLVED_DEFAULT =
2079             TEXT_DIRECTION_RESOLVED_DEFAULT << PFLAG2_TEXT_DIRECTION_RESOLVED_MASK_SHIFT;
2080 
2081     /** @hide */
2082     @IntDef({
2083         TEXT_ALIGNMENT_INHERIT,
2084         TEXT_ALIGNMENT_GRAVITY,
2085         TEXT_ALIGNMENT_CENTER,
2086         TEXT_ALIGNMENT_TEXT_START,
2087         TEXT_ALIGNMENT_TEXT_END,
2088         TEXT_ALIGNMENT_VIEW_START,
2089         TEXT_ALIGNMENT_VIEW_END
2090     })
2091     @Retention(RetentionPolicy.SOURCE)
2092     public @interface TextAlignment {}
2093 
2094     /**
2095      * Default text alignment. The text alignment of this View is inherited from its parent.
2096      * Use with {@link #setTextAlignment(int)}
2097      */
2098     public static final int TEXT_ALIGNMENT_INHERIT = 0;
2099 
2100     /**
2101      * Default for the root view. The gravity determines the text alignment, ALIGN_NORMAL,
2102      * ALIGN_CENTER, or ALIGN_OPPOSITE, which are relative to each paragraph’s text direction.
2103      *
2104      * Use with {@link #setTextAlignment(int)}
2105      */
2106     public static final int TEXT_ALIGNMENT_GRAVITY = 1;
2107 
2108     /**
2109      * Align to the start of the paragraph, e.g. ALIGN_NORMAL.
2110      *
2111      * Use with {@link #setTextAlignment(int)}
2112      */
2113     public static final int TEXT_ALIGNMENT_TEXT_START = 2;
2114 
2115     /**
2116      * Align to the end of the paragraph, e.g. ALIGN_OPPOSITE.
2117      *
2118      * Use with {@link #setTextAlignment(int)}
2119      */
2120     public static final int TEXT_ALIGNMENT_TEXT_END = 3;
2121 
2122     /**
2123      * Center the paragraph, e.g. ALIGN_CENTER.
2124      *
2125      * Use with {@link #setTextAlignment(int)}
2126      */
2127     public static final int TEXT_ALIGNMENT_CENTER = 4;
2128 
2129     /**
2130      * Align to the start of the view, which is ALIGN_LEFT if the view’s resolved
2131      * layoutDirection is LTR, and ALIGN_RIGHT otherwise.
2132      *
2133      * Use with {@link #setTextAlignment(int)}
2134      */
2135     public static final int TEXT_ALIGNMENT_VIEW_START = 5;
2136 
2137     /**
2138      * Align to the end of the view, which is ALIGN_RIGHT if the view’s resolved
2139      * layoutDirection is LTR, and ALIGN_LEFT otherwise.
2140      *
2141      * Use with {@link #setTextAlignment(int)}
2142      */
2143     public static final int TEXT_ALIGNMENT_VIEW_END = 6;
2144 
2145     /**
2146      * Default text alignment is inherited
2147      */
2148     private static final int TEXT_ALIGNMENT_DEFAULT = TEXT_ALIGNMENT_GRAVITY;
2149 
2150     /**
2151      * Default resolved text alignment
2152      * @hide
2153      */
2154     static final int TEXT_ALIGNMENT_RESOLVED_DEFAULT = TEXT_ALIGNMENT_GRAVITY;
2155 
2156     /**
2157       * Bit shift to get the horizontal layout direction. (bits after DRAG_HOVERED)
2158       * @hide
2159       */
2160     static final int PFLAG2_TEXT_ALIGNMENT_MASK_SHIFT = 13;
2161 
2162     /**
2163       * Mask for use with private flags indicating bits used for text alignment.
2164       * @hide
2165       */
2166     static final int PFLAG2_TEXT_ALIGNMENT_MASK = 0x00000007 << PFLAG2_TEXT_ALIGNMENT_MASK_SHIFT;
2167 
2168     /**
2169      * Array of text direction flags for mapping attribute "textAlignment" to correct
2170      * flag value.
2171      * @hide
2172      */
2173     private static final int[] PFLAG2_TEXT_ALIGNMENT_FLAGS = {
2174             TEXT_ALIGNMENT_INHERIT << PFLAG2_TEXT_ALIGNMENT_MASK_SHIFT,
2175             TEXT_ALIGNMENT_GRAVITY << PFLAG2_TEXT_ALIGNMENT_MASK_SHIFT,
2176             TEXT_ALIGNMENT_TEXT_START << PFLAG2_TEXT_ALIGNMENT_MASK_SHIFT,
2177             TEXT_ALIGNMENT_TEXT_END << PFLAG2_TEXT_ALIGNMENT_MASK_SHIFT,
2178             TEXT_ALIGNMENT_CENTER << PFLAG2_TEXT_ALIGNMENT_MASK_SHIFT,
2179             TEXT_ALIGNMENT_VIEW_START << PFLAG2_TEXT_ALIGNMENT_MASK_SHIFT,
2180             TEXT_ALIGNMENT_VIEW_END << PFLAG2_TEXT_ALIGNMENT_MASK_SHIFT
2181     };
2182 
2183     /**
2184      * Indicates whether the view text alignment has been resolved.
2185      * @hide
2186      */
2187     static final int PFLAG2_TEXT_ALIGNMENT_RESOLVED = 0x00000008 << PFLAG2_TEXT_ALIGNMENT_MASK_SHIFT;
2188 
2189     /**
2190      * Bit shift to get the resolved text alignment.
2191      * @hide
2192      */
2193     static final int PFLAG2_TEXT_ALIGNMENT_RESOLVED_MASK_SHIFT = 17;
2194 
2195     /**
2196      * Mask for use with private flags indicating bits used for text alignment.
2197      * @hide
2198      */
2199     static final int PFLAG2_TEXT_ALIGNMENT_RESOLVED_MASK = 0x00000007
2200             << PFLAG2_TEXT_ALIGNMENT_RESOLVED_MASK_SHIFT;
2201 
2202     /**
2203      * Indicates whether if the view text alignment has been resolved to gravity
2204      */
2205     private static final int PFLAG2_TEXT_ALIGNMENT_RESOLVED_DEFAULT =
2206             TEXT_ALIGNMENT_RESOLVED_DEFAULT << PFLAG2_TEXT_ALIGNMENT_RESOLVED_MASK_SHIFT;
2207 
2208     // Accessiblity constants for mPrivateFlags2
2209 
2210     /**
2211      * Shift for the bits in {@link #mPrivateFlags2} related to the
2212      * "importantForAccessibility" attribute.
2213      */
2214     static final int PFLAG2_IMPORTANT_FOR_ACCESSIBILITY_SHIFT = 20;
2215 
2216     /**
2217      * Automatically determine whether a view is important for accessibility.
2218      */
2219     public static final int IMPORTANT_FOR_ACCESSIBILITY_AUTO = 0x00000000;
2220 
2221     /**
2222      * The view is important for accessibility.
2223      */
2224     public static final int IMPORTANT_FOR_ACCESSIBILITY_YES = 0x00000001;
2225 
2226     /**
2227      * The view is not important for accessibility.
2228      */
2229     public static final int IMPORTANT_FOR_ACCESSIBILITY_NO = 0x00000002;
2230 
2231     /**
2232      * The view is not important for accessibility, nor are any of its
2233      * descendant views.
2234      */
2235     public static final int IMPORTANT_FOR_ACCESSIBILITY_NO_HIDE_DESCENDANTS = 0x00000004;
2236 
2237     /**
2238      * The default whether the view is important for accessibility.
2239      */
2240     static final int IMPORTANT_FOR_ACCESSIBILITY_DEFAULT = IMPORTANT_FOR_ACCESSIBILITY_AUTO;
2241 
2242     /**
2243      * Mask for obtainig the bits which specify how to determine
2244      * whether a view is important for accessibility.
2245      */
2246     static final int PFLAG2_IMPORTANT_FOR_ACCESSIBILITY_MASK = (IMPORTANT_FOR_ACCESSIBILITY_AUTO
2247         | IMPORTANT_FOR_ACCESSIBILITY_YES | IMPORTANT_FOR_ACCESSIBILITY_NO
2248         | IMPORTANT_FOR_ACCESSIBILITY_NO_HIDE_DESCENDANTS)
2249         << PFLAG2_IMPORTANT_FOR_ACCESSIBILITY_SHIFT;
2250 
2251     /**
2252      * Shift for the bits in {@link #mPrivateFlags2} related to the
2253      * "accessibilityLiveRegion" attribute.
2254      */
2255     static final int PFLAG2_ACCESSIBILITY_LIVE_REGION_SHIFT = 23;
2256 
2257     /**
2258      * Live region mode specifying that accessibility services should not
2259      * automatically announce changes to this view. This is the default live
2260      * region mode for most views.
2261      * <p>
2262      * Use with {@link #setAccessibilityLiveRegion(int)}.
2263      */
2264     public static final int ACCESSIBILITY_LIVE_REGION_NONE = 0x00000000;
2265 
2266     /**
2267      * Live region mode specifying that accessibility services should announce
2268      * changes to this view.
2269      * <p>
2270      * Use with {@link #setAccessibilityLiveRegion(int)}.
2271      */
2272     public static final int ACCESSIBILITY_LIVE_REGION_POLITE = 0x00000001;
2273 
2274     /**
2275      * Live region mode specifying that accessibility services should interrupt
2276      * ongoing speech to immediately announce changes to this view.
2277      * <p>
2278      * Use with {@link #setAccessibilityLiveRegion(int)}.
2279      */
2280     public static final int ACCESSIBILITY_LIVE_REGION_ASSERTIVE = 0x00000002;
2281 
2282     /**
2283      * The default whether the view is important for accessibility.
2284      */
2285     static final int ACCESSIBILITY_LIVE_REGION_DEFAULT = ACCESSIBILITY_LIVE_REGION_NONE;
2286 
2287     /**
2288      * Mask for obtaining the bits which specify a view's accessibility live
2289      * region mode.
2290      */
2291     static final int PFLAG2_ACCESSIBILITY_LIVE_REGION_MASK = (ACCESSIBILITY_LIVE_REGION_NONE
2292             | ACCESSIBILITY_LIVE_REGION_POLITE | ACCESSIBILITY_LIVE_REGION_ASSERTIVE)
2293             << PFLAG2_ACCESSIBILITY_LIVE_REGION_SHIFT;
2294 
2295     /**
2296      * Flag indicating whether a view has accessibility focus.
2297      */
2298     static final int PFLAG2_ACCESSIBILITY_FOCUSED = 0x04000000;
2299 
2300     /**
2301      * Flag whether the accessibility state of the subtree rooted at this view changed.
2302      */
2303     static final int PFLAG2_SUBTREE_ACCESSIBILITY_STATE_CHANGED = 0x08000000;
2304 
2305     /**
2306      * Flag indicating whether a view failed the quickReject() check in draw(). This condition
2307      * is used to check whether later changes to the view's transform should invalidate the
2308      * view to force the quickReject test to run again.
2309      */
2310     static final int PFLAG2_VIEW_QUICK_REJECTED = 0x10000000;
2311 
2312     /**
2313      * Flag indicating that start/end padding has been resolved into left/right padding
2314      * for use in measurement, layout, drawing, etc. This is set by {@link #resolvePadding()}
2315      * and checked by {@link #measure(int, int)} to determine if padding needs to be resolved
2316      * during measurement. In some special cases this is required such as when an adapter-based
2317      * view measures prospective children without attaching them to a window.
2318      */
2319     static final int PFLAG2_PADDING_RESOLVED = 0x20000000;
2320 
2321     /**
2322      * Flag indicating that the start/end drawables has been resolved into left/right ones.
2323      */
2324     static final int PFLAG2_DRAWABLE_RESOLVED = 0x40000000;
2325 
2326     /**
2327      * Indicates that the view is tracking some sort of transient state
2328      * that the app should not need to be aware of, but that the framework
2329      * should take special care to preserve.
2330      */
2331     static final int PFLAG2_HAS_TRANSIENT_STATE = 0x80000000;
2332 
2333     /**
2334      * Group of bits indicating that RTL properties resolution is done.
2335      */
2336     static final int ALL_RTL_PROPERTIES_RESOLVED = PFLAG2_LAYOUT_DIRECTION_RESOLVED |
2337             PFLAG2_TEXT_DIRECTION_RESOLVED |
2338             PFLAG2_TEXT_ALIGNMENT_RESOLVED |
2339             PFLAG2_PADDING_RESOLVED |
2340             PFLAG2_DRAWABLE_RESOLVED;
2341 
2342     // There are a couple of flags left in mPrivateFlags2
2343 
2344     /* End of masks for mPrivateFlags2 */
2345 
2346     /**
2347      * Masks for mPrivateFlags3, as generated by dumpFlags():
2348      *
2349      * |-------|-------|-------|-------|
2350      *                                 1 PFLAG3_VIEW_IS_ANIMATING_TRANSFORM
2351      *                                1  PFLAG3_VIEW_IS_ANIMATING_ALPHA
2352      *                               1   PFLAG3_IS_LAID_OUT
2353      *                              1    PFLAG3_MEASURE_NEEDED_BEFORE_LAYOUT
2354      *                             1     PFLAG3_CALLED_SUPER
2355      *                            1      PFLAG3_APPLYING_INSETS
2356      *                           1       PFLAG3_FITTING_SYSTEM_WINDOWS
2357      *                          1        PFLAG3_NESTED_SCROLLING_ENABLED
2358      *                         1         PFLAG3_SCROLL_INDICATOR_TOP
2359      *                        1          PFLAG3_SCROLL_INDICATOR_BOTTOM
2360      *                       1           PFLAG3_SCROLL_INDICATOR_LEFT
2361      *                      1            PFLAG3_SCROLL_INDICATOR_RIGHT
2362      *                     1             PFLAG3_SCROLL_INDICATOR_START
2363      *                    1              PFLAG3_SCROLL_INDICATOR_END
2364      *                   1               PFLAG3_ASSIST_BLOCKED
2365      * |-------|-------|-------|-------|
2366      */
2367 
2368     /**
2369      * Flag indicating that view has a transform animation set on it. This is used to track whether
2370      * an animation is cleared between successive frames, in order to tell the associated
2371      * DisplayList to clear its animation matrix.
2372      */
2373     static final int PFLAG3_VIEW_IS_ANIMATING_TRANSFORM = 0x1;
2374 
2375     /**
2376      * Flag indicating that view has an alpha animation set on it. This is used to track whether an
2377      * animation is cleared between successive frames, in order to tell the associated
2378      * DisplayList to restore its alpha value.
2379      */
2380     static final int PFLAG3_VIEW_IS_ANIMATING_ALPHA = 0x2;
2381 
2382     /**
2383      * Flag indicating that the view has been through at least one layout since it
2384      * was last attached to a window.
2385      */
2386     static final int PFLAG3_IS_LAID_OUT = 0x4;
2387 
2388     /**
2389      * Flag indicating that a call to measure() was skipped and should be done
2390      * instead when layout() is invoked.
2391      */
2392     static final int PFLAG3_MEASURE_NEEDED_BEFORE_LAYOUT = 0x8;
2393 
2394     /**
2395      * Flag indicating that an overridden method correctly called down to
2396      * the superclass implementation as required by the API spec.
2397      */
2398     static final int PFLAG3_CALLED_SUPER = 0x10;
2399 
2400     /**
2401      * Flag indicating that we're in the process of applying window insets.
2402      */
2403     static final int PFLAG3_APPLYING_INSETS = 0x20;
2404 
2405     /**
2406      * Flag indicating that we're in the process of fitting system windows using the old method.
2407      */
2408     static final int PFLAG3_FITTING_SYSTEM_WINDOWS = 0x40;
2409 
2410     /**
2411      * Flag indicating that nested scrolling is enabled for this view.
2412      * The view will optionally cooperate with views up its parent chain to allow for
2413      * integrated nested scrolling along the same axis.
2414      */
2415     static final int PFLAG3_NESTED_SCROLLING_ENABLED = 0x80;
2416 
2417     /**
2418      * Flag indicating that the bottom scroll indicator should be displayed
2419      * when this view can scroll up.
2420      */
2421     static final int PFLAG3_SCROLL_INDICATOR_TOP = 0x0100;
2422 
2423     /**
2424      * Flag indicating that the bottom scroll indicator should be displayed
2425      * when this view can scroll down.
2426      */
2427     static final int PFLAG3_SCROLL_INDICATOR_BOTTOM = 0x0200;
2428 
2429     /**
2430      * Flag indicating that the left scroll indicator should be displayed
2431      * when this view can scroll left.
2432      */
2433     static final int PFLAG3_SCROLL_INDICATOR_LEFT = 0x0400;
2434 
2435     /**
2436      * Flag indicating that the right scroll indicator should be displayed
2437      * when this view can scroll right.
2438      */
2439     static final int PFLAG3_SCROLL_INDICATOR_RIGHT = 0x0800;
2440 
2441     /**
2442      * Flag indicating that the start scroll indicator should be displayed
2443      * when this view can scroll in the start direction.
2444      */
2445     static final int PFLAG3_SCROLL_INDICATOR_START = 0x1000;
2446 
2447     /**
2448      * Flag indicating that the end scroll indicator should be displayed
2449      * when this view can scroll in the end direction.
2450      */
2451     static final int PFLAG3_SCROLL_INDICATOR_END = 0x2000;
2452 
2453     /* End of masks for mPrivateFlags3 */
2454 
2455     static final int DRAG_MASK = PFLAG2_DRAG_CAN_ACCEPT | PFLAG2_DRAG_HOVERED;
2456 
2457     static final int SCROLL_INDICATORS_NONE = 0x0000;
2458 
2459     /**
2460      * Mask for use with setFlags indicating bits used for indicating which
2461      * scroll indicators are enabled.
2462      */
2463     static final int SCROLL_INDICATORS_PFLAG3_MASK = PFLAG3_SCROLL_INDICATOR_TOP
2464             | PFLAG3_SCROLL_INDICATOR_BOTTOM | PFLAG3_SCROLL_INDICATOR_LEFT
2465             | PFLAG3_SCROLL_INDICATOR_RIGHT | PFLAG3_SCROLL_INDICATOR_START
2466             | PFLAG3_SCROLL_INDICATOR_END;
2467 
2468     /**
2469      * Left-shift required to translate between public scroll indicator flags
2470      * and internal PFLAGS3 flags. When used as a right-shift, translates
2471      * PFLAGS3 flags to public flags.
2472      */
2473     static final int SCROLL_INDICATORS_TO_PFLAGS3_LSHIFT = 8;
2474 
2475     /** @hide */
2476     @Retention(RetentionPolicy.SOURCE)
2477     @IntDef(flag = true,
2478             value = {
2479                     SCROLL_INDICATOR_TOP,
2480                     SCROLL_INDICATOR_BOTTOM,
2481                     SCROLL_INDICATOR_LEFT,
2482                     SCROLL_INDICATOR_RIGHT,
2483                     SCROLL_INDICATOR_START,
2484                     SCROLL_INDICATOR_END,
2485             })
2486     public @interface ScrollIndicators {}
2487 
2488     /**
2489      * Scroll indicator direction for the top edge of the view.
2490      *
2491      * @see #setScrollIndicators(int)
2492      * @see #setScrollIndicators(int, int)
2493      * @see #getScrollIndicators()
2494      */
2495     public static final int SCROLL_INDICATOR_TOP =
2496             PFLAG3_SCROLL_INDICATOR_TOP >> SCROLL_INDICATORS_TO_PFLAGS3_LSHIFT;
2497 
2498     /**
2499      * Scroll indicator direction for the bottom edge of the view.
2500      *
2501      * @see #setScrollIndicators(int)
2502      * @see #setScrollIndicators(int, int)
2503      * @see #getScrollIndicators()
2504      */
2505     public static final int SCROLL_INDICATOR_BOTTOM =
2506             PFLAG3_SCROLL_INDICATOR_BOTTOM >> SCROLL_INDICATORS_TO_PFLAGS3_LSHIFT;
2507 
2508     /**
2509      * Scroll indicator direction for the left edge of the view.
2510      *
2511      * @see #setScrollIndicators(int)
2512      * @see #setScrollIndicators(int, int)
2513      * @see #getScrollIndicators()
2514      */
2515     public static final int SCROLL_INDICATOR_LEFT =
2516             PFLAG3_SCROLL_INDICATOR_LEFT >> SCROLL_INDICATORS_TO_PFLAGS3_LSHIFT;
2517 
2518     /**
2519      * Scroll indicator direction for the right edge of the view.
2520      *
2521      * @see #setScrollIndicators(int)
2522      * @see #setScrollIndicators(int, int)
2523      * @see #getScrollIndicators()
2524      */
2525     public static final int SCROLL_INDICATOR_RIGHT =
2526             PFLAG3_SCROLL_INDICATOR_RIGHT >> SCROLL_INDICATORS_TO_PFLAGS3_LSHIFT;
2527 
2528     /**
2529      * Scroll indicator direction for the starting edge of the view.
2530      * <p>
2531      * Resolved according to the view's layout direction, see
2532      * {@link #getLayoutDirection()} for more information.
2533      *
2534      * @see #setScrollIndicators(int)
2535      * @see #setScrollIndicators(int, int)
2536      * @see #getScrollIndicators()
2537      */
2538     public static final int SCROLL_INDICATOR_START =
2539             PFLAG3_SCROLL_INDICATOR_START >> SCROLL_INDICATORS_TO_PFLAGS3_LSHIFT;
2540 
2541     /**
2542      * Scroll indicator direction for the ending edge of the view.
2543      * <p>
2544      * Resolved according to the view's layout direction, see
2545      * {@link #getLayoutDirection()} for more information.
2546      *
2547      * @see #setScrollIndicators(int)
2548      * @see #setScrollIndicators(int, int)
2549      * @see #getScrollIndicators()
2550      */
2551     public static final int SCROLL_INDICATOR_END =
2552             PFLAG3_SCROLL_INDICATOR_END >> SCROLL_INDICATORS_TO_PFLAGS3_LSHIFT;
2553 
2554     /**
2555      * <p>Indicates that we are allowing {@link ViewStructure} to traverse
2556      * into this view.<p>
2557      */
2558     static final int PFLAG3_ASSIST_BLOCKED = 0x4000;
2559 
2560     /**
2561      * Always allow a user to over-scroll this view, provided it is a
2562      * view that can scroll.
2563      *
2564      * @see #getOverScrollMode()
2565      * @see #setOverScrollMode(int)
2566      */
2567     public static final int OVER_SCROLL_ALWAYS = 0;
2568 
2569     /**
2570      * Allow a user to over-scroll this view only if the content is large
2571      * enough to meaningfully scroll, provided it is a view that can scroll.
2572      *
2573      * @see #getOverScrollMode()
2574      * @see #setOverScrollMode(int)
2575      */
2576     public static final int OVER_SCROLL_IF_CONTENT_SCROLLS = 1;
2577 
2578     /**
2579      * Never allow a user to over-scroll this view.
2580      *
2581      * @see #getOverScrollMode()
2582      * @see #setOverScrollMode(int)
2583      */
2584     public static final int OVER_SCROLL_NEVER = 2;
2585 
2586     /**
2587      * Special constant for {@link #setSystemUiVisibility(int)}: View has
2588      * requested the system UI (status bar) to be visible (the default).
2589      *
2590      * @see #setSystemUiVisibility(int)
2591      */
2592     public static final int SYSTEM_UI_FLAG_VISIBLE = 0;
2593 
2594     /**
2595      * Flag for {@link #setSystemUiVisibility(int)}: View has requested the
2596      * system UI to enter an unobtrusive "low profile" mode.
2597      *
2598      * <p>This is for use in games, book readers, video players, or any other
2599      * "immersive" application where the usual system chrome is deemed too distracting.
2600      *
2601      * <p>In low profile mode, the status bar and/or navigation icons may dim.
2602      *
2603      * @see #setSystemUiVisibility(int)
2604      */
2605     public static final int SYSTEM_UI_FLAG_LOW_PROFILE = 0x00000001;
2606 
2607     /**
2608      * Flag for {@link #setSystemUiVisibility(int)}: View has requested that the
2609      * system navigation be temporarily hidden.
2610      *
2611      * <p>This is an even less obtrusive state than that called for by
2612      * {@link #SYSTEM_UI_FLAG_LOW_PROFILE}; on devices that draw essential navigation controls
2613      * (Home, Back, and the like) on screen, <code>SYSTEM_UI_FLAG_HIDE_NAVIGATION</code> will cause
2614      * those to disappear. This is useful (in conjunction with the
2615      * {@link android.view.WindowManager.LayoutParams#FLAG_FULLSCREEN FLAG_FULLSCREEN} and
2616      * {@link android.view.WindowManager.LayoutParams#FLAG_LAYOUT_IN_SCREEN FLAG_LAYOUT_IN_SCREEN}
2617      * window flags) for displaying content using every last pixel on the display.
2618      *
2619      * <p>There is a limitation: because navigation controls are so important, the least user
2620      * interaction will cause them to reappear immediately.  When this happens, both
2621      * this flag and {@link #SYSTEM_UI_FLAG_FULLSCREEN} will be cleared automatically,
2622      * so that both elements reappear at the same time.
2623      *
2624      * @see #setSystemUiVisibility(int)
2625      */
2626     public static final int SYSTEM_UI_FLAG_HIDE_NAVIGATION = 0x00000002;
2627 
2628     /**
2629      * Flag for {@link #setSystemUiVisibility(int)}: View has requested to go
2630      * into the normal fullscreen mode so that its content can take over the screen
2631      * while still allowing the user to interact with the application.
2632      *
2633      * <p>This has the same visual effect as
2634      * {@link android.view.WindowManager.LayoutParams#FLAG_FULLSCREEN
2635      * WindowManager.LayoutParams.FLAG_FULLSCREEN},
2636      * meaning that non-critical screen decorations (such as the status bar) will be
2637      * hidden while the user is in the View's window, focusing the experience on
2638      * that content.  Unlike the window flag, if you are using ActionBar in
2639      * overlay mode with {@link Window#FEATURE_ACTION_BAR_OVERLAY
2640      * Window.FEATURE_ACTION_BAR_OVERLAY}, then enabling this flag will also
2641      * hide the action bar.
2642      *
2643      * <p>This approach to going fullscreen is best used over the window flag when
2644      * it is a transient state -- that is, the application does this at certain
2645      * points in its user interaction where it wants to allow the user to focus
2646      * on content, but not as a continuous state.  For situations where the application
2647      * would like to simply stay full screen the entire time (such as a game that
2648      * wants to take over the screen), the
2649      * {@link android.view.WindowManager.LayoutParams#FLAG_FULLSCREEN window flag}
2650      * is usually a better approach.  The state set here will be removed by the system
2651      * in various situations (such as the user moving to another application) like
2652      * the other system UI states.
2653      *
2654      * <p>When using this flag, the application should provide some easy facility
2655      * for the user to go out of it.  A common example would be in an e-book
2656      * reader, where tapping on the screen brings back whatever screen and UI
2657      * decorations that had been hidden while the user was immersed in reading
2658      * the book.
2659      *
2660      * @see #setSystemUiVisibility(int)
2661      */
2662     public static final int SYSTEM_UI_FLAG_FULLSCREEN = 0x00000004;
2663 
2664     /**
2665      * Flag for {@link #setSystemUiVisibility(int)}: When using other layout
2666      * flags, we would like a stable view of the content insets given to
2667      * {@link #fitSystemWindows(Rect)}.  This means that the insets seen there
2668      * will always represent the worst case that the application can expect
2669      * as a continuous state.  In the stock Android UI this is the space for
2670      * the system bar, nav bar, and status bar, but not more transient elements
2671      * such as an input method.
2672      *
2673      * The stable layout your UI sees is based on the system UI modes you can
2674      * switch to.  That is, if you specify {@link #SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN}
2675      * then you will get a stable layout for changes of the
2676      * {@link #SYSTEM_UI_FLAG_FULLSCREEN} mode; if you specify
2677      * {@link #SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN} and
2678      * {@link #SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION}, then you can transition
2679      * to {@link #SYSTEM_UI_FLAG_FULLSCREEN} and {@link #SYSTEM_UI_FLAG_HIDE_NAVIGATION}
2680      * with a stable layout.  (Note that you should avoid using
2681      * {@link #SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION} by itself.)
2682      *
2683      * If you have set the window flag {@link WindowManager.LayoutParams#FLAG_FULLSCREEN}
2684      * to hide the status bar (instead of using {@link #SYSTEM_UI_FLAG_FULLSCREEN}),
2685      * then a hidden status bar will be considered a "stable" state for purposes
2686      * here.  This allows your UI to continually hide the status bar, while still
2687      * using the system UI flags to hide the action bar while still retaining
2688      * a stable layout.  Note that changing the window fullscreen flag will never
2689      * provide a stable layout for a clean transition.
2690      *
2691      * <p>If you are using ActionBar in
2692      * overlay mode with {@link Window#FEATURE_ACTION_BAR_OVERLAY
2693      * Window.FEATURE_ACTION_BAR_OVERLAY}, this flag will also impact the
2694      * insets it adds to those given to the application.
2695      */
2696     public static final int SYSTEM_UI_FLAG_LAYOUT_STABLE = 0x00000100;
2697 
2698     /**
2699      * Flag for {@link #setSystemUiVisibility(int)}: View would like its window
2700      * to be laid out as if it has requested
2701      * {@link #SYSTEM_UI_FLAG_HIDE_NAVIGATION}, even if it currently hasn't.  This
2702      * allows it to avoid artifacts when switching in and out of that mode, at
2703      * the expense that some of its user interface may be covered by screen
2704      * decorations when they are shown.  You can perform layout of your inner
2705      * UI elements to account for the navigation system UI through the
2706      * {@link #fitSystemWindows(Rect)} method.
2707      */
2708     public static final int SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION = 0x00000200;
2709 
2710     /**
2711      * Flag for {@link #setSystemUiVisibility(int)}: View would like its window
2712      * to be laid out as if it has requested
2713      * {@link #SYSTEM_UI_FLAG_FULLSCREEN}, even if it currently hasn't.  This
2714      * allows it to avoid artifacts when switching in and out of that mode, at
2715      * the expense that some of its user interface may be covered by screen
2716      * decorations when they are shown.  You can perform layout of your inner
2717      * UI elements to account for non-fullscreen system UI through the
2718      * {@link #fitSystemWindows(Rect)} method.
2719      */
2720     public static final int SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN = 0x00000400;
2721 
2722     /**
2723      * Flag for {@link #setSystemUiVisibility(int)}: View would like to remain interactive when
2724      * hiding the navigation bar with {@link #SYSTEM_UI_FLAG_HIDE_NAVIGATION}.  If this flag is
2725      * not set, {@link #SYSTEM_UI_FLAG_HIDE_NAVIGATION} will be force cleared by the system on any
2726      * user interaction.
2727      * <p>Since this flag is a modifier for {@link #SYSTEM_UI_FLAG_HIDE_NAVIGATION}, it only
2728      * has an effect when used in combination with that flag.</p>
2729      */
2730     public static final int SYSTEM_UI_FLAG_IMMERSIVE = 0x00000800;
2731 
2732     /**
2733      * Flag for {@link #setSystemUiVisibility(int)}: View would like to remain interactive when
2734      * hiding the status bar with {@link #SYSTEM_UI_FLAG_FULLSCREEN} and/or hiding the navigation
2735      * bar with {@link #SYSTEM_UI_FLAG_HIDE_NAVIGATION}.  Use this flag to create an immersive
2736      * experience while also hiding the system bars.  If this flag is not set,
2737      * {@link #SYSTEM_UI_FLAG_HIDE_NAVIGATION} will be force cleared by the system on any user
2738      * interaction, and {@link #SYSTEM_UI_FLAG_FULLSCREEN} will be force-cleared by the system
2739      * if the user swipes from the top of the screen.
2740      * <p>When system bars are hidden in immersive mode, they can be revealed temporarily with
2741      * system gestures, such as swiping from the top of the screen.  These transient system bars
2742      * will overlay app’s content, may have some degree of transparency, and will automatically
2743      * hide after a short timeout.
2744      * </p><p>Since this flag is a modifier for {@link #SYSTEM_UI_FLAG_FULLSCREEN} and
2745      * {@link #SYSTEM_UI_FLAG_HIDE_NAVIGATION}, it only has an effect when used in combination
2746      * with one or both of those flags.</p>
2747      */
2748     public static final int SYSTEM_UI_FLAG_IMMERSIVE_STICKY = 0x00001000;
2749 
2750     /**
2751      * Flag for {@link #setSystemUiVisibility(int)}: Requests the status bar to draw in a mode that
2752      * is compatible with light status bar backgrounds.
2753      *
2754      * <p>For this to take effect, the window must request
2755      * {@link android.view.WindowManager.LayoutParams#FLAG_DRAWS_SYSTEM_BAR_BACKGROUNDS
2756      *         FLAG_DRAWS_SYSTEM_BAR_BACKGROUNDS} but not
2757      * {@link android.view.WindowManager.LayoutParams#FLAG_TRANSLUCENT_STATUS
2758      *         FLAG_TRANSLUCENT_STATUS}.
2759      *
2760      * @see android.R.attr#windowLightStatusBar
2761      */
2762     public static final int SYSTEM_UI_FLAG_LIGHT_STATUS_BAR = 0x00002000;
2763 
2764     /**
2765      * @deprecated Use {@link #SYSTEM_UI_FLAG_LOW_PROFILE} instead.
2766      */
2767     public static final int STATUS_BAR_HIDDEN = SYSTEM_UI_FLAG_LOW_PROFILE;
2768 
2769     /**
2770      * @deprecated Use {@link #SYSTEM_UI_FLAG_VISIBLE} instead.
2771      */
2772     public static final int STATUS_BAR_VISIBLE = SYSTEM_UI_FLAG_VISIBLE;
2773 
2774     /**
2775      * @hide
2776      *
2777      * NOTE: This flag may only be used in subtreeSystemUiVisibility. It is masked
2778      * out of the public fields to keep the undefined bits out of the developer's way.
2779      *
2780      * Flag to make the status bar not expandable.  Unless you also
2781      * set {@link #STATUS_BAR_DISABLE_NOTIFICATION_ICONS}, new notifications will continue to show.
2782      */
2783     public static final int STATUS_BAR_DISABLE_EXPAND = 0x00010000;
2784 
2785     /**
2786      * @hide
2787      *
2788      * NOTE: This flag may only be used in subtreeSystemUiVisibility. It is masked
2789      * out of the public fields to keep the undefined bits out of the developer's way.
2790      *
2791      * Flag to hide notification icons and scrolling ticker text.
2792      */
2793     public static final int STATUS_BAR_DISABLE_NOTIFICATION_ICONS = 0x00020000;
2794 
2795     /**
2796      * @hide
2797      *
2798      * NOTE: This flag may only be used in subtreeSystemUiVisibility. It is masked
2799      * out of the public fields to keep the undefined bits out of the developer's way.
2800      *
2801      * Flag to disable incoming notification alerts.  This will not block
2802      * icons, but it will block sound, vibrating and other visual or aural notifications.
2803      */
2804     public static final int STATUS_BAR_DISABLE_NOTIFICATION_ALERTS = 0x00040000;
2805 
2806     /**
2807      * @hide
2808      *
2809      * NOTE: This flag may only be used in subtreeSystemUiVisibility. It is masked
2810      * out of the public fields to keep the undefined bits out of the developer's way.
2811      *
2812      * Flag to hide only the scrolling ticker.  Note that
2813      * {@link #STATUS_BAR_DISABLE_NOTIFICATION_ICONS} implies
2814      * {@link #STATUS_BAR_DISABLE_NOTIFICATION_TICKER}.
2815      */
2816     public static final int STATUS_BAR_DISABLE_NOTIFICATION_TICKER = 0x00080000;
2817 
2818     /**
2819      * @hide
2820      *
2821      * NOTE: This flag may only be used in subtreeSystemUiVisibility. It is masked
2822      * out of the public fields to keep the undefined bits out of the developer's way.
2823      *
2824      * Flag to hide the center system info area.
2825      */
2826     public static final int STATUS_BAR_DISABLE_SYSTEM_INFO = 0x00100000;
2827 
2828     /**
2829      * @hide
2830      *
2831      * NOTE: This flag may only be used in subtreeSystemUiVisibility. It is masked
2832      * out of the public fields to keep the undefined bits out of the developer's way.
2833      *
2834      * Flag to hide only the home button.  Don't use this
2835      * unless you're a special part of the system UI (i.e., setup wizard, keyguard).
2836      */
2837     public static final int STATUS_BAR_DISABLE_HOME = 0x00200000;
2838 
2839     /**
2840      * @hide
2841      *
2842      * NOTE: This flag may only be used in subtreeSystemUiVisibility. It is masked
2843      * out of the public fields to keep the undefined bits out of the developer's way.
2844      *
2845      * Flag to hide only the back button. Don't use this
2846      * unless you're a special part of the system UI (i.e., setup wizard, keyguard).
2847      */
2848     public static final int STATUS_BAR_DISABLE_BACK = 0x00400000;
2849 
2850     /**
2851      * @hide
2852      *
2853      * NOTE: This flag may only be used in subtreeSystemUiVisibility. It is masked
2854      * out of the public fields to keep the undefined bits out of the developer's way.
2855      *
2856      * Flag to hide only the clock.  You might use this if your activity has
2857      * its own clock making the status bar's clock redundant.
2858      */
2859     public static final int STATUS_BAR_DISABLE_CLOCK = 0x00800000;
2860 
2861     /**
2862      * @hide
2863      *
2864      * NOTE: This flag may only be used in subtreeSystemUiVisibility. It is masked
2865      * out of the public fields to keep the undefined bits out of the developer's way.
2866      *
2867      * Flag to hide only the recent apps button. Don't use this
2868      * unless you're a special part of the system UI (i.e., setup wizard, keyguard).
2869      */
2870     public static final int STATUS_BAR_DISABLE_RECENT = 0x01000000;
2871 
2872     /**
2873      * @hide
2874      *
2875      * NOTE: This flag may only be used in subtreeSystemUiVisibility. It is masked
2876      * out of the public fields to keep the undefined bits out of the developer's way.
2877      *
2878      * Flag to disable the global search gesture. Don't use this
2879      * unless you're a special part of the system UI (i.e., setup wizard, keyguard).
2880      */
2881     public static final int STATUS_BAR_DISABLE_SEARCH = 0x02000000;
2882 
2883     /**
2884      * @hide
2885      *
2886      * NOTE: This flag may only be used in subtreeSystemUiVisibility. It is masked
2887      * out of the public fields to keep the undefined bits out of the developer's way.
2888      *
2889      * Flag to specify that the status bar is displayed in transient mode.
2890      */
2891     public static final int STATUS_BAR_TRANSIENT = 0x04000000;
2892 
2893     /**
2894      * @hide
2895      *
2896      * NOTE: This flag may only be used in subtreeSystemUiVisibility. It is masked
2897      * out of the public fields to keep the undefined bits out of the developer's way.
2898      *
2899      * Flag to specify that the navigation bar is displayed in transient mode.
2900      */
2901     public static final int NAVIGATION_BAR_TRANSIENT = 0x08000000;
2902 
2903     /**
2904      * @hide
2905      *
2906      * NOTE: This flag may only be used in subtreeSystemUiVisibility. It is masked
2907      * out of the public fields to keep the undefined bits out of the developer's way.
2908      *
2909      * Flag to specify that the hidden status bar would like to be shown.
2910      */
2911     public static final int STATUS_BAR_UNHIDE = 0x10000000;
2912 
2913     /**
2914      * @hide
2915      *
2916      * NOTE: This flag may only be used in subtreeSystemUiVisibility. It is masked
2917      * out of the public fields to keep the undefined bits out of the developer's way.
2918      *
2919      * Flag to specify that the hidden navigation bar would like to be shown.
2920      */
2921     public static final int NAVIGATION_BAR_UNHIDE = 0x20000000;
2922 
2923     /**
2924      * @hide
2925      *
2926      * NOTE: This flag may only be used in subtreeSystemUiVisibility. It is masked
2927      * out of the public fields to keep the undefined bits out of the developer's way.
2928      *
2929      * Flag to specify that the status bar is displayed in translucent mode.
2930      */
2931     public static final int STATUS_BAR_TRANSLUCENT = 0x40000000;
2932 
2933     /**
2934      * @hide
2935      *
2936      * NOTE: This flag may only be used in subtreeSystemUiVisibility. It is masked
2937      * out of the public fields to keep the undefined bits out of the developer's way.
2938      *
2939      * Flag to specify that the navigation bar is displayed in translucent mode.
2940      */
2941     public static final int NAVIGATION_BAR_TRANSLUCENT = 0x80000000;
2942 
2943     /**
2944      * @hide
2945      *
2946      * Whether Recents is visible or not.
2947      */
2948     public static final int RECENT_APPS_VISIBLE = 0x00004000;
2949 
2950     /**
2951      * @hide
2952      *
2953      * Makes system ui transparent.
2954      */
2955     public static final int SYSTEM_UI_TRANSPARENT = 0x00008000;
2956 
2957     /**
2958      * @hide
2959      */
2960     public static final int PUBLIC_STATUS_BAR_VISIBILITY_MASK = 0x00003FFF;
2961 
2962     /**
2963      * These are the system UI flags that can be cleared by events outside
2964      * of an application.  Currently this is just the ability to tap on the
2965      * screen while hiding the navigation bar to have it return.
2966      * @hide
2967      */
2968     public static final int SYSTEM_UI_CLEARABLE_FLAGS =
2969             SYSTEM_UI_FLAG_LOW_PROFILE | SYSTEM_UI_FLAG_HIDE_NAVIGATION
2970             | SYSTEM_UI_FLAG_FULLSCREEN;
2971 
2972     /**
2973      * Flags that can impact the layout in relation to system UI.
2974      */
2975     public static final int SYSTEM_UI_LAYOUT_FLAGS =
2976             SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION
2977             | SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN;
2978 
2979     /** @hide */
2980     @IntDef(flag = true,
2981             value = { FIND_VIEWS_WITH_TEXT, FIND_VIEWS_WITH_CONTENT_DESCRIPTION })
2982     @Retention(RetentionPolicy.SOURCE)
2983     public @interface FindViewFlags {}
2984 
2985     /**
2986      * Find views that render the specified text.
2987      *
2988      * @see #findViewsWithText(ArrayList, CharSequence, int)
2989      */
2990     public static final int FIND_VIEWS_WITH_TEXT = 0x00000001;
2991 
2992     /**
2993      * Find find views that contain the specified content description.
2994      *
2995      * @see #findViewsWithText(ArrayList, CharSequence, int)
2996      */
2997     public static final int FIND_VIEWS_WITH_CONTENT_DESCRIPTION = 0x00000002;
2998 
2999     /**
3000      * Find views that contain {@link AccessibilityNodeProvider}. Such
3001      * a View is a root of virtual view hierarchy and may contain the searched
3002      * text. If this flag is set Views with providers are automatically
3003      * added and it is a responsibility of the client to call the APIs of
3004      * the provider to determine whether the virtual tree rooted at this View
3005      * contains the text, i.e. getting the list of {@link AccessibilityNodeInfo}s
3006      * representing the virtual views with this text.
3007      *
3008      * @see #findViewsWithText(ArrayList, CharSequence, int)
3009      *
3010      * @hide
3011      */
3012     public static final int FIND_VIEWS_WITH_ACCESSIBILITY_NODE_PROVIDERS = 0x00000004;
3013 
3014     /**
3015      * The undefined cursor position.
3016      *
3017      * @hide
3018      */
3019     public static final int ACCESSIBILITY_CURSOR_POSITION_UNDEFINED = -1;
3020 
3021     /**
3022      * Indicates that the screen has changed state and is now off.
3023      *
3024      * @see #onScreenStateChanged(int)
3025      */
3026     public static final int SCREEN_STATE_OFF = 0x0;
3027 
3028     /**
3029      * Indicates that the screen has changed state and is now on.
3030      *
3031      * @see #onScreenStateChanged(int)
3032      */
3033     public static final int SCREEN_STATE_ON = 0x1;
3034 
3035     /**
3036      * Indicates no axis of view scrolling.
3037      */
3038     public static final int SCROLL_AXIS_NONE = 0;
3039 
3040     /**
3041      * Indicates scrolling along the horizontal axis.
3042      */
3043     public static final int SCROLL_AXIS_HORIZONTAL = 1 << 0;
3044 
3045     /**
3046      * Indicates scrolling along the vertical axis.
3047      */
3048     public static final int SCROLL_AXIS_VERTICAL = 1 << 1;
3049 
3050     /**
3051      * Controls the over-scroll mode for this view.
3052      * See {@link #overScrollBy(int, int, int, int, int, int, int, int, boolean)},
3053      * {@link #OVER_SCROLL_ALWAYS}, {@link #OVER_SCROLL_IF_CONTENT_SCROLLS},
3054      * and {@link #OVER_SCROLL_NEVER}.
3055      */
3056     private int mOverScrollMode;
3057 
3058     /**
3059      * The parent this view is attached to.
3060      * {@hide}
3061      *
3062      * @see #getParent()
3063      */
3064     protected ViewParent mParent;
3065 
3066     /**
3067      * {@hide}
3068      */
3069     AttachInfo mAttachInfo;
3070 
3071     /**
3072      * {@hide}
3073      */
3074     @ViewDebug.ExportedProperty(flagMapping = {
3075         @ViewDebug.FlagToString(mask = PFLAG_FORCE_LAYOUT, equals = PFLAG_FORCE_LAYOUT,
3076                 name = "FORCE_LAYOUT"),
3077         @ViewDebug.FlagToString(mask = PFLAG_LAYOUT_REQUIRED, equals = PFLAG_LAYOUT_REQUIRED,
3078                 name = "LAYOUT_REQUIRED"),
3079         @ViewDebug.FlagToString(mask = PFLAG_DRAWING_CACHE_VALID, equals = PFLAG_DRAWING_CACHE_VALID,
3080             name = "DRAWING_CACHE_INVALID", outputIf = false),
3081         @ViewDebug.FlagToString(mask = PFLAG_DRAWN, equals = PFLAG_DRAWN, name = "DRAWN", outputIf = true),
3082         @ViewDebug.FlagToString(mask = PFLAG_DRAWN, equals = PFLAG_DRAWN, name = "NOT_DRAWN", outputIf = false),
3083         @ViewDebug.FlagToString(mask = PFLAG_DIRTY_MASK, equals = PFLAG_DIRTY_OPAQUE, name = "DIRTY_OPAQUE"),
3084         @ViewDebug.FlagToString(mask = PFLAG_DIRTY_MASK, equals = PFLAG_DIRTY, name = "DIRTY")
3085     }, formatToHexString = true)
3086     int mPrivateFlags;
3087     int mPrivateFlags2;
3088     int mPrivateFlags3;
3089 
3090     /**
3091      * This view's request for the visibility of the status bar.
3092      * @hide
3093      */
3094     @ViewDebug.ExportedProperty(flagMapping = {
3095         @ViewDebug.FlagToString(mask = SYSTEM_UI_FLAG_LOW_PROFILE,
3096                                 equals = SYSTEM_UI_FLAG_LOW_PROFILE,
3097                                 name = "SYSTEM_UI_FLAG_LOW_PROFILE", outputIf = true),
3098         @ViewDebug.FlagToString(mask = SYSTEM_UI_FLAG_HIDE_NAVIGATION,
3099                                 equals = SYSTEM_UI_FLAG_HIDE_NAVIGATION,
3100                                 name = "SYSTEM_UI_FLAG_HIDE_NAVIGATION", outputIf = true),
3101         @ViewDebug.FlagToString(mask = PUBLIC_STATUS_BAR_VISIBILITY_MASK,
3102                                 equals = SYSTEM_UI_FLAG_VISIBLE,
3103                                 name = "SYSTEM_UI_FLAG_VISIBLE", outputIf = true)
3104     }, formatToHexString = true)
3105     int mSystemUiVisibility;
3106 
3107     /**
3108      * Reference count for transient state.
3109      * @see #setHasTransientState(boolean)
3110      */
3111     int mTransientStateCount = 0;
3112 
3113     /**
3114      * Count of how many windows this view has been attached to.
3115      */
3116     int mWindowAttachCount;
3117 
3118     /**
3119      * The layout parameters associated with this view and used by the parent
3120      * {@link android.view.ViewGroup} to determine how this view should be
3121      * laid out.
3122      * {@hide}
3123      */
3124     protected ViewGroup.LayoutParams mLayoutParams;
3125 
3126     /**
3127      * The view flags hold various views states.
3128      * {@hide}
3129      */
3130     @ViewDebug.ExportedProperty(formatToHexString = true)
3131     int mViewFlags;
3132 
3133     static class TransformationInfo {
3134         /**
3135          * The transform matrix for the View. This transform is calculated internally
3136          * based on the translation, rotation, and scale properties.
3137          *
3138          * Do *not* use this variable directly; instead call getMatrix(), which will
3139          * load the value from the View's RenderNode.
3140          */
3141         private final Matrix mMatrix = new Matrix();
3142 
3143         /**
3144          * The inverse transform matrix for the View. This transform is calculated
3145          * internally based on the translation, rotation, and scale properties.
3146          *
3147          * Do *not* use this variable directly; instead call getInverseMatrix(),
3148          * which will load the value from the View's RenderNode.
3149          */
3150         private Matrix mInverseMatrix;
3151 
3152         /**
3153          * The opacity of the View. This is a value from 0 to 1, where 0 means
3154          * completely transparent and 1 means completely opaque.
3155          */
3156         @ViewDebug.ExportedProperty
3157         float mAlpha = 1f;
3158 
3159         /**
3160          * The opacity of the view as manipulated by the Fade transition. This is a hidden
3161          * property only used by transitions, which is composited with the other alpha
3162          * values to calculate the final visual alpha value.
3163          */
3164         float mTransitionAlpha = 1f;
3165     }
3166 
3167     TransformationInfo mTransformationInfo;
3168 
3169     /**
3170      * Current clip bounds. to which all drawing of this view are constrained.
3171      */
3172     Rect mClipBounds = null;
3173 
3174     private boolean mLastIsOpaque;
3175 
3176     /**
3177      * The distance in pixels from the left edge of this view's parent
3178      * to the left edge of this view.
3179      * {@hide}
3180      */
3181     @ViewDebug.ExportedProperty(category = "layout")
3182     protected int mLeft;
3183     /**
3184      * The distance in pixels from the left edge of this view's parent
3185      * to the right edge of this view.
3186      * {@hide}
3187      */
3188     @ViewDebug.ExportedProperty(category = "layout")
3189     protected int mRight;
3190     /**
3191      * The distance in pixels from the top edge of this view's parent
3192      * to the top edge of this view.
3193      * {@hide}
3194      */
3195     @ViewDebug.ExportedProperty(category = "layout")
3196     protected int mTop;
3197     /**
3198      * The distance in pixels from the top edge of this view's parent
3199      * to the bottom edge of this view.
3200      * {@hide}
3201      */
3202     @ViewDebug.ExportedProperty(category = "layout")
3203     protected int mBottom;
3204 
3205     /**
3206      * The offset, in pixels, by which the content of this view is scrolled
3207      * horizontally.
3208      * {@hide}
3209      */
3210     @ViewDebug.ExportedProperty(category = "scrolling")
3211     protected int mScrollX;
3212     /**
3213      * The offset, in pixels, by which the content of this view is scrolled
3214      * vertically.
3215      * {@hide}
3216      */
3217     @ViewDebug.ExportedProperty(category = "scrolling")
3218     protected int mScrollY;
3219 
3220     /**
3221      * The left padding in pixels, that is the distance in pixels between the
3222      * left edge of this view and the left edge of its content.
3223      * {@hide}
3224      */
3225     @ViewDebug.ExportedProperty(category = "padding")
3226     protected int mPaddingLeft = 0;
3227     /**
3228      * The right padding in pixels, that is the distance in pixels between the
3229      * right edge of this view and the right edge of its content.
3230      * {@hide}
3231      */
3232     @ViewDebug.ExportedProperty(category = "padding")
3233     protected int mPaddingRight = 0;
3234     /**
3235      * The top padding in pixels, that is the distance in pixels between the
3236      * top edge of this view and the top edge of its content.
3237      * {@hide}
3238      */
3239     @ViewDebug.ExportedProperty(category = "padding")
3240     protected int mPaddingTop;
3241     /**
3242      * The bottom padding in pixels, that is the distance in pixels between the
3243      * bottom edge of this view and the bottom edge of its content.
3244      * {@hide}
3245      */
3246     @ViewDebug.ExportedProperty(category = "padding")
3247     protected int mPaddingBottom;
3248 
3249     /**
3250      * The layout insets in pixels, that is the distance in pixels between the
3251      * visible edges of this view its bounds.
3252      */
3253     private Insets mLayoutInsets;
3254 
3255     /**
3256      * Briefly describes the view and is primarily used for accessibility support.
3257      */
3258     private CharSequence mContentDescription;
3259 
3260     /**
3261      * Specifies the id of a view for which this view serves as a label for
3262      * accessibility purposes.
3263      */
3264     private int mLabelForId = View.NO_ID;
3265 
3266     /**
3267      * Predicate for matching labeled view id with its label for
3268      * accessibility purposes.
3269      */
3270     private MatchLabelForPredicate mMatchLabelForPredicate;
3271 
3272     /**
3273      * Specifies a view before which this one is visited in accessibility traversal.
3274      */
3275     private int mAccessibilityTraversalBeforeId = NO_ID;
3276 
3277     /**
3278      * Specifies a view after which this one is visited in accessibility traversal.
3279      */
3280     private int mAccessibilityTraversalAfterId = NO_ID;
3281 
3282     /**
3283      * Predicate for matching a view by its id.
3284      */
3285     private MatchIdPredicate mMatchIdPredicate;
3286 
3287     /**
3288      * Cache the paddingRight set by the user to append to the scrollbar's size.
3289      *
3290      * @hide
3291      */
3292     @ViewDebug.ExportedProperty(category = "padding")
3293     protected int mUserPaddingRight;
3294 
3295     /**
3296      * Cache the paddingBottom set by the user to append to the scrollbar's size.
3297      *
3298      * @hide
3299      */
3300     @ViewDebug.ExportedProperty(category = "padding")
3301     protected int mUserPaddingBottom;
3302 
3303     /**
3304      * Cache the paddingLeft set by the user to append to the scrollbar's size.
3305      *
3306      * @hide
3307      */
3308     @ViewDebug.ExportedProperty(category = "padding")
3309     protected int mUserPaddingLeft;
3310 
3311     /**
3312      * Cache the paddingStart set by the user to append to the scrollbar's size.
3313      *
3314      */
3315     @ViewDebug.ExportedProperty(category = "padding")
3316     int mUserPaddingStart;
3317 
3318     /**
3319      * Cache the paddingEnd set by the user to append to the scrollbar's size.
3320      *
3321      */
3322     @ViewDebug.ExportedProperty(category = "padding")
3323     int mUserPaddingEnd;
3324 
3325     /**
3326      * Cache initial left padding.
3327      *
3328      * @hide
3329      */
3330     int mUserPaddingLeftInitial;
3331 
3332     /**
3333      * Cache initial right padding.
3334      *
3335      * @hide
3336      */
3337     int mUserPaddingRightInitial;
3338 
3339     /**
3340      * Default undefined padding
3341      */
3342     private static final int UNDEFINED_PADDING = Integer.MIN_VALUE;
3343 
3344     /**
3345      * Cache if a left padding has been defined
3346      */
3347     private boolean mLeftPaddingDefined = false;
3348 
3349     /**
3350      * Cache if a right padding has been defined
3351      */
3352     private boolean mRightPaddingDefined = false;
3353 
3354     /**
3355      * @hide
3356      */
3357     int mOldWidthMeasureSpec = Integer.MIN_VALUE;
3358     /**
3359      * @hide
3360      */
3361     int mOldHeightMeasureSpec = Integer.MIN_VALUE;
3362 
3363     private LongSparseLongArray mMeasureCache;
3364 
3365     @ViewDebug.ExportedProperty(deepExport = true, prefix = "bg_")
3366     private Drawable mBackground;
3367     private TintInfo mBackgroundTint;
3368 
3369     @ViewDebug.ExportedProperty(deepExport = true, prefix = "fg_")
3370     private ForegroundInfo mForegroundInfo;
3371 
3372     private Drawable mScrollIndicatorDrawable;
3373 
3374     /**
3375      * RenderNode used for backgrounds.
3376      * <p>
3377      * When non-null and valid, this is expected to contain an up-to-date copy
3378      * of the background drawable. It is cleared on temporary detach, and reset
3379      * on cleanup.
3380      */
3381     private RenderNode mBackgroundRenderNode;
3382 
3383     private int mBackgroundResource;
3384     private boolean mBackgroundSizeChanged;
3385 
3386     private String mTransitionName;
3387 
3388     static class TintInfo {
3389         ColorStateList mTintList;
3390         PorterDuff.Mode mTintMode;
3391         boolean mHasTintMode;
3392         boolean mHasTintList;
3393     }
3394 
3395     private static class ForegroundInfo {
3396         private Drawable mDrawable;
3397         private TintInfo mTintInfo;
3398         private int mGravity = Gravity.FILL;
3399         private boolean mInsidePadding = true;
3400         private boolean mBoundsChanged = true;
3401         private final Rect mSelfBounds = new Rect();
3402         private final Rect mOverlayBounds = new Rect();
3403     }
3404 
3405     static class ListenerInfo {
3406         /**
3407          * Listener used to dispatch focus change events.
3408          * This field should be made private, so it is hidden from the SDK.
3409          * {@hide}
3410          */
3411         protected OnFocusChangeListener mOnFocusChangeListener;
3412 
3413         /**
3414          * Listeners for layout change events.
3415          */
3416         private ArrayList<OnLayoutChangeListener> mOnLayoutChangeListeners;
3417 
3418         protected OnScrollChangeListener mOnScrollChangeListener;
3419 
3420         /**
3421          * Listeners for attach events.
3422          */
3423         private CopyOnWriteArrayList<OnAttachStateChangeListener> mOnAttachStateChangeListeners;
3424 
3425         /**
3426          * Listener used to dispatch click events.
3427          * This field should be made private, so it is hidden from the SDK.
3428          * {@hide}
3429          */
3430         public OnClickListener mOnClickListener;
3431 
3432         /**
3433          * Listener used to dispatch long click events.
3434          * This field should be made private, so it is hidden from the SDK.
3435          * {@hide}
3436          */
3437         protected OnLongClickListener mOnLongClickListener;
3438 
3439         /**
3440          * Listener used to dispatch context click events. This field should be made private, so it
3441          * is hidden from the SDK.
3442          * {@hide}
3443          */
3444         protected OnContextClickListener mOnContextClickListener;
3445 
3446         /**
3447          * Listener used to build the context menu.
3448          * This field should be made private, so it is hidden from the SDK.
3449          * {@hide}
3450          */
3451         protected OnCreateContextMenuListener mOnCreateContextMenuListener;
3452 
3453         private OnKeyListener mOnKeyListener;
3454 
3455         private OnTouchListener mOnTouchListener;
3456 
3457         private OnHoverListener mOnHoverListener;
3458 
3459         private OnGenericMotionListener mOnGenericMotionListener;
3460 
3461         private OnDragListener mOnDragListener;
3462 
3463         private OnSystemUiVisibilityChangeListener mOnSystemUiVisibilityChangeListener;
3464 
3465         OnApplyWindowInsetsListener mOnApplyWindowInsetsListener;
3466     }
3467 
3468     ListenerInfo mListenerInfo;
3469 
3470     /**
3471      * The application environment this view lives in.
3472      * This field should be made private, so it is hidden from the SDK.
3473      * {@hide}
3474      */
3475     @ViewDebug.ExportedProperty(deepExport = true)
3476     protected Context mContext;
3477 
3478     private final Resources mResources;
3479 
3480     private ScrollabilityCache mScrollCache;
3481 
3482     private int[] mDrawableState = null;
3483 
3484     ViewOutlineProvider mOutlineProvider = ViewOutlineProvider.BACKGROUND;
3485 
3486     /**
3487      * Animator that automatically runs based on state changes.
3488      */
3489     private StateListAnimator mStateListAnimator;
3490 
3491     /**
3492      * When this view has focus and the next focus is {@link #FOCUS_LEFT},
3493      * the user may specify which view to go to next.
3494      */
3495     private int mNextFocusLeftId = View.NO_ID;
3496 
3497     /**
3498      * When this view has focus and the next focus is {@link #FOCUS_RIGHT},
3499      * the user may specify which view to go to next.
3500      */
3501     private int mNextFocusRightId = View.NO_ID;
3502 
3503     /**
3504      * When this view has focus and the next focus is {@link #FOCUS_UP},
3505      * the user may specify which view to go to next.
3506      */
3507     private int mNextFocusUpId = View.NO_ID;
3508 
3509     /**
3510      * When this view has focus and the next focus is {@link #FOCUS_DOWN},
3511      * the user may specify which view to go to next.
3512      */
3513     private int mNextFocusDownId = View.NO_ID;
3514 
3515     /**
3516      * When this view has focus and the next focus is {@link #FOCUS_FORWARD},
3517      * the user may specify which view to go to next.
3518      */
3519     int mNextFocusForwardId = View.NO_ID;
3520 
3521     private CheckForLongPress mPendingCheckForLongPress;
3522     private CheckForTap mPendingCheckForTap = null;
3523     private PerformClick mPerformClick;
3524     private SendViewScrolledAccessibilityEvent mSendViewScrolledAccessibilityEvent;
3525 
3526     private UnsetPressedState mUnsetPressedState;
3527 
3528     /**
3529      * Whether the long press's action has been invoked.  The tap's action is invoked on the
3530      * up event while a long press is invoked as soon as the long press duration is reached, so
3531      * a long press could be performed before the tap is checked, in which case the tap's action
3532      * should not be invoked.
3533      */
3534     private boolean mHasPerformedLongPress;
3535 
3536     /**
3537      * Whether a context click button is currently pressed down. This is true when the stylus is
3538      * touching the screen and the primary button has been pressed, or if a mouse's right button is
3539      * pressed. This is false once the button is released or if the stylus has been lifted.
3540      */
3541     private boolean mInContextButtonPress;
3542 
3543     /**
3544      * Whether the next up event should be ignored for the purposes of gesture recognition. This is
3545      * true after a stylus button press has occured, when the next up event should not be recognized
3546      * as a tap.
3547      */
3548     private boolean mIgnoreNextUpEvent;
3549 
3550     /**
3551      * The minimum height of the view. We'll try our best to have the height
3552      * of this view to at least this amount.
3553      */
3554     @ViewDebug.ExportedProperty(category = "measurement")
3555     private int mMinHeight;
3556 
3557     /**
3558      * The minimum width of the view. We'll try our best to have the width
3559      * of this view to at least this amount.
3560      */
3561     @ViewDebug.ExportedProperty(category = "measurement")
3562     private int mMinWidth;
3563 
3564     /**
3565      * The delegate to handle touch events that are physically in this view
3566      * but should be handled by another view.
3567      */
3568     private TouchDelegate mTouchDelegate = null;
3569 
3570     /**
3571      * Solid color to use as a background when creating the drawing cache. Enables
3572      * the cache to use 16 bit bitmaps instead of 32 bit.
3573      */
3574     private int mDrawingCacheBackgroundColor = 0;
3575 
3576     /**
3577      * Special tree observer used when mAttachInfo is null.
3578      */
3579     private ViewTreeObserver mFloatingTreeObserver;
3580 
3581     /**
3582      * Cache the touch slop from the context that created the view.
3583      */
3584     private int mTouchSlop;
3585 
3586     /**
3587      * Object that handles automatic animation of view properties.
3588      */
3589     private ViewPropertyAnimator mAnimator = null;
3590 
3591     /**
3592      * Flag indicating that a drag can cross window boundaries.  When
3593      * {@link #startDrag(ClipData, DragShadowBuilder, Object, int)} is called
3594      * with this flag set, all visible applications will be able to participate
3595      * in the drag operation and receive the dragged content.
3596      *
3597      * @hide
3598      */
3599     public static final int DRAG_FLAG_GLOBAL = 1;
3600 
3601     /**
3602      * Vertical scroll factor cached by {@link #getVerticalScrollFactor}.
3603      */
3604     private float mVerticalScrollFactor;
3605 
3606     /**
3607      * Position of the vertical scroll bar.
3608      */
3609     private int mVerticalScrollbarPosition;
3610 
3611     /**
3612      * Position the scroll bar at the default position as determined by the system.
3613      */
3614     public static final int SCROLLBAR_POSITION_DEFAULT = 0;
3615 
3616     /**
3617      * Position the scroll bar along the left edge.
3618      */
3619     public static final int SCROLLBAR_POSITION_LEFT = 1;
3620 
3621     /**
3622      * Position the scroll bar along the right edge.
3623      */
3624     public static final int SCROLLBAR_POSITION_RIGHT = 2;
3625 
3626     /**
3627      * Indicates that the view does not have a layer.
3628      *
3629      * @see #getLayerType()
3630      * @see #setLayerType(int, android.graphics.Paint)
3631      * @see #LAYER_TYPE_SOFTWARE
3632      * @see #LAYER_TYPE_HARDWARE
3633      */
3634     public static final int LAYER_TYPE_NONE = 0;
3635 
3636     /**
3637      * <p>Indicates that the view has a software layer. A software layer is backed
3638      * by a bitmap and causes the view to be rendered using Android's software
3639      * rendering pipeline, even if hardware acceleration is enabled.</p>
3640      *
3641      * <p>Software layers have various usages:</p>
3642      * <p>When the application is not using hardware acceleration, a software layer
3643      * is useful to apply a specific color filter and/or blending mode and/or
3644      * translucency to a view and all its children.</p>
3645      * <p>When the application is using hardware acceleration, a software layer
3646      * is useful to render drawing primitives not supported by the hardware
3647      * accelerated pipeline. It can also be used to cache a complex view tree
3648      * into a texture and reduce the complexity of drawing operations. For instance,
3649      * when animating a complex view tree with a translation, a software layer can
3650      * be used to render the view tree only once.</p>
3651      * <p>Software layers should be avoided when the affected view tree updates
3652      * often. Every update will require to re-render the software layer, which can
3653      * potentially be slow (particularly when hardware acceleration is turned on
3654      * since the layer will have to be uploaded into a hardware texture after every
3655      * update.)</p>
3656      *
3657      * @see #getLayerType()
3658      * @see #setLayerType(int, android.graphics.Paint)
3659      * @see #LAYER_TYPE_NONE
3660      * @see #LAYER_TYPE_HARDWARE
3661      */
3662     public static final int LAYER_TYPE_SOFTWARE = 1;
3663 
3664     /**
3665      * <p>Indicates that the view has a hardware layer. A hardware layer is backed
3666      * by a hardware specific texture (generally Frame Buffer Objects or FBO on
3667      * OpenGL hardware) and causes the view to be rendered using Android's hardware
3668      * rendering pipeline, but only if hardware acceleration is turned on for the
3669      * view hierarchy. When hardware acceleration is turned off, hardware layers
3670      * behave exactly as {@link #LAYER_TYPE_SOFTWARE software layers}.</p>
3671      *
3672      * <p>A hardware layer is useful to apply a specific color filter and/or
3673      * blending mode and/or translucency to a view and all its children.</p>
3674      * <p>A hardware layer can be used to cache a complex view tree into a
3675      * texture and reduce the complexity of drawing operations. For instance,
3676      * when animating a complex view tree with a translation, a hardware layer can
3677      * be used to render the view tree only once.</p>
3678      * <p>A hardware layer can also be used to increase the rendering quality when
3679      * rotation transformations are applied on a view. It can also be used to
3680      * prevent potential clipping issues when applying 3D transforms on a view.</p>
3681      *
3682      * @see #getLayerType()
3683      * @see #setLayerType(int, android.graphics.Paint)
3684      * @see #LAYER_TYPE_NONE
3685      * @see #LAYER_TYPE_SOFTWARE
3686      */
3687     public static final int LAYER_TYPE_HARDWARE = 2;
3688 
3689     @ViewDebug.ExportedProperty(category = "drawing", mapping = {
3690             @ViewDebug.IntToString(from = LAYER_TYPE_NONE, to = "NONE"),
3691             @ViewDebug.IntToString(from = LAYER_TYPE_SOFTWARE, to = "SOFTWARE"),
3692             @ViewDebug.IntToString(from = LAYER_TYPE_HARDWARE, to = "HARDWARE")
3693     })
3694     int mLayerType = LAYER_TYPE_NONE;
3695     Paint mLayerPaint;
3696 
3697     /**
3698      * Set to true when drawing cache is enabled and cannot be created.
3699      *
3700      * @hide
3701      */
3702     public boolean mCachingFailed;
3703     private Bitmap mDrawingCache;
3704     private Bitmap mUnscaledDrawingCache;
3705 
3706     /**
3707      * RenderNode holding View properties, potentially holding a DisplayList of View content.
3708      * <p>
3709      * When non-null and valid, this is expected to contain an up-to-date copy
3710      * of the View content. Its DisplayList content is cleared on temporary detach and reset on
3711      * cleanup.
3712      */
3713     final RenderNode mRenderNode;
3714 
3715     /**
3716      * Set to true when the view is sending hover accessibility events because it
3717      * is the innermost hovered view.
3718      */
3719     private boolean mSendingHoverAccessibilityEvents;
3720 
3721     /**
3722      * Delegate for injecting accessibility functionality.
3723      */
3724     AccessibilityDelegate mAccessibilityDelegate;
3725 
3726     /**
3727      * The view's overlay layer. Developers get a reference to the overlay via getOverlay()
3728      * and add/remove objects to/from the overlay directly through the Overlay methods.
3729      */
3730     ViewOverlay mOverlay;
3731 
3732     /**
3733      * The currently active parent view for receiving delegated nested scrolling events.
3734      * This is set by {@link #startNestedScroll(int)} during a touch interaction and cleared
3735      * by {@link #stopNestedScroll()} at the same point where we clear
3736      * requestDisallowInterceptTouchEvent.
3737      */
3738     private ViewParent mNestedScrollingParent;
3739 
3740     /**
3741      * Consistency verifier for debugging purposes.
3742      * @hide
3743      */
3744     protected final InputEventConsistencyVerifier mInputEventConsistencyVerifier =
3745             InputEventConsistencyVerifier.isInstrumentationEnabled() ?
3746                     new InputEventConsistencyVerifier(this, 0) : null;
3747 
3748     private static final AtomicInteger sNextGeneratedId = new AtomicInteger(1);
3749 
3750     private int[] mTempNestedScrollConsumed;
3751 
3752     /**
3753      * An overlay is going to draw this View instead of being drawn as part of this
3754      * View's parent. mGhostView is the View in the Overlay that must be invalidated
3755      * when this view is invalidated.
3756      */
3757     GhostView mGhostView;
3758 
3759     /**
3760      * Holds pairs of adjacent attribute data: attribute name followed by its value.
3761      * @hide
3762      */
3763     @ViewDebug.ExportedProperty(category = "attributes", hasAdjacentMapping = true)
3764     public String[] mAttributes;
3765 
3766     /**
3767      * Maps a Resource id to its name.
3768      */
3769     private static SparseArray<String> mAttributeMap;
3770 
3771     /**
3772      * @hide
3773      */
3774     String mStartActivityRequestWho;
3775 
3776     /**
3777      * Simple constructor to use when creating a view from code.
3778      *
3779      * @param context The Context the view is running in, through which it can
3780      *        access the current theme, resources, etc.
3781      */
View(Context context)3782     public View(Context context) {
3783         mContext = context;
3784         mResources = context != null ? context.getResources() : null;
3785         mViewFlags = SOUND_EFFECTS_ENABLED | HAPTIC_FEEDBACK_ENABLED;
3786         // Set some flags defaults
3787         mPrivateFlags2 =
3788                 (LAYOUT_DIRECTION_DEFAULT << PFLAG2_LAYOUT_DIRECTION_MASK_SHIFT) |
3789                 (TEXT_DIRECTION_DEFAULT << PFLAG2_TEXT_DIRECTION_MASK_SHIFT) |
3790                 (PFLAG2_TEXT_DIRECTION_RESOLVED_DEFAULT) |
3791                 (TEXT_ALIGNMENT_DEFAULT << PFLAG2_TEXT_ALIGNMENT_MASK_SHIFT) |
3792                 (PFLAG2_TEXT_ALIGNMENT_RESOLVED_DEFAULT) |
3793                 (IMPORTANT_FOR_ACCESSIBILITY_DEFAULT << PFLAG2_IMPORTANT_FOR_ACCESSIBILITY_SHIFT);
3794         mTouchSlop = ViewConfiguration.get(context).getScaledTouchSlop();
3795         setOverScrollMode(OVER_SCROLL_IF_CONTENT_SCROLLS);
3796         mUserPaddingStart = UNDEFINED_PADDING;
3797         mUserPaddingEnd = UNDEFINED_PADDING;
3798         mRenderNode = RenderNode.create(getClass().getName(), this);
3799 
3800         if (!sCompatibilityDone && context != null) {
3801             final int targetSdkVersion = context.getApplicationInfo().targetSdkVersion;
3802 
3803             // Older apps may need this compatibility hack for measurement.
3804             sUseBrokenMakeMeasureSpec = targetSdkVersion <= JELLY_BEAN_MR1;
3805 
3806             // Older apps expect onMeasure() to always be called on a layout pass, regardless
3807             // of whether a layout was requested on that View.
3808             sIgnoreMeasureCache = targetSdkVersion < KITKAT;
3809 
3810             Canvas.sCompatibilityRestore = targetSdkVersion < M;
3811 
3812             // In M and newer, our widgets can pass a "hint" value in the size
3813             // for UNSPECIFIED MeasureSpecs. This lets child views of scrolling containers
3814             // know what the expected parent size is going to be, so e.g. list items can size
3815             // themselves at 1/3 the size of their container. It breaks older apps though,
3816             // specifically apps that use some popular open source libraries.
3817             sUseZeroUnspecifiedMeasureSpec = targetSdkVersion < M;
3818 
3819             sCompatibilityDone = true;
3820         }
3821     }
3822 
3823     /**
3824      * Constructor that is called when inflating a view from XML. This is called
3825      * when a view is being constructed from an XML file, supplying attributes
3826      * that were specified in the XML file. This version uses a default style of
3827      * 0, so the only attribute values applied are those in the Context's Theme
3828      * and the given AttributeSet.
3829      *
3830      * <p>
3831      * The method onFinishInflate() will be called after all children have been
3832      * added.
3833      *
3834      * @param context The Context the view is running in, through which it can
3835      *        access the current theme, resources, etc.
3836      * @param attrs The attributes of the XML tag that is inflating the view.
3837      * @see #View(Context, AttributeSet, int)
3838      */
3839     public View(Context context, @Nullable AttributeSet attrs) {
3840         this(context, attrs, 0);
3841     }
3842 
3843     /**
3844      * Perform inflation from XML and apply a class-specific base style from a
3845      * theme attribute. This constructor of View allows subclasses to use their
3846      * own base style when they are inflating. For example, a Button class's
3847      * constructor would call this version of the super class constructor and
3848      * supply <code>R.attr.buttonStyle</code> for <var>defStyleAttr</var>; this
3849      * allows the theme's button style to modify all of the base view attributes
3850      * (in particular its background) as well as the Button class's attributes.
3851      *
3852      * @param context The Context the view is running in, through which it can
3853      *        access the current theme, resources, etc.
3854      * @param attrs The attributes of the XML tag that is inflating the view.
3855      * @param defStyleAttr An attribute in the current theme that contains a
3856      *        reference to a style resource that supplies default values for
3857      *        the view. Can be 0 to not look for defaults.
3858      * @see #View(Context, AttributeSet)
3859      */
3860     public View(Context context, @Nullable AttributeSet attrs, int defStyleAttr) {
3861         this(context, attrs, defStyleAttr, 0);
3862     }
3863 
3864     /**
3865      * Perform inflation from XML and apply a class-specific base style from a
3866      * theme attribute or style resource. This constructor of View allows
3867      * subclasses to use their own base style when they are inflating.
3868      * <p>
3869      * When determining the final value of a particular attribute, there are
3870      * four inputs that come into play:
3871      * <ol>
3872      * <li>Any attribute values in the given AttributeSet.
3873      * <li>The style resource specified in the AttributeSet (named "style").
3874      * <li>The default style specified by <var>defStyleAttr</var>.
3875      * <li>The default style specified by <var>defStyleRes</var>.
3876      * <li>The base values in this theme.
3877      * </ol>
3878      * <p>
3879      * Each of these inputs is considered in-order, with the first listed taking
3880      * precedence over the following ones. In other words, if in the
3881      * AttributeSet you have supplied <code>&lt;Button * textColor="#ff000000"&gt;</code>
3882      * , then the button's text will <em>always</em> be black, regardless of
3883      * what is specified in any of the styles.
3884      *
3885      * @param context The Context the view is running in, through which it can
3886      *        access the current theme, resources, etc.
3887      * @param attrs The attributes of the XML tag that is inflating the view.
3888      * @param defStyleAttr An attribute in the current theme that contains a
3889      *        reference to a style resource that supplies default values for
3890      *        the view. Can be 0 to not look for defaults.
3891      * @param defStyleRes A resource identifier of a style resource that
3892      *        supplies default values for the view, used only if
3893      *        defStyleAttr is 0 or can not be found in the theme. Can be 0
3894      *        to not look for defaults.
3895      * @see #View(Context, AttributeSet, int)
3896      */
3897     public View(Context context, @Nullable AttributeSet attrs, int defStyleAttr, int defStyleRes) {
3898         this(context);
3899 
3900         final TypedArray a = context.obtainStyledAttributes(
3901                 attrs, com.android.internal.R.styleable.View, defStyleAttr, defStyleRes);
3902 
3903         if (mDebugViewAttributes) {
3904             saveAttributeData(attrs, a);
3905         }
3906 
3907         Drawable background = null;
3908 
3909         int leftPadding = -1;
3910         int topPadding = -1;
3911         int rightPadding = -1;
3912         int bottomPadding = -1;
3913         int startPadding = UNDEFINED_PADDING;
3914         int endPadding = UNDEFINED_PADDING;
3915 
3916         int padding = -1;
3917 
3918         int viewFlagValues = 0;
3919         int viewFlagMasks = 0;
3920 
3921         boolean setScrollContainer = false;
3922 
3923         int x = 0;
3924         int y = 0;
3925 
3926         float tx = 0;
3927         float ty = 0;
3928         float tz = 0;
3929         float elevation = 0;
3930         float rotation = 0;
3931         float rotationX = 0;
3932         float rotationY = 0;
3933         float sx = 1f;
3934         float sy = 1f;
3935         boolean transformSet = false;
3936 
3937         int scrollbarStyle = SCROLLBARS_INSIDE_OVERLAY;
3938         int overScrollMode = mOverScrollMode;
3939         boolean initializeScrollbars = false;
3940         boolean initializeScrollIndicators = false;
3941 
3942         boolean startPaddingDefined = false;
3943         boolean endPaddingDefined = false;
3944         boolean leftPaddingDefined = false;
3945         boolean rightPaddingDefined = false;
3946 
3947         final int targetSdkVersion = context.getApplicationInfo().targetSdkVersion;
3948 
3949         final int N = a.getIndexCount();
3950         for (int i = 0; i < N; i++) {
3951             int attr = a.getIndex(i);
3952             switch (attr) {
3953                 case com.android.internal.R.styleable.View_background:
3954                     background = a.getDrawable(attr);
3955                     break;
3956                 case com.android.internal.R.styleable.View_padding:
3957                     padding = a.getDimensionPixelSize(attr, -1);
3958                     mUserPaddingLeftInitial = padding;
3959                     mUserPaddingRightInitial = padding;
3960                     leftPaddingDefined = true;
3961                     rightPaddingDefined = true;
3962                     break;
3963                  case com.android.internal.R.styleable.View_paddingLeft:
3964                     leftPadding = a.getDimensionPixelSize(attr, -1);
3965                     mUserPaddingLeftInitial = leftPadding;
3966                     leftPaddingDefined = true;
3967                     break;
3968                 case com.android.internal.R.styleable.View_paddingTop:
3969                     topPadding = a.getDimensionPixelSize(attr, -1);
3970                     break;
3971                 case com.android.internal.R.styleable.View_paddingRight:
3972                     rightPadding = a.getDimensionPixelSize(attr, -1);
3973                     mUserPaddingRightInitial = rightPadding;
3974                     rightPaddingDefined = true;
3975                     break;
3976                 case com.android.internal.R.styleable.View_paddingBottom:
3977                     bottomPadding = a.getDimensionPixelSize(attr, -1);
3978                     break;
3979                 case com.android.internal.R.styleable.View_paddingStart:
3980                     startPadding = a.getDimensionPixelSize(attr, UNDEFINED_PADDING);
3981                     startPaddingDefined = (startPadding != UNDEFINED_PADDING);
3982                     break;
3983                 case com.android.internal.R.styleable.View_paddingEnd:
3984                     endPadding = a.getDimensionPixelSize(attr, UNDEFINED_PADDING);
3985                     endPaddingDefined = (endPadding != UNDEFINED_PADDING);
3986                     break;
3987                 case com.android.internal.R.styleable.View_scrollX:
3988                     x = a.getDimensionPixelOffset(attr, 0);
3989                     break;
3990                 case com.android.internal.R.styleable.View_scrollY:
3991                     y = a.getDimensionPixelOffset(attr, 0);
3992                     break;
3993                 case com.android.internal.R.styleable.View_alpha:
3994                     setAlpha(a.getFloat(attr, 1f));
3995                     break;
3996                 case com.android.internal.R.styleable.View_transformPivotX:
3997                     setPivotX(a.getDimensionPixelOffset(attr, 0));
3998                     break;
3999                 case com.android.internal.R.styleable.View_transformPivotY:
4000                     setPivotY(a.getDimensionPixelOffset(attr, 0));
4001                     break;
4002                 case com.android.internal.R.styleable.View_translationX:
4003                     tx = a.getDimensionPixelOffset(attr, 0);
4004                     transformSet = true;
4005                     break;
4006                 case com.android.internal.R.styleable.View_translationY:
4007                     ty = a.getDimensionPixelOffset(attr, 0);
4008                     transformSet = true;
4009                     break;
4010                 case com.android.internal.R.styleable.View_translationZ:
4011                     tz = a.getDimensionPixelOffset(attr, 0);
4012                     transformSet = true;
4013                     break;
4014                 case com.android.internal.R.styleable.View_elevation:
4015                     elevation = a.getDimensionPixelOffset(attr, 0);
4016                     transformSet = true;
4017                     break;
4018                 case com.android.internal.R.styleable.View_rotation:
4019                     rotation = a.getFloat(attr, 0);
4020                     transformSet = true;
4021                     break;
4022                 case com.android.internal.R.styleable.View_rotationX:
4023                     rotationX = a.getFloat(attr, 0);
4024                     transformSet = true;
4025                     break;
4026                 case com.android.internal.R.styleable.View_rotationY:
4027                     rotationY = a.getFloat(attr, 0);
4028                     transformSet = true;
4029                     break;
4030                 case com.android.internal.R.styleable.View_scaleX:
4031                     sx = a.getFloat(attr, 1f);
4032                     transformSet = true;
4033                     break;
4034                 case com.android.internal.R.styleable.View_scaleY:
4035                     sy = a.getFloat(attr, 1f);
4036                     transformSet = true;
4037                     break;
4038                 case com.android.internal.R.styleable.View_id:
4039                     mID = a.getResourceId(attr, NO_ID);
4040                     break;
4041                 case com.android.internal.R.styleable.View_tag:
4042                     mTag = a.getText(attr);
4043                     break;
4044                 case com.android.internal.R.styleable.View_fitsSystemWindows:
4045                     if (a.getBoolean(attr, false)) {
4046                         viewFlagValues |= FITS_SYSTEM_WINDOWS;
4047                         viewFlagMasks |= FITS_SYSTEM_WINDOWS;
4048                     }
4049                     break;
4050                 case com.android.internal.R.styleable.View_focusable:
4051                     if (a.getBoolean(attr, false)) {
4052                         viewFlagValues |= FOCUSABLE;
4053                         viewFlagMasks |= FOCUSABLE_MASK;
4054                     }
4055                     break;
4056                 case com.android.internal.R.styleable.View_focusableInTouchMode:
4057                     if (a.getBoolean(attr, false)) {
4058                         viewFlagValues |= FOCUSABLE_IN_TOUCH_MODE | FOCUSABLE;
4059                         viewFlagMasks |= FOCUSABLE_IN_TOUCH_MODE | FOCUSABLE_MASK;
4060                     }
4061                     break;
4062                 case com.android.internal.R.styleable.View_clickable:
4063                     if (a.getBoolean(attr, false)) {
4064                         viewFlagValues |= CLICKABLE;
4065                         viewFlagMasks |= CLICKABLE;
4066                     }
4067                     break;
4068                 case com.android.internal.R.styleable.View_longClickable:
4069                     if (a.getBoolean(attr, false)) {
4070                         viewFlagValues |= LONG_CLICKABLE;
4071                         viewFlagMasks |= LONG_CLICKABLE;
4072                     }
4073                     break;
4074                 case com.android.internal.R.styleable.View_contextClickable:
4075                     if (a.getBoolean(attr, false)) {
4076                         viewFlagValues |= CONTEXT_CLICKABLE;
4077                         viewFlagMasks |= CONTEXT_CLICKABLE;
4078                     }
4079                     break;
4080                 case com.android.internal.R.styleable.View_saveEnabled:
4081                     if (!a.getBoolean(attr, true)) {
4082                         viewFlagValues |= SAVE_DISABLED;
4083                         viewFlagMasks |= SAVE_DISABLED_MASK;
4084                     }
4085                     break;
4086                 case com.android.internal.R.styleable.View_duplicateParentState:
4087                     if (a.getBoolean(attr, false)) {
4088                         viewFlagValues |= DUPLICATE_PARENT_STATE;
4089                         viewFlagMasks |= DUPLICATE_PARENT_STATE;
4090                     }
4091                     break;
4092                 case com.android.internal.R.styleable.View_visibility:
4093                     final int visibility = a.getInt(attr, 0);
4094                     if (visibility != 0) {
4095                         viewFlagValues |= VISIBILITY_FLAGS[visibility];
4096                         viewFlagMasks |= VISIBILITY_MASK;
4097                     }
4098                     break;
4099                 case com.android.internal.R.styleable.View_layoutDirection:
4100                     // Clear any layout direction flags (included resolved bits) already set
4101                     mPrivateFlags2 &=
4102                             ~(PFLAG2_LAYOUT_DIRECTION_MASK | PFLAG2_LAYOUT_DIRECTION_RESOLVED_MASK);
4103                     // Set the layout direction flags depending on the value of the attribute
4104                     final int layoutDirection = a.getInt(attr, -1);
4105                     final int value = (layoutDirection != -1) ?
4106                             LAYOUT_DIRECTION_FLAGS[layoutDirection] : LAYOUT_DIRECTION_DEFAULT;
4107                     mPrivateFlags2 |= (value << PFLAG2_LAYOUT_DIRECTION_MASK_SHIFT);
4108                     break;
4109                 case com.android.internal.R.styleable.View_drawingCacheQuality:
4110                     final int cacheQuality = a.getInt(attr, 0);
4111                     if (cacheQuality != 0) {
4112                         viewFlagValues |= DRAWING_CACHE_QUALITY_FLAGS[cacheQuality];
4113                         viewFlagMasks |= DRAWING_CACHE_QUALITY_MASK;
4114                     }
4115                     break;
4116                 case com.android.internal.R.styleable.View_contentDescription:
4117                     setContentDescription(a.getString(attr));
4118                     break;
4119                 case com.android.internal.R.styleable.View_accessibilityTraversalBefore:
4120                     setAccessibilityTraversalBefore(a.getResourceId(attr, NO_ID));
4121                     break;
4122                 case com.android.internal.R.styleable.View_accessibilityTraversalAfter:
4123                     setAccessibilityTraversalAfter(a.getResourceId(attr, NO_ID));
4124                     break;
4125                 case com.android.internal.R.styleable.View_labelFor:
4126                     setLabelFor(a.getResourceId(attr, NO_ID));
4127                     break;
4128                 case com.android.internal.R.styleable.View_soundEffectsEnabled:
4129                     if (!a.getBoolean(attr, true)) {
4130                         viewFlagValues &= ~SOUND_EFFECTS_ENABLED;
4131                         viewFlagMasks |= SOUND_EFFECTS_ENABLED;
4132                     }
4133                     break;
4134                 case com.android.internal.R.styleable.View_hapticFeedbackEnabled:
4135                     if (!a.getBoolean(attr, true)) {
4136                         viewFlagValues &= ~HAPTIC_FEEDBACK_ENABLED;
4137                         viewFlagMasks |= HAPTIC_FEEDBACK_ENABLED;
4138                     }
4139                     break;
4140                 case R.styleable.View_scrollbars:
4141                     final int scrollbars = a.getInt(attr, SCROLLBARS_NONE);
4142                     if (scrollbars != SCROLLBARS_NONE) {
4143                         viewFlagValues |= scrollbars;
4144                         viewFlagMasks |= SCROLLBARS_MASK;
4145                         initializeScrollbars = true;
4146                     }
4147                     break;
4148                 //noinspection deprecation
4149                 case R.styleable.View_fadingEdge:
4150                     if (targetSdkVersion >= ICE_CREAM_SANDWICH) {
4151                         // Ignore the attribute starting with ICS
4152                         break;
4153                     }
4154                     // With builds < ICS, fall through and apply fading edges
4155                 case R.styleable.View_requiresFadingEdge:
4156                     final int fadingEdge = a.getInt(attr, FADING_EDGE_NONE);
4157                     if (fadingEdge != FADING_EDGE_NONE) {
4158                         viewFlagValues |= fadingEdge;
4159                         viewFlagMasks |= FADING_EDGE_MASK;
4160                         initializeFadingEdgeInternal(a);
4161                     }
4162                     break;
4163                 case R.styleable.View_scrollbarStyle:
4164                     scrollbarStyle = a.getInt(attr, SCROLLBARS_INSIDE_OVERLAY);
4165                     if (scrollbarStyle != SCROLLBARS_INSIDE_OVERLAY) {
4166                         viewFlagValues |= scrollbarStyle & SCROLLBARS_STYLE_MASK;
4167                         viewFlagMasks |= SCROLLBARS_STYLE_MASK;
4168                     }
4169                     break;
4170                 case R.styleable.View_isScrollContainer:
4171                     setScrollContainer = true;
4172                     if (a.getBoolean(attr, false)) {
4173                         setScrollContainer(true);
4174                     }
4175                     break;
4176                 case com.android.internal.R.styleable.View_keepScreenOn:
4177                     if (a.getBoolean(attr, false)) {
4178                         viewFlagValues |= KEEP_SCREEN_ON;
4179                         viewFlagMasks |= KEEP_SCREEN_ON;
4180                     }
4181                     break;
4182                 case R.styleable.View_filterTouchesWhenObscured:
4183                     if (a.getBoolean(attr, false)) {
4184                         viewFlagValues |= FILTER_TOUCHES_WHEN_OBSCURED;
4185                         viewFlagMasks |= FILTER_TOUCHES_WHEN_OBSCURED;
4186                     }
4187                     break;
4188                 case R.styleable.View_nextFocusLeft:
4189                     mNextFocusLeftId = a.getResourceId(attr, View.NO_ID);
4190                     break;
4191                 case R.styleable.View_nextFocusRight:
4192                     mNextFocusRightId = a.getResourceId(attr, View.NO_ID);
4193                     break;
4194                 case R.styleable.View_nextFocusUp:
4195                     mNextFocusUpId = a.getResourceId(attr, View.NO_ID);
4196                     break;
4197                 case R.styleable.View_nextFocusDown:
4198                     mNextFocusDownId = a.getResourceId(attr, View.NO_ID);
4199                     break;
4200                 case R.styleable.View_nextFocusForward:
4201                     mNextFocusForwardId = a.getResourceId(attr, View.NO_ID);
4202                     break;
4203                 case R.styleable.View_minWidth:
4204                     mMinWidth = a.getDimensionPixelSize(attr, 0);
4205                     break;
4206                 case R.styleable.View_minHeight:
4207                     mMinHeight = a.getDimensionPixelSize(attr, 0);
4208                     break;
4209                 case R.styleable.View_onClick:
4210                     if (context.isRestricted()) {
4211                         throw new IllegalStateException("The android:onClick attribute cannot "
4212                                 + "be used within a restricted context");
4213                     }
4214 
4215                     final String handlerName = a.getString(attr);
4216                     if (handlerName != null) {
4217                         setOnClickListener(new DeclaredOnClickListener(this, handlerName));
4218                     }
4219                     break;
4220                 case R.styleable.View_overScrollMode:
4221                     overScrollMode = a.getInt(attr, OVER_SCROLL_IF_CONTENT_SCROLLS);
4222                     break;
4223                 case R.styleable.View_verticalScrollbarPosition:
4224                     mVerticalScrollbarPosition = a.getInt(attr, SCROLLBAR_POSITION_DEFAULT);
4225                     break;
4226                 case R.styleable.View_layerType:
4227                     setLayerType(a.getInt(attr, LAYER_TYPE_NONE), null);
4228                     break;
4229                 case R.styleable.View_textDirection:
4230                     // Clear any text direction flag already set
4231                     mPrivateFlags2 &= ~PFLAG2_TEXT_DIRECTION_MASK;
4232                     // Set the text direction flags depending on the value of the attribute
4233                     final int textDirection = a.getInt(attr, -1);
4234                     if (textDirection != -1) {
4235                         mPrivateFlags2 |= PFLAG2_TEXT_DIRECTION_FLAGS[textDirection];
4236                     }
4237                     break;
4238                 case R.styleable.View_textAlignment:
4239                     // Clear any text alignment flag already set
4240                     mPrivateFlags2 &= ~PFLAG2_TEXT_ALIGNMENT_MASK;
4241                     // Set the text alignment flag depending on the value of the attribute
4242                     final int textAlignment = a.getInt(attr, TEXT_ALIGNMENT_DEFAULT);
4243                     mPrivateFlags2 |= PFLAG2_TEXT_ALIGNMENT_FLAGS[textAlignment];
4244                     break;
4245                 case R.styleable.View_importantForAccessibility:
4246                     setImportantForAccessibility(a.getInt(attr,
4247                             IMPORTANT_FOR_ACCESSIBILITY_DEFAULT));
4248                     break;
4249                 case R.styleable.View_accessibilityLiveRegion:
4250                     setAccessibilityLiveRegion(a.getInt(attr, ACCESSIBILITY_LIVE_REGION_DEFAULT));
4251                     break;
4252                 case R.styleable.View_transitionName:
4253                     setTransitionName(a.getString(attr));
4254                     break;
4255                 case R.styleable.View_nestedScrollingEnabled:
4256                     setNestedScrollingEnabled(a.getBoolean(attr, false));
4257                     break;
4258                 case R.styleable.View_stateListAnimator:
4259                     setStateListAnimator(AnimatorInflater.loadStateListAnimator(context,
4260                             a.getResourceId(attr, 0)));
4261                     break;
4262                 case R.styleable.View_backgroundTint:
4263                     // This will get applied later during setBackground().
4264                     if (mBackgroundTint == null) {
4265                         mBackgroundTint = new TintInfo();
4266                     }
4267                     mBackgroundTint.mTintList = a.getColorStateList(
4268                             R.styleable.View_backgroundTint);
4269                     mBackgroundTint.mHasTintList = true;
4270                     break;
4271                 case R.styleable.View_backgroundTintMode:
4272                     // This will get applied later during setBackground().
4273                     if (mBackgroundTint == null) {
4274                         mBackgroundTint = new TintInfo();
4275                     }
4276                     mBackgroundTint.mTintMode = Drawable.parseTintMode(a.getInt(
4277                             R.styleable.View_backgroundTintMode, -1), null);
4278                     mBackgroundTint.mHasTintMode = true;
4279                     break;
4280                 case R.styleable.View_outlineProvider:
4281                     setOutlineProviderFromAttribute(a.getInt(R.styleable.View_outlineProvider,
4282                             PROVIDER_BACKGROUND));
4283                     break;
4284                 case R.styleable.View_foreground:
4285                     if (targetSdkVersion >= VERSION_CODES.M || this instanceof FrameLayout) {
4286                         setForeground(a.getDrawable(attr));
4287                     }
4288                     break;
4289                 case R.styleable.View_foregroundGravity:
4290                     if (targetSdkVersion >= VERSION_CODES.M || this instanceof FrameLayout) {
4291                         setForegroundGravity(a.getInt(attr, Gravity.NO_GRAVITY));
4292                     }
4293                     break;
4294                 case R.styleable.View_foregroundTintMode:
4295                     if (targetSdkVersion >= VERSION_CODES.M || this instanceof FrameLayout) {
4296                         setForegroundTintMode(Drawable.parseTintMode(a.getInt(attr, -1), null));
4297                     }
4298                     break;
4299                 case R.styleable.View_foregroundTint:
4300                     if (targetSdkVersion >= VERSION_CODES.M || this instanceof FrameLayout) {
4301                         setForegroundTintList(a.getColorStateList(attr));
4302                     }
4303                     break;
4304                 case R.styleable.View_foregroundInsidePadding:
4305                     if (targetSdkVersion >= VERSION_CODES.M || this instanceof FrameLayout) {
4306                         if (mForegroundInfo == null) {
4307                             mForegroundInfo = new ForegroundInfo();
4308                         }
4309                         mForegroundInfo.mInsidePadding = a.getBoolean(attr,
4310                                 mForegroundInfo.mInsidePadding);
4311                     }
4312                     break;
4313                 case R.styleable.View_scrollIndicators:
4314                     final int scrollIndicators =
4315                             (a.getInt(attr, 0) << SCROLL_INDICATORS_TO_PFLAGS3_LSHIFT)
4316                                     & SCROLL_INDICATORS_PFLAG3_MASK;
4317                     if (scrollIndicators != 0) {
4318                         mPrivateFlags3 |= scrollIndicators;
4319                         initializeScrollIndicators = true;
4320                     }
4321                     break;
4322             }
4323         }
4324 
setOverScrollMode(overScrollMode)4325         setOverScrollMode(overScrollMode);
4326 
4327         // Cache start/end user padding as we cannot fully resolve padding here (we dont have yet
4328         // the resolved layout direction). Those cached values will be used later during padding
4329         // resolution.
4330         mUserPaddingStart = startPadding;
4331         mUserPaddingEnd = endPadding;
4332 
4333         if (background != null) {
4334             setBackground(background);
4335         }
4336 
4337         // setBackground above will record that padding is currently provided by the background.
4338         // If we have padding specified via xml, record that here instead and use it.
4339         mLeftPaddingDefined = leftPaddingDefined;
4340         mRightPaddingDefined = rightPaddingDefined;
4341 
4342         if (padding >= 0) {
4343             leftPadding = padding;
4344             topPadding = padding;
4345             rightPadding = padding;
4346             bottomPadding = padding;
4347             mUserPaddingLeftInitial = padding;
4348             mUserPaddingRightInitial = padding;
4349         }
4350 
4351         if (isRtlCompatibilityMode()) {
4352             // RTL compatibility mode: pre Jelly Bean MR1 case OR no RTL support case.
4353             // left / right padding are used if defined (meaning here nothing to do). If they are not
4354             // defined and start / end padding are defined (e.g. in Frameworks resources), then we use
4355             // start / end and resolve them as left / right (layout direction is not taken into account).
4356             // Padding from the background drawable is stored at this point in mUserPaddingLeftInitial
4357             // and mUserPaddingRightInitial) so drawable padding will be used as ultimate default if
4358             // defined.
4359             if (!mLeftPaddingDefined && startPaddingDefined) {
4360                 leftPadding = startPadding;
4361             }
4362             mUserPaddingLeftInitial = (leftPadding >= 0) ? leftPadding : mUserPaddingLeftInitial;
4363             if (!mRightPaddingDefined && endPaddingDefined) {
4364                 rightPadding = endPadding;
4365             }
4366             mUserPaddingRightInitial = (rightPadding >= 0) ? rightPadding : mUserPaddingRightInitial;
4367         } else {
4368             // Jelly Bean MR1 and after case: if start/end defined, they will override any left/right
4369             // values defined. Otherwise, left /right values are used.
4370             // Padding from the background drawable is stored at this point in mUserPaddingLeftInitial
4371             // and mUserPaddingRightInitial) so drawable padding will be used as ultimate default if
4372             // defined.
4373             final boolean hasRelativePadding = startPaddingDefined || endPaddingDefined;
4374 
4375             if (mLeftPaddingDefined && !hasRelativePadding) {
4376                 mUserPaddingLeftInitial = leftPadding;
4377             }
4378             if (mRightPaddingDefined && !hasRelativePadding) {
4379                 mUserPaddingRightInitial = rightPadding;
4380             }
4381         }
4382 
internalSetPadding( mUserPaddingLeftInitial, topPadding >= 0 ? topPadding : mPaddingTop, mUserPaddingRightInitial, bottomPadding >= 0 ? bottomPadding : mPaddingBottom)4383         internalSetPadding(
4384                 mUserPaddingLeftInitial,
4385                 topPadding >= 0 ? topPadding : mPaddingTop,
4386                 mUserPaddingRightInitial,
4387                 bottomPadding >= 0 ? bottomPadding : mPaddingBottom);
4388 
4389         if (viewFlagMasks != 0) {
setFlags(viewFlagValues, viewFlagMasks)4390             setFlags(viewFlagValues, viewFlagMasks);
4391         }
4392 
4393         if (initializeScrollbars) {
4394             initializeScrollbarsInternal(a);
4395         }
4396 
4397         if (initializeScrollIndicators) {
initializeScrollIndicatorsInternal()4398             initializeScrollIndicatorsInternal();
4399         }
4400 
a.recycle()4401         a.recycle();
4402 
4403         // Needs to be called after mViewFlags is set
4404         if (scrollbarStyle != SCROLLBARS_INSIDE_OVERLAY) {
recomputePadding()4405             recomputePadding();
4406         }
4407 
4408         if (x != 0 || y != 0) {
scrollTo(x, y)4409             scrollTo(x, y);
4410         }
4411 
4412         if (transformSet) {
4413             setTranslationX(tx);
4414             setTranslationY(ty);
4415             setTranslationZ(tz);
4416             setElevation(elevation);
4417             setRotation(rotation);
4418             setRotationX(rotationX);
4419             setRotationY(rotationY);
4420             setScaleX(sx);
4421             setScaleY(sy);
4422         }
4423 
4424         if (!setScrollContainer && (viewFlagValues&SCROLLBARS_VERTICAL) != 0) {
4425             setScrollContainer(true);
4426         }
4427 
computeOpaqueFlags()4428         computeOpaqueFlags();
4429     }
4430 
4431     /**
4432      * An implementation of OnClickListener that attempts to lazily load a
4433      * named click handling method from a parent or ancestor context.
4434      */
4435     private static class DeclaredOnClickListener implements OnClickListener {
4436         private final View mHostView;
4437         private final String mMethodName;
4438 
4439         private Method mMethod;
4440 
DeclaredOnClickListener(@onNull View hostView, @NonNull String methodName)4441         public DeclaredOnClickListener(@NonNull View hostView, @NonNull String methodName) {
4442             mHostView = hostView;
4443             mMethodName = methodName;
4444         }
4445 
4446         @Override
onClick(@onNull View v)4447         public void onClick(@NonNull View v) {
4448             if (mMethod == null) {
4449                 mMethod = resolveMethod(mHostView.getContext(), mMethodName);
4450             }
4451 
4452             try {
4453                 mMethod.invoke(mHostView.getContext(), v);
4454             } catch (IllegalAccessException e) {
4455                 throw new IllegalStateException(
4456                         "Could not execute non-public method for android:onClick", e);
4457             } catch (InvocationTargetException e) {
4458                 throw new IllegalStateException(
4459                         "Could not execute method for android:onClick", e);
4460             }
4461         }
4462 
4463         @NonNull
resolveMethod(@ullable Context context, @NonNull String name)4464         private Method resolveMethod(@Nullable Context context, @NonNull String name) {
4465             while (context != null) {
4466                 try {
4467                     if (!context.isRestricted()) {
4468                         return context.getClass().getMethod(mMethodName, View.class);
4469                     }
4470                 } catch (NoSuchMethodException e) {
4471                     // Failed to find method, keep searching up the hierarchy.
4472                 }
4473 
4474                 if (context instanceof ContextWrapper) {
4475                     context = ((ContextWrapper) context).getBaseContext();
4476                 } else {
4477                     // Can't search up the hierarchy, null out and fail.
4478                     context = null;
4479                 }
4480             }
4481 
4482             final int id = mHostView.getId();
4483             final String idText = id == NO_ID ? "" : " with id '"
4484                     + mHostView.getContext().getResources().getResourceEntryName(id) + "'";
4485             throw new IllegalStateException("Could not find method " + mMethodName
4486                     + "(View) in a parent or ancestor Context for android:onClick "
4487                     + "attribute defined on view " + mHostView.getClass() + idText);
4488         }
4489     }
4490 
4491     /**
4492      * Non-public constructor for use in testing
4493      */
View()4494     View() {
4495         mResources = null;
4496         mRenderNode = RenderNode.create(getClass().getName(), this);
4497     }
4498 
getAttributeMap()4499     private static SparseArray<String> getAttributeMap() {
4500         if (mAttributeMap == null) {
4501             mAttributeMap = new SparseArray<>();
4502         }
4503         return mAttributeMap;
4504     }
4505 
saveAttributeData(@ullable AttributeSet attrs, @NonNull TypedArray t)4506     private void saveAttributeData(@Nullable AttributeSet attrs, @NonNull TypedArray t) {
4507         final int attrsCount = attrs == null ? 0 : attrs.getAttributeCount();
4508         final int indexCount = t.getIndexCount();
4509         final String[] attributes = new String[(attrsCount + indexCount) * 2];
4510 
4511         int i = 0;
4512 
4513         // Store raw XML attributes.
4514         for (int j = 0; j < attrsCount; ++j) {
4515             attributes[i] = attrs.getAttributeName(j);
4516             attributes[i + 1] = attrs.getAttributeValue(j);
4517             i += 2;
4518         }
4519 
4520         // Store resolved styleable attributes.
4521         final Resources res = t.getResources();
4522         final SparseArray<String> attributeMap = getAttributeMap();
4523         for (int j = 0; j < indexCount; ++j) {
4524             final int index = t.getIndex(j);
4525             if (!t.hasValueOrEmpty(index)) {
4526                 // Value is undefined. Skip it.
4527                 continue;
4528             }
4529 
4530             final int resourceId = t.getResourceId(index, 0);
4531             if (resourceId == 0) {
4532                 // Value is not a reference. Skip it.
4533                 continue;
4534             }
4535 
4536             String resourceName = attributeMap.get(resourceId);
4537             if (resourceName == null) {
4538                 try {
4539                     resourceName = res.getResourceName(resourceId);
4540                 } catch (Resources.NotFoundException e) {
4541                     resourceName = "0x" + Integer.toHexString(resourceId);
4542                 }
4543                 attributeMap.put(resourceId, resourceName);
4544             }
4545 
4546             attributes[i] = resourceName;
4547             attributes[i + 1] = t.getString(index);
4548             i += 2;
4549         }
4550 
4551         // Trim to fit contents.
4552         final String[] trimmed = new String[i];
4553         System.arraycopy(attributes, 0, trimmed, 0, i);
4554         mAttributes = trimmed;
4555     }
4556 
toString()4557     public String toString() {
4558         StringBuilder out = new StringBuilder(128);
4559         out.append(getClass().getName());
4560         out.append('{');
4561         out.append(Integer.toHexString(System.identityHashCode(this)));
4562         out.append(' ');
4563         switch (mViewFlags&VISIBILITY_MASK) {
4564             case VISIBLE: out.append('V'); break;
4565             case INVISIBLE: out.append('I'); break;
4566             case GONE: out.append('G'); break;
4567             default: out.append('.'); break;
4568         }
4569         out.append((mViewFlags&FOCUSABLE_MASK) == FOCUSABLE ? 'F' : '.');
4570         out.append((mViewFlags&ENABLED_MASK) == ENABLED ? 'E' : '.');
4571         out.append((mViewFlags&DRAW_MASK) == WILL_NOT_DRAW ? '.' : 'D');
4572         out.append((mViewFlags&SCROLLBARS_HORIZONTAL) != 0 ? 'H' : '.');
4573         out.append((mViewFlags&SCROLLBARS_VERTICAL) != 0 ? 'V' : '.');
4574         out.append((mViewFlags&CLICKABLE) != 0 ? 'C' : '.');
4575         out.append((mViewFlags&LONG_CLICKABLE) != 0 ? 'L' : '.');
4576         out.append((mViewFlags&CONTEXT_CLICKABLE) != 0 ? 'X' : '.');
4577         out.append(' ');
4578         out.append((mPrivateFlags&PFLAG_IS_ROOT_NAMESPACE) != 0 ? 'R' : '.');
4579         out.append((mPrivateFlags&PFLAG_FOCUSED) != 0 ? 'F' : '.');
4580         out.append((mPrivateFlags&PFLAG_SELECTED) != 0 ? 'S' : '.');
4581         if ((mPrivateFlags&PFLAG_PREPRESSED) != 0) {
4582             out.append('p');
4583         } else {
4584             out.append((mPrivateFlags&PFLAG_PRESSED) != 0 ? 'P' : '.');
4585         }
4586         out.append((mPrivateFlags&PFLAG_HOVERED) != 0 ? 'H' : '.');
4587         out.append((mPrivateFlags&PFLAG_ACTIVATED) != 0 ? 'A' : '.');
4588         out.append((mPrivateFlags&PFLAG_INVALIDATED) != 0 ? 'I' : '.');
4589         out.append((mPrivateFlags&PFLAG_DIRTY_MASK) != 0 ? 'D' : '.');
4590         out.append(' ');
4591         out.append(mLeft);
4592         out.append(',');
4593         out.append(mTop);
4594         out.append('-');
4595         out.append(mRight);
4596         out.append(',');
4597         out.append(mBottom);
4598         final int id = getId();
4599         if (id != NO_ID) {
4600             out.append(" #");
4601             out.append(Integer.toHexString(id));
4602             final Resources r = mResources;
4603             if (Resources.resourceHasPackage(id) && r != null) {
4604                 try {
4605                     String pkgname;
4606                     switch (id&0xff000000) {
4607                         case 0x7f000000:
4608                             pkgname="app";
4609                             break;
4610                         case 0x01000000:
4611                             pkgname="android";
4612                             break;
4613                         default:
4614                             pkgname = r.getResourcePackageName(id);
4615                             break;
4616                     }
4617                     String typename = r.getResourceTypeName(id);
4618                     String entryname = r.getResourceEntryName(id);
4619                     out.append(" ");
4620                     out.append(pkgname);
4621                     out.append(":");
4622                     out.append(typename);
4623                     out.append("/");
4624                     out.append(entryname);
4625                 } catch (Resources.NotFoundException e) {
4626                 }
4627             }
4628         }
4629         out.append("}");
4630         return out.toString();
4631     }
4632 
4633     /**
4634      * <p>
4635      * Initializes the fading edges from a given set of styled attributes. This
4636      * method should be called by subclasses that need fading edges and when an
4637      * instance of these subclasses is created programmatically rather than
4638      * being inflated from XML. This method is automatically called when the XML
4639      * is inflated.
4640      * </p>
4641      *
4642      * @param a the styled attributes set to initialize the fading edges from
4643      *
4644      * @removed
4645      */
initializeFadingEdge(TypedArray a)4646     protected void initializeFadingEdge(TypedArray a) {
4647         // This method probably shouldn't have been included in the SDK to begin with.
4648         // It relies on 'a' having been initialized using an attribute filter array that is
4649         // not publicly available to the SDK. The old method has been renamed
4650         // to initializeFadingEdgeInternal and hidden for framework use only;
4651         // this one initializes using defaults to make it safe to call for apps.
4652 
4653         TypedArray arr = mContext.obtainStyledAttributes(com.android.internal.R.styleable.View);
4654 
4655         initializeFadingEdgeInternal(arr);
4656 
4657         arr.recycle();
4658     }
4659 
4660     /**
4661      * <p>
4662      * Initializes the fading edges from a given set of styled attributes. This
4663      * method should be called by subclasses that need fading edges and when an
4664      * instance of these subclasses is created programmatically rather than
4665      * being inflated from XML. This method is automatically called when the XML
4666      * is inflated.
4667      * </p>
4668      *
4669      * @param a the styled attributes set to initialize the fading edges from
4670      * @hide This is the real method; the public one is shimmed to be safe to call from apps.
4671      */
initializeFadingEdgeInternal(TypedArray a)4672     protected void initializeFadingEdgeInternal(TypedArray a) {
4673         initScrollCache();
4674 
4675         mScrollCache.fadingEdgeLength = a.getDimensionPixelSize(
4676                 R.styleable.View_fadingEdgeLength,
4677                 ViewConfiguration.get(mContext).getScaledFadingEdgeLength());
4678     }
4679 
4680     /**
4681      * Returns the size of the vertical faded edges used to indicate that more
4682      * content in this view is visible.
4683      *
4684      * @return The size in pixels of the vertical faded edge or 0 if vertical
4685      *         faded edges are not enabled for this view.
4686      * @attr ref android.R.styleable#View_fadingEdgeLength
4687      */
getVerticalFadingEdgeLength()4688     public int getVerticalFadingEdgeLength() {
4689         if (isVerticalFadingEdgeEnabled()) {
4690             ScrollabilityCache cache = mScrollCache;
4691             if (cache != null) {
4692                 return cache.fadingEdgeLength;
4693             }
4694         }
4695         return 0;
4696     }
4697 
4698     /**
4699      * Set the size of the faded edge used to indicate that more content in this
4700      * view is available.  Will not change whether the fading edge is enabled; use
4701      * {@link #setVerticalFadingEdgeEnabled(boolean)} or
4702      * {@link #setHorizontalFadingEdgeEnabled(boolean)} to enable the fading edge
4703      * for the vertical or horizontal fading edges.
4704      *
4705      * @param length The size in pixels of the faded edge used to indicate that more
4706      *        content in this view is visible.
4707      */
setFadingEdgeLength(int length)4708     public void setFadingEdgeLength(int length) {
4709         initScrollCache();
4710         mScrollCache.fadingEdgeLength = length;
4711     }
4712 
4713     /**
4714      * Returns the size of the horizontal faded edges used to indicate that more
4715      * content in this view is visible.
4716      *
4717      * @return The size in pixels of the horizontal faded edge or 0 if horizontal
4718      *         faded edges are not enabled for this view.
4719      * @attr ref android.R.styleable#View_fadingEdgeLength
4720      */
getHorizontalFadingEdgeLength()4721     public int getHorizontalFadingEdgeLength() {
4722         if (isHorizontalFadingEdgeEnabled()) {
4723             ScrollabilityCache cache = mScrollCache;
4724             if (cache != null) {
4725                 return cache.fadingEdgeLength;
4726             }
4727         }
4728         return 0;
4729     }
4730 
4731     /**
4732      * Returns the width of the vertical scrollbar.
4733      *
4734      * @return The width in pixels of the vertical scrollbar or 0 if there
4735      *         is no vertical scrollbar.
4736      */
getVerticalScrollbarWidth()4737     public int getVerticalScrollbarWidth() {
4738         ScrollabilityCache cache = mScrollCache;
4739         if (cache != null) {
4740             ScrollBarDrawable scrollBar = cache.scrollBar;
4741             if (scrollBar != null) {
4742                 int size = scrollBar.getSize(true);
4743                 if (size <= 0) {
4744                     size = cache.scrollBarSize;
4745                 }
4746                 return size;
4747             }
4748             return 0;
4749         }
4750         return 0;
4751     }
4752 
4753     /**
4754      * Returns the height of the horizontal scrollbar.
4755      *
4756      * @return The height in pixels of the horizontal scrollbar or 0 if
4757      *         there is no horizontal scrollbar.
4758      */
getHorizontalScrollbarHeight()4759     protected int getHorizontalScrollbarHeight() {
4760         ScrollabilityCache cache = mScrollCache;
4761         if (cache != null) {
4762             ScrollBarDrawable scrollBar = cache.scrollBar;
4763             if (scrollBar != null) {
4764                 int size = scrollBar.getSize(false);
4765                 if (size <= 0) {
4766                     size = cache.scrollBarSize;
4767                 }
4768                 return size;
4769             }
4770             return 0;
4771         }
4772         return 0;
4773     }
4774 
4775     /**
4776      * <p>
4777      * Initializes the scrollbars from a given set of styled attributes. This
4778      * method should be called by subclasses that need scrollbars and when an
4779      * instance of these subclasses is created programmatically rather than
4780      * being inflated from XML. This method is automatically called when the XML
4781      * is inflated.
4782      * </p>
4783      *
4784      * @param a the styled attributes set to initialize the scrollbars from
4785      *
4786      * @removed
4787      */
initializeScrollbars(TypedArray a)4788     protected void initializeScrollbars(TypedArray a) {
4789         // It's not safe to use this method from apps. The parameter 'a' must have been obtained
4790         // using the View filter array which is not available to the SDK. As such, internal
4791         // framework usage now uses initializeScrollbarsInternal and we grab a default
4792         // TypedArray with the right filter instead here.
4793         TypedArray arr = mContext.obtainStyledAttributes(com.android.internal.R.styleable.View);
4794 
4795         initializeScrollbarsInternal(arr);
4796 
4797         // We ignored the method parameter. Recycle the one we actually did use.
4798         arr.recycle();
4799     }
4800 
4801     /**
4802      * <p>
4803      * Initializes the scrollbars from a given set of styled attributes. This
4804      * method should be called by subclasses that need scrollbars and when an
4805      * instance of these subclasses is created programmatically rather than
4806      * being inflated from XML. This method is automatically called when the XML
4807      * is inflated.
4808      * </p>
4809      *
4810      * @param a the styled attributes set to initialize the scrollbars from
4811      * @hide
4812      */
initializeScrollbarsInternal(TypedArray a)4813     protected void initializeScrollbarsInternal(TypedArray a) {
4814         initScrollCache();
4815 
4816         final ScrollabilityCache scrollabilityCache = mScrollCache;
4817 
4818         if (scrollabilityCache.scrollBar == null) {
4819             scrollabilityCache.scrollBar = new ScrollBarDrawable();
4820             scrollabilityCache.scrollBar.setCallback(this);
4821             scrollabilityCache.scrollBar.setState(getDrawableState());
4822         }
4823 
4824         final boolean fadeScrollbars = a.getBoolean(R.styleable.View_fadeScrollbars, true);
4825 
4826         if (!fadeScrollbars) {
4827             scrollabilityCache.state = ScrollabilityCache.ON;
4828         }
4829         scrollabilityCache.fadeScrollBars = fadeScrollbars;
4830 
4831 
4832         scrollabilityCache.scrollBarFadeDuration = a.getInt(
4833                 R.styleable.View_scrollbarFadeDuration, ViewConfiguration
4834                         .getScrollBarFadeDuration());
4835         scrollabilityCache.scrollBarDefaultDelayBeforeFade = a.getInt(
4836                 R.styleable.View_scrollbarDefaultDelayBeforeFade,
4837                 ViewConfiguration.getScrollDefaultDelay());
4838 
4839 
4840         scrollabilityCache.scrollBarSize = a.getDimensionPixelSize(
4841                 com.android.internal.R.styleable.View_scrollbarSize,
4842                 ViewConfiguration.get(mContext).getScaledScrollBarSize());
4843 
4844         Drawable track = a.getDrawable(R.styleable.View_scrollbarTrackHorizontal);
4845         scrollabilityCache.scrollBar.setHorizontalTrackDrawable(track);
4846 
4847         Drawable thumb = a.getDrawable(R.styleable.View_scrollbarThumbHorizontal);
4848         if (thumb != null) {
4849             scrollabilityCache.scrollBar.setHorizontalThumbDrawable(thumb);
4850         }
4851 
4852         boolean alwaysDraw = a.getBoolean(R.styleable.View_scrollbarAlwaysDrawHorizontalTrack,
4853                 false);
4854         if (alwaysDraw) {
4855             scrollabilityCache.scrollBar.setAlwaysDrawHorizontalTrack(true);
4856         }
4857 
4858         track = a.getDrawable(R.styleable.View_scrollbarTrackVertical);
4859         scrollabilityCache.scrollBar.setVerticalTrackDrawable(track);
4860 
4861         thumb = a.getDrawable(R.styleable.View_scrollbarThumbVertical);
4862         if (thumb != null) {
4863             scrollabilityCache.scrollBar.setVerticalThumbDrawable(thumb);
4864         }
4865 
4866         alwaysDraw = a.getBoolean(R.styleable.View_scrollbarAlwaysDrawVerticalTrack,
4867                 false);
4868         if (alwaysDraw) {
4869             scrollabilityCache.scrollBar.setAlwaysDrawVerticalTrack(true);
4870         }
4871 
4872         // Apply layout direction to the new Drawables if needed
4873         final int layoutDirection = getLayoutDirection();
4874         if (track != null) {
4875             track.setLayoutDirection(layoutDirection);
4876         }
4877         if (thumb != null) {
4878             thumb.setLayoutDirection(layoutDirection);
4879         }
4880 
4881         // Re-apply user/background padding so that scrollbar(s) get added
4882         resolvePadding();
4883     }
4884 
initializeScrollIndicatorsInternal()4885     private void initializeScrollIndicatorsInternal() {
4886         // Some day maybe we'll break this into top/left/start/etc. and let the
4887         // client control it. Until then, you can have any scroll indicator you
4888         // want as long as it's a 1dp foreground-colored rectangle.
4889         if (mScrollIndicatorDrawable == null) {
4890             mScrollIndicatorDrawable = mContext.getDrawable(R.drawable.scroll_indicator_material);
4891         }
4892     }
4893 
4894     /**
4895      * <p>
4896      * Initalizes the scrollability cache if necessary.
4897      * </p>
4898      */
initScrollCache()4899     private void initScrollCache() {
4900         if (mScrollCache == null) {
4901             mScrollCache = new ScrollabilityCache(ViewConfiguration.get(mContext), this);
4902         }
4903     }
4904 
getScrollCache()4905     private ScrollabilityCache getScrollCache() {
4906         initScrollCache();
4907         return mScrollCache;
4908     }
4909 
4910     /**
4911      * Set the position of the vertical scroll bar. Should be one of
4912      * {@link #SCROLLBAR_POSITION_DEFAULT}, {@link #SCROLLBAR_POSITION_LEFT} or
4913      * {@link #SCROLLBAR_POSITION_RIGHT}.
4914      *
4915      * @param position Where the vertical scroll bar should be positioned.
4916      */
setVerticalScrollbarPosition(int position)4917     public void setVerticalScrollbarPosition(int position) {
4918         if (mVerticalScrollbarPosition != position) {
4919             mVerticalScrollbarPosition = position;
4920             computeOpaqueFlags();
4921             resolvePadding();
4922         }
4923     }
4924 
4925     /**
4926      * @return The position where the vertical scroll bar will show, if applicable.
4927      * @see #setVerticalScrollbarPosition(int)
4928      */
getVerticalScrollbarPosition()4929     public int getVerticalScrollbarPosition() {
4930         return mVerticalScrollbarPosition;
4931     }
4932 
4933     /**
4934      * Sets the state of all scroll indicators.
4935      * <p>
4936      * See {@link #setScrollIndicators(int, int)} for usage information.
4937      *
4938      * @param indicators a bitmask of indicators that should be enabled, or
4939      *                   {@code 0} to disable all indicators
4940      * @see #setScrollIndicators(int, int)
4941      * @see #getScrollIndicators()
4942      * @attr ref android.R.styleable#View_scrollIndicators
4943      */
setScrollIndicators(@crollIndicators int indicators)4944     public void setScrollIndicators(@ScrollIndicators int indicators) {
4945         setScrollIndicators(indicators,
4946                 SCROLL_INDICATORS_PFLAG3_MASK >>> SCROLL_INDICATORS_TO_PFLAGS3_LSHIFT);
4947     }
4948 
4949     /**
4950      * Sets the state of the scroll indicators specified by the mask. To change
4951      * all scroll indicators at once, see {@link #setScrollIndicators(int)}.
4952      * <p>
4953      * When a scroll indicator is enabled, it will be displayed if the view
4954      * can scroll in the direction of the indicator.
4955      * <p>
4956      * Multiple indicator types may be enabled or disabled by passing the
4957      * logical OR of the desired types. If multiple types are specified, they
4958      * will all be set to the same enabled state.
4959      * <p>
4960      * For example, to enable the top scroll indicatorExample: {@code setScrollIndicators
4961      *
4962      * @param indicators the indicator direction, or the logical OR of multiple
4963      *             indicator directions. One or more of:
4964      *             <ul>
4965      *               <li>{@link #SCROLL_INDICATOR_TOP}</li>
4966      *               <li>{@link #SCROLL_INDICATOR_BOTTOM}</li>
4967      *               <li>{@link #SCROLL_INDICATOR_LEFT}</li>
4968      *               <li>{@link #SCROLL_INDICATOR_RIGHT}</li>
4969      *               <li>{@link #SCROLL_INDICATOR_START}</li>
4970      *               <li>{@link #SCROLL_INDICATOR_END}</li>
4971      *             </ul>
4972      * @see #setScrollIndicators(int)
4973      * @see #getScrollIndicators()
4974      * @attr ref android.R.styleable#View_scrollIndicators
4975      */
setScrollIndicators(@crollIndicators int indicators, @ScrollIndicators int mask)4976     public void setScrollIndicators(@ScrollIndicators int indicators, @ScrollIndicators int mask) {
4977         // Shift and sanitize mask.
4978         mask <<= SCROLL_INDICATORS_TO_PFLAGS3_LSHIFT;
4979         mask &= SCROLL_INDICATORS_PFLAG3_MASK;
4980 
4981         // Shift and mask indicators.
4982         indicators <<= SCROLL_INDICATORS_TO_PFLAGS3_LSHIFT;
4983         indicators &= mask;
4984 
4985         // Merge with non-masked flags.
4986         final int updatedFlags = indicators | (mPrivateFlags3 & ~mask);
4987 
4988         if (mPrivateFlags3 != updatedFlags) {
4989             mPrivateFlags3 = updatedFlags;
4990 
4991             if (indicators != 0) {
4992                 initializeScrollIndicatorsInternal();
4993             }
4994             invalidate();
4995         }
4996     }
4997 
4998     /**
4999      * Returns a bitmask representing the enabled scroll indicators.
5000      * <p>
5001      * For example, if the top and left scroll indicators are enabled and all
5002      * other indicators are disabled, the return value will be
5003      * {@code View.SCROLL_INDICATOR_TOP | View.SCROLL_INDICATOR_LEFT}.
5004      * <p>
5005      * To check whether the bottom scroll indicator is enabled, use the value
5006      * of {@code (getScrollIndicators() & View.SCROLL_INDICATOR_BOTTOM) != 0}.
5007      *
5008      * @return a bitmask representing the enabled scroll indicators
5009      */
5010     @ScrollIndicators
getScrollIndicators()5011     public int getScrollIndicators() {
5012         return (mPrivateFlags3 & SCROLL_INDICATORS_PFLAG3_MASK)
5013                 >>> SCROLL_INDICATORS_TO_PFLAGS3_LSHIFT;
5014     }
5015 
getListenerInfo()5016     ListenerInfo getListenerInfo() {
5017         if (mListenerInfo != null) {
5018             return mListenerInfo;
5019         }
5020         mListenerInfo = new ListenerInfo();
5021         return mListenerInfo;
5022     }
5023 
5024     /**
5025      * Register a callback to be invoked when the scroll X or Y positions of
5026      * this view change.
5027      * <p>
5028      * <b>Note:</b> Some views handle scrolling independently from View and may
5029      * have their own separate listeners for scroll-type events. For example,
5030      * {@link android.widget.ListView ListView} allows clients to register an
5031      * {@link android.widget.ListView#setOnScrollListener(android.widget.AbsListView.OnScrollListener) AbsListView.OnScrollListener}
5032      * to listen for changes in list scroll position.
5033      *
5034      * @param l The listener to notify when the scroll X or Y position changes.
5035      * @see android.view.View#getScrollX()
5036      * @see android.view.View#getScrollY()
5037      */
setOnScrollChangeListener(OnScrollChangeListener l)5038     public void setOnScrollChangeListener(OnScrollChangeListener l) {
5039         getListenerInfo().mOnScrollChangeListener = l;
5040     }
5041 
5042     /**
5043      * Register a callback to be invoked when focus of this view changed.
5044      *
5045      * @param l The callback that will run.
5046      */
setOnFocusChangeListener(OnFocusChangeListener l)5047     public void setOnFocusChangeListener(OnFocusChangeListener l) {
5048         getListenerInfo().mOnFocusChangeListener = l;
5049     }
5050 
5051     /**
5052      * Add a listener that will be called when the bounds of the view change due to
5053      * layout processing.
5054      *
5055      * @param listener The listener that will be called when layout bounds change.
5056      */
addOnLayoutChangeListener(OnLayoutChangeListener listener)5057     public void addOnLayoutChangeListener(OnLayoutChangeListener listener) {
5058         ListenerInfo li = getListenerInfo();
5059         if (li.mOnLayoutChangeListeners == null) {
5060             li.mOnLayoutChangeListeners = new ArrayList<OnLayoutChangeListener>();
5061         }
5062         if (!li.mOnLayoutChangeListeners.contains(listener)) {
5063             li.mOnLayoutChangeListeners.add(listener);
5064         }
5065     }
5066 
5067     /**
5068      * Remove a listener for layout changes.
5069      *
5070      * @param listener The listener for layout bounds change.
5071      */
removeOnLayoutChangeListener(OnLayoutChangeListener listener)5072     public void removeOnLayoutChangeListener(OnLayoutChangeListener listener) {
5073         ListenerInfo li = mListenerInfo;
5074         if (li == null || li.mOnLayoutChangeListeners == null) {
5075             return;
5076         }
5077         li.mOnLayoutChangeListeners.remove(listener);
5078     }
5079 
5080     /**
5081      * Add a listener for attach state changes.
5082      *
5083      * This listener will be called whenever this view is attached or detached
5084      * from a window. Remove the listener using
5085      * {@link #removeOnAttachStateChangeListener(OnAttachStateChangeListener)}.
5086      *
5087      * @param listener Listener to attach
5088      * @see #removeOnAttachStateChangeListener(OnAttachStateChangeListener)
5089      */
addOnAttachStateChangeListener(OnAttachStateChangeListener listener)5090     public void addOnAttachStateChangeListener(OnAttachStateChangeListener listener) {
5091         ListenerInfo li = getListenerInfo();
5092         if (li.mOnAttachStateChangeListeners == null) {
5093             li.mOnAttachStateChangeListeners
5094                     = new CopyOnWriteArrayList<OnAttachStateChangeListener>();
5095         }
5096         li.mOnAttachStateChangeListeners.add(listener);
5097     }
5098 
5099     /**
5100      * Remove a listener for attach state changes. The listener will receive no further
5101      * notification of window attach/detach events.
5102      *
5103      * @param listener Listener to remove
5104      * @see #addOnAttachStateChangeListener(OnAttachStateChangeListener)
5105      */
removeOnAttachStateChangeListener(OnAttachStateChangeListener listener)5106     public void removeOnAttachStateChangeListener(OnAttachStateChangeListener listener) {
5107         ListenerInfo li = mListenerInfo;
5108         if (li == null || li.mOnAttachStateChangeListeners == null) {
5109             return;
5110         }
5111         li.mOnAttachStateChangeListeners.remove(listener);
5112     }
5113 
5114     /**
5115      * Returns the focus-change callback registered for this view.
5116      *
5117      * @return The callback, or null if one is not registered.
5118      */
getOnFocusChangeListener()5119     public OnFocusChangeListener getOnFocusChangeListener() {
5120         ListenerInfo li = mListenerInfo;
5121         return li != null ? li.mOnFocusChangeListener : null;
5122     }
5123 
5124     /**
5125      * Register a callback to be invoked when this view is clicked. If this view is not
5126      * clickable, it becomes clickable.
5127      *
5128      * @param l The callback that will run
5129      *
5130      * @see #setClickable(boolean)
5131      */
setOnClickListener(@ullable OnClickListener l)5132     public void setOnClickListener(@Nullable OnClickListener l) {
5133         if (!isClickable()) {
5134             setClickable(true);
5135         }
5136         getListenerInfo().mOnClickListener = l;
5137     }
5138 
5139     /**
5140      * Return whether this view has an attached OnClickListener.  Returns
5141      * true if there is a listener, false if there is none.
5142      */
hasOnClickListeners()5143     public boolean hasOnClickListeners() {
5144         ListenerInfo li = mListenerInfo;
5145         return (li != null && li.mOnClickListener != null);
5146     }
5147 
5148     /**
5149      * Register a callback to be invoked when this view is clicked and held. If this view is not
5150      * long clickable, it becomes long clickable.
5151      *
5152      * @param l The callback that will run
5153      *
5154      * @see #setLongClickable(boolean)
5155      */
setOnLongClickListener(@ullable OnLongClickListener l)5156     public void setOnLongClickListener(@Nullable OnLongClickListener l) {
5157         if (!isLongClickable()) {
5158             setLongClickable(true);
5159         }
5160         getListenerInfo().mOnLongClickListener = l;
5161     }
5162 
5163     /**
5164      * Register a callback to be invoked when this view is context clicked. If the view is not
5165      * context clickable, it becomes context clickable.
5166      *
5167      * @param l The callback that will run
5168      * @see #setContextClickable(boolean)
5169      */
setOnContextClickListener(@ullable OnContextClickListener l)5170     public void setOnContextClickListener(@Nullable OnContextClickListener l) {
5171         if (!isContextClickable()) {
5172             setContextClickable(true);
5173         }
5174         getListenerInfo().mOnContextClickListener = l;
5175     }
5176 
5177     /**
5178      * Register a callback to be invoked when the context menu for this view is
5179      * being built. If this view is not long clickable, it becomes long clickable.
5180      *
5181      * @param l The callback that will run
5182      *
5183      */
setOnCreateContextMenuListener(OnCreateContextMenuListener l)5184     public void setOnCreateContextMenuListener(OnCreateContextMenuListener l) {
5185         if (!isLongClickable()) {
5186             setLongClickable(true);
5187         }
5188         getListenerInfo().mOnCreateContextMenuListener = l;
5189     }
5190 
5191     /**
5192      * Call this view's OnClickListener, if it is defined.  Performs all normal
5193      * actions associated with clicking: reporting accessibility event, playing
5194      * a sound, etc.
5195      *
5196      * @return True there was an assigned OnClickListener that was called, false
5197      *         otherwise is returned.
5198      */
performClick()5199     public boolean performClick() {
5200         final boolean result;
5201         final ListenerInfo li = mListenerInfo;
5202         if (li != null && li.mOnClickListener != null) {
5203             playSoundEffect(SoundEffectConstants.CLICK);
5204             li.mOnClickListener.onClick(this);
5205             result = true;
5206         } else {
5207             result = false;
5208         }
5209 
5210         sendAccessibilityEvent(AccessibilityEvent.TYPE_VIEW_CLICKED);
5211         return result;
5212     }
5213 
5214     /**
5215      * Directly call any attached OnClickListener.  Unlike {@link #performClick()},
5216      * this only calls the listener, and does not do any associated clicking
5217      * actions like reporting an accessibility event.
5218      *
5219      * @return True there was an assigned OnClickListener that was called, false
5220      *         otherwise is returned.
5221      */
callOnClick()5222     public boolean callOnClick() {
5223         ListenerInfo li = mListenerInfo;
5224         if (li != null && li.mOnClickListener != null) {
5225             li.mOnClickListener.onClick(this);
5226             return true;
5227         }
5228         return false;
5229     }
5230 
5231     /**
5232      * Call this view's OnLongClickListener, if it is defined. Invokes the context menu if the
5233      * OnLongClickListener did not consume the event.
5234      *
5235      * @return True if one of the above receivers consumed the event, false otherwise.
5236      */
performLongClick()5237     public boolean performLongClick() {
5238         sendAccessibilityEvent(AccessibilityEvent.TYPE_VIEW_LONG_CLICKED);
5239 
5240         boolean handled = false;
5241         ListenerInfo li = mListenerInfo;
5242         if (li != null && li.mOnLongClickListener != null) {
5243             handled = li.mOnLongClickListener.onLongClick(View.this);
5244         }
5245         if (!handled) {
5246             handled = showContextMenu();
5247         }
5248         if (handled) {
5249             performHapticFeedback(HapticFeedbackConstants.LONG_PRESS);
5250         }
5251         return handled;
5252     }
5253 
5254     /**
5255      * Call this view's OnContextClickListener, if it is defined.
5256      *
5257      * @return True if there was an assigned OnContextClickListener that consumed the event, false
5258      *         otherwise.
5259      */
performContextClick()5260     public boolean performContextClick() {
5261         sendAccessibilityEvent(AccessibilityEvent.TYPE_VIEW_CONTEXT_CLICKED);
5262 
5263         boolean handled = false;
5264         ListenerInfo li = mListenerInfo;
5265         if (li != null && li.mOnContextClickListener != null) {
5266             handled = li.mOnContextClickListener.onContextClick(View.this);
5267         }
5268         if (handled) {
5269             performHapticFeedback(HapticFeedbackConstants.CONTEXT_CLICK);
5270         }
5271         return handled;
5272     }
5273 
5274     /**
5275      * Performs button-related actions during a touch down event.
5276      *
5277      * @param event The event.
5278      * @return True if the down was consumed.
5279      *
5280      * @hide
5281      */
performButtonActionOnTouchDown(MotionEvent event)5282     protected boolean performButtonActionOnTouchDown(MotionEvent event) {
5283         if (event.getToolType(0) == MotionEvent.TOOL_TYPE_MOUSE &&
5284             (event.getButtonState() & MotionEvent.BUTTON_SECONDARY) != 0) {
5285             showContextMenu(event.getX(), event.getY(), event.getMetaState());
5286             mPrivateFlags |= PFLAG_CANCEL_NEXT_UP_EVENT;
5287             return true;
5288         }
5289         return false;
5290     }
5291 
5292     /**
5293      * Bring up the context menu for this view.
5294      *
5295      * @return Whether a context menu was displayed.
5296      */
showContextMenu()5297     public boolean showContextMenu() {
5298         return getParent().showContextMenuForChild(this);
5299     }
5300 
5301     /**
5302      * Bring up the context menu for this view, referring to the item under the specified point.
5303      *
5304      * @param x The referenced x coordinate.
5305      * @param y The referenced y coordinate.
5306      * @param metaState The keyboard modifiers that were pressed.
5307      * @return Whether a context menu was displayed.
5308      *
5309      * @hide
5310      */
showContextMenu(float x, float y, int metaState)5311     public boolean showContextMenu(float x, float y, int metaState) {
5312         return showContextMenu();
5313     }
5314 
5315     /**
5316      * Start an action mode with the default type {@link ActionMode#TYPE_PRIMARY}.
5317      *
5318      * @param callback Callback that will control the lifecycle of the action mode
5319      * @return The new action mode if it is started, null otherwise
5320      *
5321      * @see ActionMode
5322      * @see #startActionMode(android.view.ActionMode.Callback, int)
5323      */
startActionMode(ActionMode.Callback callback)5324     public ActionMode startActionMode(ActionMode.Callback callback) {
5325         return startActionMode(callback, ActionMode.TYPE_PRIMARY);
5326     }
5327 
5328     /**
5329      * Start an action mode with the given type.
5330      *
5331      * @param callback Callback that will control the lifecycle of the action mode
5332      * @param type One of {@link ActionMode#TYPE_PRIMARY} or {@link ActionMode#TYPE_FLOATING}.
5333      * @return The new action mode if it is started, null otherwise
5334      *
5335      * @see ActionMode
5336      */
startActionMode(ActionMode.Callback callback, int type)5337     public ActionMode startActionMode(ActionMode.Callback callback, int type) {
5338         ViewParent parent = getParent();
5339         if (parent == null) return null;
5340         try {
5341             return parent.startActionModeForChild(this, callback, type);
5342         } catch (AbstractMethodError ame) {
5343             // Older implementations of custom views might not implement this.
5344             return parent.startActionModeForChild(this, callback);
5345         }
5346     }
5347 
5348     /**
5349      * Call {@link Context#startActivityForResult(String, Intent, int, Bundle)} for the View's
5350      * Context, creating a unique View identifier to retrieve the result.
5351      *
5352      * @param intent The Intent to be started.
5353      * @param requestCode The request code to use.
5354      * @hide
5355      */
startActivityForResult(Intent intent, int requestCode)5356     public void startActivityForResult(Intent intent, int requestCode) {
5357         mStartActivityRequestWho = "@android:view:" + System.identityHashCode(this);
5358         getContext().startActivityForResult(mStartActivityRequestWho, intent, requestCode, null);
5359     }
5360 
5361     /**
5362      * If this View corresponds to the calling who, dispatches the activity result.
5363      * @param who The identifier for the targeted View to receive the result.
5364      * @param requestCode The integer request code originally supplied to
5365      *                    startActivityForResult(), allowing you to identify who this
5366      *                    result came from.
5367      * @param resultCode The integer result code returned by the child activity
5368      *                   through its setResult().
5369      * @param data An Intent, which can return result data to the caller
5370      *               (various data can be attached to Intent "extras").
5371      * @return {@code true} if the activity result was dispatched.
5372      * @hide
5373      */
dispatchActivityResult( String who, int requestCode, int resultCode, Intent data)5374     public boolean dispatchActivityResult(
5375             String who, int requestCode, int resultCode, Intent data) {
5376         if (mStartActivityRequestWho != null && mStartActivityRequestWho.equals(who)) {
5377             onActivityResult(requestCode, resultCode, data);
5378             mStartActivityRequestWho = null;
5379             return true;
5380         }
5381         return false;
5382     }
5383 
5384     /**
5385      * Receive the result from a previous call to {@link #startActivityForResult(Intent, int)}.
5386      *
5387      * @param requestCode The integer request code originally supplied to
5388      *                    startActivityForResult(), allowing you to identify who this
5389      *                    result came from.
5390      * @param resultCode The integer result code returned by the child activity
5391      *                   through its setResult().
5392      * @param data An Intent, which can return result data to the caller
5393      *               (various data can be attached to Intent "extras").
5394      * @hide
5395      */
onActivityResult(int requestCode, int resultCode, Intent data)5396     public void onActivityResult(int requestCode, int resultCode, Intent data) {
5397         // Do nothing.
5398     }
5399 
5400     /**
5401      * Register a callback to be invoked when a hardware key is pressed in this view.
5402      * Key presses in software input methods will generally not trigger the methods of
5403      * this listener.
5404      * @param l the key listener to attach to this view
5405      */
setOnKeyListener(OnKeyListener l)5406     public void setOnKeyListener(OnKeyListener l) {
5407         getListenerInfo().mOnKeyListener = l;
5408     }
5409 
5410     /**
5411      * Register a callback to be invoked when a touch event is sent to this view.
5412      * @param l the touch listener to attach to this view
5413      */
setOnTouchListener(OnTouchListener l)5414     public void setOnTouchListener(OnTouchListener l) {
5415         getListenerInfo().mOnTouchListener = l;
5416     }
5417 
5418     /**
5419      * Register a callback to be invoked when a generic motion event is sent to this view.
5420      * @param l the generic motion listener to attach to this view
5421      */
setOnGenericMotionListener(OnGenericMotionListener l)5422     public void setOnGenericMotionListener(OnGenericMotionListener l) {
5423         getListenerInfo().mOnGenericMotionListener = l;
5424     }
5425 
5426     /**
5427      * Register a callback to be invoked when a hover event is sent to this view.
5428      * @param l the hover listener to attach to this view
5429      */
setOnHoverListener(OnHoverListener l)5430     public void setOnHoverListener(OnHoverListener l) {
5431         getListenerInfo().mOnHoverListener = l;
5432     }
5433 
5434     /**
5435      * Register a drag event listener callback object for this View. The parameter is
5436      * an implementation of {@link android.view.View.OnDragListener}. To send a drag event to a
5437      * View, the system calls the
5438      * {@link android.view.View.OnDragListener#onDrag(View,DragEvent)} method.
5439      * @param l An implementation of {@link android.view.View.OnDragListener}.
5440      */
setOnDragListener(OnDragListener l)5441     public void setOnDragListener(OnDragListener l) {
5442         getListenerInfo().mOnDragListener = l;
5443     }
5444 
5445     /**
5446      * Give this view focus. This will cause
5447      * {@link #onFocusChanged(boolean, int, android.graphics.Rect)} to be called.
5448      *
5449      * Note: this does not check whether this {@link View} should get focus, it just
5450      * gives it focus no matter what.  It should only be called internally by framework
5451      * code that knows what it is doing, namely {@link #requestFocus(int, Rect)}.
5452      *
5453      * @param direction values are {@link View#FOCUS_UP}, {@link View#FOCUS_DOWN},
5454      *        {@link View#FOCUS_LEFT} or {@link View#FOCUS_RIGHT}. This is the direction which
5455      *        focus moved when requestFocus() is called. It may not always
5456      *        apply, in which case use the default View.FOCUS_DOWN.
5457      * @param previouslyFocusedRect The rectangle of the view that had focus
5458      *        prior in this View's coordinate system.
5459      */
handleFocusGainInternal(@ocusRealDirection int direction, Rect previouslyFocusedRect)5460     void handleFocusGainInternal(@FocusRealDirection int direction, Rect previouslyFocusedRect) {
5461         if (DBG) {
5462             System.out.println(this + " requestFocus()");
5463         }
5464 
5465         if ((mPrivateFlags & PFLAG_FOCUSED) == 0) {
5466             mPrivateFlags |= PFLAG_FOCUSED;
5467 
5468             View oldFocus = (mAttachInfo != null) ? getRootView().findFocus() : null;
5469 
5470             if (mParent != null) {
5471                 mParent.requestChildFocus(this, this);
5472             }
5473 
5474             if (mAttachInfo != null) {
5475                 mAttachInfo.mTreeObserver.dispatchOnGlobalFocusChange(oldFocus, this);
5476             }
5477 
5478             onFocusChanged(true, direction, previouslyFocusedRect);
5479             refreshDrawableState();
5480         }
5481     }
5482 
5483     /**
5484      * Populates <code>outRect</code> with the hotspot bounds. By default,
5485      * the hotspot bounds are identical to the screen bounds.
5486      *
5487      * @param outRect rect to populate with hotspot bounds
5488      * @hide Only for internal use by views and widgets.
5489      */
getHotspotBounds(Rect outRect)5490     public void getHotspotBounds(Rect outRect) {
5491         final Drawable background = getBackground();
5492         if (background != null) {
5493             background.getHotspotBounds(outRect);
5494         } else {
5495             getBoundsOnScreen(outRect);
5496         }
5497     }
5498 
5499     /**
5500      * Request that a rectangle of this view be visible on the screen,
5501      * scrolling if necessary just enough.
5502      *
5503      * <p>A View should call this if it maintains some notion of which part
5504      * of its content is interesting.  For example, a text editing view
5505      * should call this when its cursor moves.
5506      *
5507      * @param rectangle The rectangle.
5508      * @return Whether any parent scrolled.
5509      */
requestRectangleOnScreen(Rect rectangle)5510     public boolean requestRectangleOnScreen(Rect rectangle) {
5511         return requestRectangleOnScreen(rectangle, false);
5512     }
5513 
5514     /**
5515      * Request that a rectangle of this view be visible on the screen,
5516      * scrolling if necessary just enough.
5517      *
5518      * <p>A View should call this if it maintains some notion of which part
5519      * of its content is interesting.  For example, a text editing view
5520      * should call this when its cursor moves.
5521      *
5522      * <p>When <code>immediate</code> is set to true, scrolling will not be
5523      * animated.
5524      *
5525      * @param rectangle The rectangle.
5526      * @param immediate True to forbid animated scrolling, false otherwise
5527      * @return Whether any parent scrolled.
5528      */
requestRectangleOnScreen(Rect rectangle, boolean immediate)5529     public boolean requestRectangleOnScreen(Rect rectangle, boolean immediate) {
5530         if (mParent == null) {
5531             return false;
5532         }
5533 
5534         View child = this;
5535 
5536         RectF position = (mAttachInfo != null) ? mAttachInfo.mTmpTransformRect : new RectF();
5537         position.set(rectangle);
5538 
5539         ViewParent parent = mParent;
5540         boolean scrolled = false;
5541         while (parent != null) {
5542             rectangle.set((int) position.left, (int) position.top,
5543                     (int) position.right, (int) position.bottom);
5544 
5545             scrolled |= parent.requestChildRectangleOnScreen(child,
5546                     rectangle, immediate);
5547 
5548             if (!child.hasIdentityMatrix()) {
5549                 child.getMatrix().mapRect(position);
5550             }
5551 
5552             position.offset(child.mLeft, child.mTop);
5553 
5554             if (!(parent instanceof View)) {
5555                 break;
5556             }
5557 
5558             View parentView = (View) parent;
5559 
5560             position.offset(-parentView.getScrollX(), -parentView.getScrollY());
5561 
5562             child = parentView;
5563             parent = child.getParent();
5564         }
5565 
5566         return scrolled;
5567     }
5568 
5569     /**
5570      * Called when this view wants to give up focus. If focus is cleared
5571      * {@link #onFocusChanged(boolean, int, android.graphics.Rect)} is called.
5572      * <p>
5573      * <strong>Note:</strong> When a View clears focus the framework is trying
5574      * to give focus to the first focusable View from the top. Hence, if this
5575      * View is the first from the top that can take focus, then all callbacks
5576      * related to clearing focus will be invoked after which the framework will
5577      * give focus to this view.
5578      * </p>
5579      */
clearFocus()5580     public void clearFocus() {
5581         if (DBG) {
5582             System.out.println(this + " clearFocus()");
5583         }
5584 
5585         clearFocusInternal(null, true, true);
5586     }
5587 
5588     /**
5589      * Clears focus from the view, optionally propagating the change up through
5590      * the parent hierarchy and requesting that the root view place new focus.
5591      *
5592      * @param propagate whether to propagate the change up through the parent
5593      *            hierarchy
5594      * @param refocus when propagate is true, specifies whether to request the
5595      *            root view place new focus
5596      */
clearFocusInternal(View focused, boolean propagate, boolean refocus)5597     void clearFocusInternal(View focused, boolean propagate, boolean refocus) {
5598         if ((mPrivateFlags & PFLAG_FOCUSED) != 0) {
5599             mPrivateFlags &= ~PFLAG_FOCUSED;
5600 
5601             if (propagate && mParent != null) {
5602                 mParent.clearChildFocus(this);
5603             }
5604 
5605             onFocusChanged(false, 0, null);
5606             refreshDrawableState();
5607 
5608             if (propagate && (!refocus || !rootViewRequestFocus())) {
5609                 notifyGlobalFocusCleared(this);
5610             }
5611         }
5612     }
5613 
notifyGlobalFocusCleared(View oldFocus)5614     void notifyGlobalFocusCleared(View oldFocus) {
5615         if (oldFocus != null && mAttachInfo != null) {
5616             mAttachInfo.mTreeObserver.dispatchOnGlobalFocusChange(oldFocus, null);
5617         }
5618     }
5619 
rootViewRequestFocus()5620     boolean rootViewRequestFocus() {
5621         final View root = getRootView();
5622         return root != null && root.requestFocus();
5623     }
5624 
5625     /**
5626      * Called internally by the view system when a new view is getting focus.
5627      * This is what clears the old focus.
5628      * <p>
5629      * <b>NOTE:</b> The parent view's focused child must be updated manually
5630      * after calling this method. Otherwise, the view hierarchy may be left in
5631      * an inconstent state.
5632      */
unFocus(View focused)5633     void unFocus(View focused) {
5634         if (DBG) {
5635             System.out.println(this + " unFocus()");
5636         }
5637 
5638         clearFocusInternal(focused, false, false);
5639     }
5640 
5641     /**
5642      * Returns true if this view has focus itself, or is the ancestor of the
5643      * view that has focus.
5644      *
5645      * @return True if this view has or contains focus, false otherwise.
5646      */
5647     @ViewDebug.ExportedProperty(category = "focus")
hasFocus()5648     public boolean hasFocus() {
5649         return (mPrivateFlags & PFLAG_FOCUSED) != 0;
5650     }
5651 
5652     /**
5653      * Returns true if this view is focusable or if it contains a reachable View
5654      * for which {@link #hasFocusable()} returns true. A "reachable hasFocusable()"
5655      * is a View whose parents do not block descendants focus.
5656      *
5657      * Only {@link #VISIBLE} views are considered focusable.
5658      *
5659      * @return True if the view is focusable or if the view contains a focusable
5660      *         View, false otherwise.
5661      *
5662      * @see ViewGroup#FOCUS_BLOCK_DESCENDANTS
5663      * @see ViewGroup#getTouchscreenBlocksFocus()
5664      */
hasFocusable()5665     public boolean hasFocusable() {
5666         if (!isFocusableInTouchMode()) {
5667             for (ViewParent p = mParent; p instanceof ViewGroup; p = p.getParent()) {
5668                 final ViewGroup g = (ViewGroup) p;
5669                 if (g.shouldBlockFocusForTouchscreen()) {
5670                     return false;
5671                 }
5672             }
5673         }
5674         return (mViewFlags & VISIBILITY_MASK) == VISIBLE && isFocusable();
5675     }
5676 
5677     /**
5678      * Called by the view system when the focus state of this view changes.
5679      * When the focus change event is caused by directional navigation, direction
5680      * and previouslyFocusedRect provide insight into where the focus is coming from.
5681      * When overriding, be sure to call up through to the super class so that
5682      * the standard focus handling will occur.
5683      *
5684      * @param gainFocus True if the View has focus; false otherwise.
5685      * @param direction The direction focus has moved when requestFocus()
5686      *                  is called to give this view focus. Values are
5687      *                  {@link #FOCUS_UP}, {@link #FOCUS_DOWN}, {@link #FOCUS_LEFT},
5688      *                  {@link #FOCUS_RIGHT}, {@link #FOCUS_FORWARD}, or {@link #FOCUS_BACKWARD}.
5689      *                  It may not always apply, in which case use the default.
5690      * @param previouslyFocusedRect The rectangle, in this view's coordinate
5691      *        system, of the previously focused view.  If applicable, this will be
5692      *        passed in as finer grained information about where the focus is coming
5693      *        from (in addition to direction).  Will be <code>null</code> otherwise.
5694      */
5695     @CallSuper
onFocusChanged(boolean gainFocus, @FocusDirection int direction, @Nullable Rect previouslyFocusedRect)5696     protected void onFocusChanged(boolean gainFocus, @FocusDirection int direction,
5697             @Nullable Rect previouslyFocusedRect) {
5698         if (gainFocus) {
5699             sendAccessibilityEvent(AccessibilityEvent.TYPE_VIEW_FOCUSED);
5700         } else {
5701             notifyViewAccessibilityStateChangedIfNeeded(
5702                     AccessibilityEvent.CONTENT_CHANGE_TYPE_UNDEFINED);
5703         }
5704 
5705         InputMethodManager imm = InputMethodManager.peekInstance();
5706         if (!gainFocus) {
5707             if (isPressed()) {
5708                 setPressed(false);
5709             }
5710             if (imm != null && mAttachInfo != null
5711                     && mAttachInfo.mHasWindowFocus) {
5712                 imm.focusOut(this);
5713             }
5714             onFocusLost();
5715         } else if (imm != null && mAttachInfo != null
5716                 && mAttachInfo.mHasWindowFocus) {
5717             imm.focusIn(this);
5718         }
5719 
5720         invalidate(true);
5721         ListenerInfo li = mListenerInfo;
5722         if (li != null && li.mOnFocusChangeListener != null) {
5723             li.mOnFocusChangeListener.onFocusChange(this, gainFocus);
5724         }
5725 
5726         if (mAttachInfo != null) {
5727             mAttachInfo.mKeyDispatchState.reset(this);
5728         }
5729     }
5730 
5731     /**
5732      * Sends an accessibility event of the given type. If accessibility is
5733      * not enabled this method has no effect. The default implementation calls
5734      * {@link #onInitializeAccessibilityEvent(AccessibilityEvent)} first
5735      * to populate information about the event source (this View), then calls
5736      * {@link #dispatchPopulateAccessibilityEvent(AccessibilityEvent)} to
5737      * populate the text content of the event source including its descendants,
5738      * and last calls
5739      * {@link ViewParent#requestSendAccessibilityEvent(View, AccessibilityEvent)}
5740      * on its parent to request sending of the event to interested parties.
5741      * <p>
5742      * If an {@link AccessibilityDelegate} has been specified via calling
5743      * {@link #setAccessibilityDelegate(AccessibilityDelegate)} its
5744      * {@link AccessibilityDelegate#sendAccessibilityEvent(View, int)} is
5745      * responsible for handling this call.
5746      * </p>
5747      *
5748      * @param eventType The type of the event to send, as defined by several types from
5749      * {@link android.view.accessibility.AccessibilityEvent}, such as
5750      * {@link android.view.accessibility.AccessibilityEvent#TYPE_VIEW_CLICKED} or
5751      * {@link android.view.accessibility.AccessibilityEvent#TYPE_VIEW_HOVER_ENTER}.
5752      *
5753      * @see #onInitializeAccessibilityEvent(AccessibilityEvent)
5754      * @see #dispatchPopulateAccessibilityEvent(AccessibilityEvent)
5755      * @see ViewParent#requestSendAccessibilityEvent(View, AccessibilityEvent)
5756      * @see AccessibilityDelegate
5757      */
sendAccessibilityEvent(int eventType)5758     public void sendAccessibilityEvent(int eventType) {
5759         if (mAccessibilityDelegate != null) {
5760             mAccessibilityDelegate.sendAccessibilityEvent(this, eventType);
5761         } else {
5762             sendAccessibilityEventInternal(eventType);
5763         }
5764     }
5765 
5766     /**
5767      * Convenience method for sending a {@link AccessibilityEvent#TYPE_ANNOUNCEMENT}
5768      * {@link AccessibilityEvent} to make an announcement which is related to some
5769      * sort of a context change for which none of the events representing UI transitions
5770      * is a good fit. For example, announcing a new page in a book. If accessibility
5771      * is not enabled this method does nothing.
5772      *
5773      * @param text The announcement text.
5774      */
announceForAccessibility(CharSequence text)5775     public void announceForAccessibility(CharSequence text) {
5776         if (AccessibilityManager.getInstance(mContext).isEnabled() && mParent != null) {
5777             AccessibilityEvent event = AccessibilityEvent.obtain(
5778                     AccessibilityEvent.TYPE_ANNOUNCEMENT);
5779             onInitializeAccessibilityEvent(event);
5780             event.getText().add(text);
5781             event.setContentDescription(null);
5782             mParent.requestSendAccessibilityEvent(this, event);
5783         }
5784     }
5785 
5786     /**
5787      * @see #sendAccessibilityEvent(int)
5788      *
5789      * Note: Called from the default {@link AccessibilityDelegate}.
5790      *
5791      * @hide
5792      */
sendAccessibilityEventInternal(int eventType)5793     public void sendAccessibilityEventInternal(int eventType) {
5794         if (AccessibilityManager.getInstance(mContext).isEnabled()) {
5795             sendAccessibilityEventUnchecked(AccessibilityEvent.obtain(eventType));
5796         }
5797     }
5798 
5799     /**
5800      * This method behaves exactly as {@link #sendAccessibilityEvent(int)} but
5801      * takes as an argument an empty {@link AccessibilityEvent} and does not
5802      * perform a check whether accessibility is enabled.
5803      * <p>
5804      * If an {@link AccessibilityDelegate} has been specified via calling
5805      * {@link #setAccessibilityDelegate(AccessibilityDelegate)} its
5806      * {@link AccessibilityDelegate#sendAccessibilityEventUnchecked(View, AccessibilityEvent)}
5807      * is responsible for handling this call.
5808      * </p>
5809      *
5810      * @param event The event to send.
5811      *
5812      * @see #sendAccessibilityEvent(int)
5813      */
sendAccessibilityEventUnchecked(AccessibilityEvent event)5814     public void sendAccessibilityEventUnchecked(AccessibilityEvent event) {
5815         if (mAccessibilityDelegate != null) {
5816             mAccessibilityDelegate.sendAccessibilityEventUnchecked(this, event);
5817         } else {
5818             sendAccessibilityEventUncheckedInternal(event);
5819         }
5820     }
5821 
5822     /**
5823      * @see #sendAccessibilityEventUnchecked(AccessibilityEvent)
5824      *
5825      * Note: Called from the default {@link AccessibilityDelegate}.
5826      *
5827      * @hide
5828      */
sendAccessibilityEventUncheckedInternal(AccessibilityEvent event)5829     public void sendAccessibilityEventUncheckedInternal(AccessibilityEvent event) {
5830         if (!isShown()) {
5831             return;
5832         }
5833         onInitializeAccessibilityEvent(event);
5834         // Only a subset of accessibility events populates text content.
5835         if ((event.getEventType() & POPULATING_ACCESSIBILITY_EVENT_TYPES) != 0) {
5836             dispatchPopulateAccessibilityEvent(event);
5837         }
5838         // In the beginning we called #isShown(), so we know that getParent() is not null.
5839         getParent().requestSendAccessibilityEvent(this, event);
5840     }
5841 
5842     /**
5843      * Dispatches an {@link AccessibilityEvent} to the {@link View} first and then
5844      * to its children for adding their text content to the event. Note that the
5845      * event text is populated in a separate dispatch path since we add to the
5846      * event not only the text of the source but also the text of all its descendants.
5847      * A typical implementation will call
5848      * {@link #onPopulateAccessibilityEvent(AccessibilityEvent)} on the this view
5849      * and then call the {@link #dispatchPopulateAccessibilityEvent(AccessibilityEvent)}
5850      * on each child. Override this method if custom population of the event text
5851      * content is required.
5852      * <p>
5853      * If an {@link AccessibilityDelegate} has been specified via calling
5854      * {@link #setAccessibilityDelegate(AccessibilityDelegate)} its
5855      * {@link AccessibilityDelegate#dispatchPopulateAccessibilityEvent(View, AccessibilityEvent)}
5856      * is responsible for handling this call.
5857      * </p>
5858      * <p>
5859      * <em>Note:</em> Accessibility events of certain types are not dispatched for
5860      * populating the event text via this method. For details refer to {@link AccessibilityEvent}.
5861      * </p>
5862      *
5863      * @param event The event.
5864      *
5865      * @return True if the event population was completed.
5866      */
dispatchPopulateAccessibilityEvent(AccessibilityEvent event)5867     public boolean dispatchPopulateAccessibilityEvent(AccessibilityEvent event) {
5868         if (mAccessibilityDelegate != null) {
5869             return mAccessibilityDelegate.dispatchPopulateAccessibilityEvent(this, event);
5870         } else {
5871             return dispatchPopulateAccessibilityEventInternal(event);
5872         }
5873     }
5874 
5875     /**
5876      * @see #dispatchPopulateAccessibilityEvent(AccessibilityEvent)
5877      *
5878      * Note: Called from the default {@link AccessibilityDelegate}.
5879      *
5880      * @hide
5881      */
dispatchPopulateAccessibilityEventInternal(AccessibilityEvent event)5882     public boolean dispatchPopulateAccessibilityEventInternal(AccessibilityEvent event) {
5883         onPopulateAccessibilityEvent(event);
5884         return false;
5885     }
5886 
5887     /**
5888      * Called from {@link #dispatchPopulateAccessibilityEvent(AccessibilityEvent)}
5889      * giving a chance to this View to populate the accessibility event with its
5890      * text content. While this method is free to modify event
5891      * attributes other than text content, doing so should normally be performed in
5892      * {@link #onInitializeAccessibilityEvent(AccessibilityEvent)}.
5893      * <p>
5894      * Example: Adding formatted date string to an accessibility event in addition
5895      *          to the text added by the super implementation:
5896      * <pre> public void onPopulateAccessibilityEvent(AccessibilityEvent event) {
5897      *     super.onPopulateAccessibilityEvent(event);
5898      *     final int flags = DateUtils.FORMAT_SHOW_DATE | DateUtils.FORMAT_SHOW_WEEKDAY;
5899      *     String selectedDateUtterance = DateUtils.formatDateTime(mContext,
5900      *         mCurrentDate.getTimeInMillis(), flags);
5901      *     event.getText().add(selectedDateUtterance);
5902      * }</pre>
5903      * <p>
5904      * If an {@link AccessibilityDelegate} has been specified via calling
5905      * {@link #setAccessibilityDelegate(AccessibilityDelegate)} its
5906      * {@link AccessibilityDelegate#onPopulateAccessibilityEvent(View, AccessibilityEvent)}
5907      * is responsible for handling this call.
5908      * </p>
5909      * <p class="note"><strong>Note:</strong> Always call the super implementation before adding
5910      * information to the event, in case the default implementation has basic information to add.
5911      * </p>
5912      *
5913      * @param event The accessibility event which to populate.
5914      *
5915      * @see #sendAccessibilityEvent(int)
5916      * @see #dispatchPopulateAccessibilityEvent(AccessibilityEvent)
5917      */
5918     @CallSuper
onPopulateAccessibilityEvent(AccessibilityEvent event)5919     public void onPopulateAccessibilityEvent(AccessibilityEvent event) {
5920         if (mAccessibilityDelegate != null) {
5921             mAccessibilityDelegate.onPopulateAccessibilityEvent(this, event);
5922         } else {
5923             onPopulateAccessibilityEventInternal(event);
5924         }
5925     }
5926 
5927     /**
5928      * @see #onPopulateAccessibilityEvent(AccessibilityEvent)
5929      *
5930      * Note: Called from the default {@link AccessibilityDelegate}.
5931      *
5932      * @hide
5933      */
onPopulateAccessibilityEventInternal(AccessibilityEvent event)5934     public void onPopulateAccessibilityEventInternal(AccessibilityEvent event) {
5935     }
5936 
5937     /**
5938      * Initializes an {@link AccessibilityEvent} with information about
5939      * this View which is the event source. In other words, the source of
5940      * an accessibility event is the view whose state change triggered firing
5941      * the event.
5942      * <p>
5943      * Example: Setting the password property of an event in addition
5944      *          to properties set by the super implementation:
5945      * <pre> public void onInitializeAccessibilityEvent(AccessibilityEvent event) {
5946      *     super.onInitializeAccessibilityEvent(event);
5947      *     event.setPassword(true);
5948      * }</pre>
5949      * <p>
5950      * If an {@link AccessibilityDelegate} has been specified via calling
5951      * {@link #setAccessibilityDelegate(AccessibilityDelegate)} its
5952      * {@link AccessibilityDelegate#onInitializeAccessibilityEvent(View, AccessibilityEvent)}
5953      * is responsible for handling this call.
5954      * </p>
5955      * <p class="note"><strong>Note:</strong> Always call the super implementation before adding
5956      * information to the event, in case the default implementation has basic information to add.
5957      * </p>
5958      * @param event The event to initialize.
5959      *
5960      * @see #sendAccessibilityEvent(int)
5961      * @see #dispatchPopulateAccessibilityEvent(AccessibilityEvent)
5962      */
5963     @CallSuper
onInitializeAccessibilityEvent(AccessibilityEvent event)5964     public void onInitializeAccessibilityEvent(AccessibilityEvent event) {
5965         if (mAccessibilityDelegate != null) {
5966             mAccessibilityDelegate.onInitializeAccessibilityEvent(this, event);
5967         } else {
5968             onInitializeAccessibilityEventInternal(event);
5969         }
5970     }
5971 
5972     /**
5973      * @see #onInitializeAccessibilityEvent(AccessibilityEvent)
5974      *
5975      * Note: Called from the default {@link AccessibilityDelegate}.
5976      *
5977      * @hide
5978      */
onInitializeAccessibilityEventInternal(AccessibilityEvent event)5979     public void onInitializeAccessibilityEventInternal(AccessibilityEvent event) {
5980         event.setSource(this);
5981         event.setClassName(getAccessibilityClassName());
5982         event.setPackageName(getContext().getPackageName());
5983         event.setEnabled(isEnabled());
5984         event.setContentDescription(mContentDescription);
5985 
5986         switch (event.getEventType()) {
5987             case AccessibilityEvent.TYPE_VIEW_FOCUSED: {
5988                 ArrayList<View> focusablesTempList = (mAttachInfo != null)
5989                         ? mAttachInfo.mTempArrayList : new ArrayList<View>();
5990                 getRootView().addFocusables(focusablesTempList, View.FOCUS_FORWARD, FOCUSABLES_ALL);
5991                 event.setItemCount(focusablesTempList.size());
5992                 event.setCurrentItemIndex(focusablesTempList.indexOf(this));
5993                 if (mAttachInfo != null) {
5994                     focusablesTempList.clear();
5995                 }
5996             } break;
5997             case AccessibilityEvent.TYPE_VIEW_TEXT_SELECTION_CHANGED: {
5998                 CharSequence text = getIterableTextForAccessibility();
5999                 if (text != null && text.length() > 0) {
6000                     event.setFromIndex(getAccessibilitySelectionStart());
6001                     event.setToIndex(getAccessibilitySelectionEnd());
6002                     event.setItemCount(text.length());
6003                 }
6004             } break;
6005         }
6006     }
6007 
6008     /**
6009      * Returns an {@link AccessibilityNodeInfo} representing this view from the
6010      * point of view of an {@link android.accessibilityservice.AccessibilityService}.
6011      * This method is responsible for obtaining an accessibility node info from a
6012      * pool of reusable instances and calling
6013      * {@link #onInitializeAccessibilityNodeInfo(AccessibilityNodeInfo)} on this view to
6014      * initialize the former.
6015      * <p>
6016      * Note: The client is responsible for recycling the obtained instance by calling
6017      *       {@link AccessibilityNodeInfo#recycle()} to minimize object creation.
6018      * </p>
6019      *
6020      * @return A populated {@link AccessibilityNodeInfo}.
6021      *
6022      * @see AccessibilityNodeInfo
6023      */
createAccessibilityNodeInfo()6024     public AccessibilityNodeInfo createAccessibilityNodeInfo() {
6025         if (mAccessibilityDelegate != null) {
6026             return mAccessibilityDelegate.createAccessibilityNodeInfo(this);
6027         } else {
6028             return createAccessibilityNodeInfoInternal();
6029         }
6030     }
6031 
6032     /**
6033      * @see #createAccessibilityNodeInfo()
6034      *
6035      * @hide
6036      */
createAccessibilityNodeInfoInternal()6037     public AccessibilityNodeInfo createAccessibilityNodeInfoInternal() {
6038         AccessibilityNodeProvider provider = getAccessibilityNodeProvider();
6039         if (provider != null) {
6040             return provider.createAccessibilityNodeInfo(AccessibilityNodeProvider.HOST_VIEW_ID);
6041         } else {
6042             AccessibilityNodeInfo info = AccessibilityNodeInfo.obtain(this);
6043             onInitializeAccessibilityNodeInfo(info);
6044             return info;
6045         }
6046     }
6047 
6048     /**
6049      * Initializes an {@link AccessibilityNodeInfo} with information about this view.
6050      * The base implementation sets:
6051      * <ul>
6052      *   <li>{@link AccessibilityNodeInfo#setParent(View)},</li>
6053      *   <li>{@link AccessibilityNodeInfo#setBoundsInParent(Rect)},</li>
6054      *   <li>{@link AccessibilityNodeInfo#setBoundsInScreen(Rect)},</li>
6055      *   <li>{@link AccessibilityNodeInfo#setPackageName(CharSequence)},</li>
6056      *   <li>{@link AccessibilityNodeInfo#setClassName(CharSequence)},</li>
6057      *   <li>{@link AccessibilityNodeInfo#setContentDescription(CharSequence)},</li>
6058      *   <li>{@link AccessibilityNodeInfo#setEnabled(boolean)},</li>
6059      *   <li>{@link AccessibilityNodeInfo#setClickable(boolean)},</li>
6060      *   <li>{@link AccessibilityNodeInfo#setFocusable(boolean)},</li>
6061      *   <li>{@link AccessibilityNodeInfo#setFocused(boolean)},</li>
6062      *   <li>{@link AccessibilityNodeInfo#setLongClickable(boolean)},</li>
6063      *   <li>{@link AccessibilityNodeInfo#setSelected(boolean)},</li>
6064      *   <li>{@link AccessibilityNodeInfo#setContextClickable(boolean)}</li>
6065      * </ul>
6066      * <p>
6067      * Subclasses should override this method, call the super implementation,
6068      * and set additional attributes.
6069      * </p>
6070      * <p>
6071      * If an {@link AccessibilityDelegate} has been specified via calling
6072      * {@link #setAccessibilityDelegate(AccessibilityDelegate)} its
6073      * {@link AccessibilityDelegate#onInitializeAccessibilityNodeInfo(View, AccessibilityNodeInfo)}
6074      * is responsible for handling this call.
6075      * </p>
6076      *
6077      * @param info The instance to initialize.
6078      */
6079     @CallSuper
onInitializeAccessibilityNodeInfo(AccessibilityNodeInfo info)6080     public void onInitializeAccessibilityNodeInfo(AccessibilityNodeInfo info) {
6081         if (mAccessibilityDelegate != null) {
6082             mAccessibilityDelegate.onInitializeAccessibilityNodeInfo(this, info);
6083         } else {
6084             onInitializeAccessibilityNodeInfoInternal(info);
6085         }
6086     }
6087 
6088     /**
6089      * Gets the location of this view in screen coordinates.
6090      *
6091      * @param outRect The output location
6092      * @hide
6093      */
getBoundsOnScreen(Rect outRect)6094     public void getBoundsOnScreen(Rect outRect) {
6095         getBoundsOnScreen(outRect, false);
6096     }
6097 
6098     /**
6099      * Gets the location of this view in screen coordinates.
6100      *
6101      * @param outRect The output location
6102      * @param clipToParent Whether to clip child bounds to the parent ones.
6103      * @hide
6104      */
getBoundsOnScreen(Rect outRect, boolean clipToParent)6105     public void getBoundsOnScreen(Rect outRect, boolean clipToParent) {
6106         if (mAttachInfo == null) {
6107             return;
6108         }
6109 
6110         RectF position = mAttachInfo.mTmpTransformRect;
6111         position.set(0, 0, mRight - mLeft, mBottom - mTop);
6112 
6113         if (!hasIdentityMatrix()) {
6114             getMatrix().mapRect(position);
6115         }
6116 
6117         position.offset(mLeft, mTop);
6118 
6119         ViewParent parent = mParent;
6120         while (parent instanceof View) {
6121             View parentView = (View) parent;
6122 
6123             position.offset(-parentView.mScrollX, -parentView.mScrollY);
6124 
6125             if (clipToParent) {
6126                 position.left = Math.max(position.left, 0);
6127                 position.top = Math.max(position.top, 0);
6128                 position.right = Math.min(position.right, parentView.getWidth());
6129                 position.bottom = Math.min(position.bottom, parentView.getHeight());
6130             }
6131 
6132             if (!parentView.hasIdentityMatrix()) {
6133                 parentView.getMatrix().mapRect(position);
6134             }
6135 
6136             position.offset(parentView.mLeft, parentView.mTop);
6137 
6138             parent = parentView.mParent;
6139         }
6140 
6141         if (parent instanceof ViewRootImpl) {
6142             ViewRootImpl viewRootImpl = (ViewRootImpl) parent;
6143             position.offset(0, -viewRootImpl.mCurScrollY);
6144         }
6145 
6146         position.offset(mAttachInfo.mWindowLeft, mAttachInfo.mWindowTop);
6147 
6148         outRect.set((int) (position.left + 0.5f), (int) (position.top + 0.5f),
6149                 (int) (position.right + 0.5f), (int) (position.bottom + 0.5f));
6150     }
6151 
6152     /**
6153      * Return the class name of this object to be used for accessibility purposes.
6154      * Subclasses should only override this if they are implementing something that
6155      * should be seen as a completely new class of view when used by accessibility,
6156      * unrelated to the class it is deriving from.  This is used to fill in
6157      * {@link AccessibilityNodeInfo#setClassName AccessibilityNodeInfo.setClassName}.
6158      */
getAccessibilityClassName()6159     public CharSequence getAccessibilityClassName() {
6160         return View.class.getName();
6161     }
6162 
6163     /**
6164      * Called when assist structure is being retrieved from a view as part of
6165      * {@link android.app.Activity#onProvideAssistData Activity.onProvideAssistData}.
6166      * @param structure Fill in with structured view data.  The default implementation
6167      * fills in all data that can be inferred from the view itself.
6168      */
onProvideStructure(ViewStructure structure)6169     public void onProvideStructure(ViewStructure structure) {
6170         final int id = mID;
6171         if (id > 0 && (id&0xff000000) != 0 && (id&0x00ff0000) != 0
6172                 && (id&0x0000ffff) != 0) {
6173             String pkg, type, entry;
6174             try {
6175                 final Resources res = getResources();
6176                 entry = res.getResourceEntryName(id);
6177                 type = res.getResourceTypeName(id);
6178                 pkg = res.getResourcePackageName(id);
6179             } catch (Resources.NotFoundException e) {
6180                 entry = type = pkg = null;
6181             }
6182             structure.setId(id, pkg, type, entry);
6183         } else {
6184             structure.setId(id, null, null, null);
6185         }
6186         structure.setDimens(mLeft, mTop, mScrollX, mScrollY, mRight - mLeft, mBottom - mTop);
6187         if (!hasIdentityMatrix()) {
6188             structure.setTransformation(getMatrix());
6189         }
6190         structure.setElevation(getZ());
6191         structure.setVisibility(getVisibility());
6192         structure.setEnabled(isEnabled());
6193         if (isClickable()) {
6194             structure.setClickable(true);
6195         }
6196         if (isFocusable()) {
6197             structure.setFocusable(true);
6198         }
6199         if (isFocused()) {
6200             structure.setFocused(true);
6201         }
6202         if (isAccessibilityFocused()) {
6203             structure.setAccessibilityFocused(true);
6204         }
6205         if (isSelected()) {
6206             structure.setSelected(true);
6207         }
6208         if (isActivated()) {
6209             structure.setActivated(true);
6210         }
6211         if (isLongClickable()) {
6212             structure.setLongClickable(true);
6213         }
6214         if (this instanceof Checkable) {
6215             structure.setCheckable(true);
6216             if (((Checkable)this).isChecked()) {
6217                 structure.setChecked(true);
6218             }
6219         }
6220         if (isContextClickable()) {
6221             structure.setContextClickable(true);
6222         }
6223         structure.setClassName(getAccessibilityClassName().toString());
6224         structure.setContentDescription(getContentDescription());
6225     }
6226 
6227     /**
6228      * Called when assist structure is being retrieved from a view as part of
6229      * {@link android.app.Activity#onProvideAssistData Activity.onProvideAssistData} to
6230      * generate additional virtual structure under this view.  The defaullt implementation
6231      * uses {@link #getAccessibilityNodeProvider()} to try to generate this from the
6232      * view's virtual accessibility nodes, if any.  You can override this for a more
6233      * optimal implementation providing this data.
6234      */
onProvideVirtualStructure(ViewStructure structure)6235     public void onProvideVirtualStructure(ViewStructure structure) {
6236         AccessibilityNodeProvider provider = getAccessibilityNodeProvider();
6237         if (provider != null) {
6238             AccessibilityNodeInfo info = createAccessibilityNodeInfo();
6239             structure.setChildCount(1);
6240             ViewStructure root = structure.newChild(0);
6241             populateVirtualStructure(root, provider, info);
6242             info.recycle();
6243         }
6244     }
6245 
populateVirtualStructure(ViewStructure structure, AccessibilityNodeProvider provider, AccessibilityNodeInfo info)6246     private void populateVirtualStructure(ViewStructure structure,
6247             AccessibilityNodeProvider provider, AccessibilityNodeInfo info) {
6248         structure.setId(AccessibilityNodeInfo.getVirtualDescendantId(info.getSourceNodeId()),
6249                 null, null, null);
6250         Rect rect = structure.getTempRect();
6251         info.getBoundsInParent(rect);
6252         structure.setDimens(rect.left, rect.top, 0, 0, rect.width(), rect.height());
6253         structure.setVisibility(VISIBLE);
6254         structure.setEnabled(info.isEnabled());
6255         if (info.isClickable()) {
6256             structure.setClickable(true);
6257         }
6258         if (info.isFocusable()) {
6259             structure.setFocusable(true);
6260         }
6261         if (info.isFocused()) {
6262             structure.setFocused(true);
6263         }
6264         if (info.isAccessibilityFocused()) {
6265             structure.setAccessibilityFocused(true);
6266         }
6267         if (info.isSelected()) {
6268             structure.setSelected(true);
6269         }
6270         if (info.isLongClickable()) {
6271             structure.setLongClickable(true);
6272         }
6273         if (info.isCheckable()) {
6274             structure.setCheckable(true);
6275             if (info.isChecked()) {
6276                 structure.setChecked(true);
6277             }
6278         }
6279         if (info.isContextClickable()) {
6280             structure.setContextClickable(true);
6281         }
6282         CharSequence cname = info.getClassName();
6283         structure.setClassName(cname != null ? cname.toString() : null);
6284         structure.setContentDescription(info.getContentDescription());
6285         if (info.getText() != null || info.getError() != null) {
6286             structure.setText(info.getText(), info.getTextSelectionStart(),
6287                     info.getTextSelectionEnd());
6288         }
6289         final int NCHILDREN = info.getChildCount();
6290         if (NCHILDREN > 0) {
6291             structure.setChildCount(NCHILDREN);
6292             for (int i=0; i<NCHILDREN; i++) {
6293                 AccessibilityNodeInfo cinfo = provider.createAccessibilityNodeInfo(
6294                         AccessibilityNodeInfo.getVirtualDescendantId(info.getChildId(i)));
6295                 ViewStructure child = structure.newChild(i);
6296                 populateVirtualStructure(child, provider, cinfo);
6297                 cinfo.recycle();
6298             }
6299         }
6300     }
6301 
6302     /**
6303      * Dispatch creation of {@link ViewStructure} down the hierarchy.  The default
6304      * implementation calls {@link #onProvideStructure} and
6305      * {@link #onProvideVirtualStructure}.
6306      */
dispatchProvideStructure(ViewStructure structure)6307     public void dispatchProvideStructure(ViewStructure structure) {
6308         if (!isAssistBlocked()) {
6309             onProvideStructure(structure);
6310             onProvideVirtualStructure(structure);
6311         } else {
6312             structure.setClassName(getAccessibilityClassName().toString());
6313             structure.setAssistBlocked(true);
6314         }
6315     }
6316 
6317     /**
6318      * @see #onInitializeAccessibilityNodeInfo(AccessibilityNodeInfo)
6319      *
6320      * Note: Called from the default {@link AccessibilityDelegate}.
6321      *
6322      * @hide
6323      */
onInitializeAccessibilityNodeInfoInternal(AccessibilityNodeInfo info)6324     public void onInitializeAccessibilityNodeInfoInternal(AccessibilityNodeInfo info) {
6325         if (mAttachInfo == null) {
6326             return;
6327         }
6328 
6329         Rect bounds = mAttachInfo.mTmpInvalRect;
6330 
6331         getDrawingRect(bounds);
6332         info.setBoundsInParent(bounds);
6333 
6334         getBoundsOnScreen(bounds, true);
6335         info.setBoundsInScreen(bounds);
6336 
6337         ViewParent parent = getParentForAccessibility();
6338         if (parent instanceof View) {
6339             info.setParent((View) parent);
6340         }
6341 
6342         if (mID != View.NO_ID) {
6343             View rootView = getRootView();
6344             if (rootView == null) {
6345                 rootView = this;
6346             }
6347 
6348             View label = rootView.findLabelForView(this, mID);
6349             if (label != null) {
6350                 info.setLabeledBy(label);
6351             }
6352 
6353             if ((mAttachInfo.mAccessibilityFetchFlags
6354                     & AccessibilityNodeInfo.FLAG_REPORT_VIEW_IDS) != 0
6355                     && Resources.resourceHasPackage(mID)) {
6356                 try {
6357                     String viewId = getResources().getResourceName(mID);
6358                     info.setViewIdResourceName(viewId);
6359                 } catch (Resources.NotFoundException nfe) {
6360                     /* ignore */
6361                 }
6362             }
6363         }
6364 
6365         if (mLabelForId != View.NO_ID) {
6366             View rootView = getRootView();
6367             if (rootView == null) {
6368                 rootView = this;
6369             }
6370             View labeled = rootView.findViewInsideOutShouldExist(this, mLabelForId);
6371             if (labeled != null) {
6372                 info.setLabelFor(labeled);
6373             }
6374         }
6375 
6376         if (mAccessibilityTraversalBeforeId != View.NO_ID) {
6377             View rootView = getRootView();
6378             if (rootView == null) {
6379                 rootView = this;
6380             }
6381             View next = rootView.findViewInsideOutShouldExist(this,
6382                     mAccessibilityTraversalBeforeId);
6383             if (next != null && next.includeForAccessibility()) {
6384                 info.setTraversalBefore(next);
6385             }
6386         }
6387 
6388         if (mAccessibilityTraversalAfterId != View.NO_ID) {
6389             View rootView = getRootView();
6390             if (rootView == null) {
6391                 rootView = this;
6392             }
6393             View next = rootView.findViewInsideOutShouldExist(this,
6394                     mAccessibilityTraversalAfterId);
6395             if (next != null && next.includeForAccessibility()) {
6396                 info.setTraversalAfter(next);
6397             }
6398         }
6399 
6400         info.setVisibleToUser(isVisibleToUser());
6401 
6402         info.setPackageName(mContext.getPackageName());
6403         info.setClassName(getAccessibilityClassName());
6404         info.setContentDescription(getContentDescription());
6405 
6406         info.setEnabled(isEnabled());
6407         info.setClickable(isClickable());
6408         info.setFocusable(isFocusable());
6409         info.setFocused(isFocused());
6410         info.setAccessibilityFocused(isAccessibilityFocused());
6411         info.setSelected(isSelected());
6412         info.setLongClickable(isLongClickable());
6413         info.setContextClickable(isContextClickable());
6414         info.setLiveRegion(getAccessibilityLiveRegion());
6415 
6416         // TODO: These make sense only if we are in an AdapterView but all
6417         // views can be selected. Maybe from accessibility perspective
6418         // we should report as selectable view in an AdapterView.
6419         info.addAction(AccessibilityNodeInfo.ACTION_SELECT);
6420         info.addAction(AccessibilityNodeInfo.ACTION_CLEAR_SELECTION);
6421 
6422         if (isFocusable()) {
6423             if (isFocused()) {
6424                 info.addAction(AccessibilityNodeInfo.ACTION_CLEAR_FOCUS);
6425             } else {
6426                 info.addAction(AccessibilityNodeInfo.ACTION_FOCUS);
6427             }
6428         }
6429 
6430         if (!isAccessibilityFocused()) {
6431             info.addAction(AccessibilityNodeInfo.ACTION_ACCESSIBILITY_FOCUS);
6432         } else {
6433             info.addAction(AccessibilityNodeInfo.ACTION_CLEAR_ACCESSIBILITY_FOCUS);
6434         }
6435 
6436         if (isClickable() && isEnabled()) {
6437             info.addAction(AccessibilityNodeInfo.ACTION_CLICK);
6438         }
6439 
6440         if (isLongClickable() && isEnabled()) {
6441             info.addAction(AccessibilityNodeInfo.ACTION_LONG_CLICK);
6442         }
6443 
6444         if (isContextClickable() && isEnabled()) {
6445             info.addAction(AccessibilityAction.ACTION_CONTEXT_CLICK);
6446         }
6447 
6448         CharSequence text = getIterableTextForAccessibility();
6449         if (text != null && text.length() > 0) {
6450             info.setTextSelection(getAccessibilitySelectionStart(), getAccessibilitySelectionEnd());
6451 
6452             info.addAction(AccessibilityNodeInfo.ACTION_SET_SELECTION);
6453             info.addAction(AccessibilityNodeInfo.ACTION_NEXT_AT_MOVEMENT_GRANULARITY);
6454             info.addAction(AccessibilityNodeInfo.ACTION_PREVIOUS_AT_MOVEMENT_GRANULARITY);
6455             info.setMovementGranularities(AccessibilityNodeInfo.MOVEMENT_GRANULARITY_CHARACTER
6456                     | AccessibilityNodeInfo.MOVEMENT_GRANULARITY_WORD
6457                     | AccessibilityNodeInfo.MOVEMENT_GRANULARITY_PARAGRAPH);
6458         }
6459 
6460         info.addAction(AccessibilityAction.ACTION_SHOW_ON_SCREEN);
6461     }
6462 
findLabelForView(View view, int labeledId)6463     private View findLabelForView(View view, int labeledId) {
6464         if (mMatchLabelForPredicate == null) {
6465             mMatchLabelForPredicate = new MatchLabelForPredicate();
6466         }
6467         mMatchLabelForPredicate.mLabeledId = labeledId;
6468         return findViewByPredicateInsideOut(view, mMatchLabelForPredicate);
6469     }
6470 
6471     /**
6472      * Computes whether this view is visible to the user. Such a view is
6473      * attached, visible, all its predecessors are visible, it is not clipped
6474      * entirely by its predecessors, and has an alpha greater than zero.
6475      *
6476      * @return Whether the view is visible on the screen.
6477      *
6478      * @hide
6479      */
isVisibleToUser()6480     protected boolean isVisibleToUser() {
6481         return isVisibleToUser(null);
6482     }
6483 
6484     /**
6485      * Computes whether the given portion of this view is visible to the user.
6486      * Such a view is attached, visible, all its predecessors are visible,
6487      * has an alpha greater than zero, and the specified portion is not
6488      * clipped entirely by its predecessors.
6489      *
6490      * @param boundInView the portion of the view to test; coordinates should be relative; may be
6491      *                    <code>null</code>, and the entire view will be tested in this case.
6492      *                    When <code>true</code> is returned by the function, the actual visible
6493      *                    region will be stored in this parameter; that is, if boundInView is fully
6494      *                    contained within the view, no modification will be made, otherwise regions
6495      *                    outside of the visible area of the view will be clipped.
6496      *
6497      * @return Whether the specified portion of the view is visible on the screen.
6498      *
6499      * @hide
6500      */
isVisibleToUser(Rect boundInView)6501     protected boolean isVisibleToUser(Rect boundInView) {
6502         if (mAttachInfo != null) {
6503             // Attached to invisible window means this view is not visible.
6504             if (mAttachInfo.mWindowVisibility != View.VISIBLE) {
6505                 return false;
6506             }
6507             // An invisible predecessor or one with alpha zero means
6508             // that this view is not visible to the user.
6509             Object current = this;
6510             while (current instanceof View) {
6511                 View view = (View) current;
6512                 // We have attach info so this view is attached and there is no
6513                 // need to check whether we reach to ViewRootImpl on the way up.
6514                 if (view.getAlpha() <= 0 || view.getTransitionAlpha() <= 0 ||
6515                         view.getVisibility() != VISIBLE) {
6516                     return false;
6517                 }
6518                 current = view.mParent;
6519             }
6520             // Check if the view is entirely covered by its predecessors.
6521             Rect visibleRect = mAttachInfo.mTmpInvalRect;
6522             Point offset = mAttachInfo.mPoint;
6523             if (!getGlobalVisibleRect(visibleRect, offset)) {
6524                 return false;
6525             }
6526             // Check if the visible portion intersects the rectangle of interest.
6527             if (boundInView != null) {
6528                 visibleRect.offset(-offset.x, -offset.y);
6529                 return boundInView.intersect(visibleRect);
6530             }
6531             return true;
6532         }
6533         return false;
6534     }
6535 
6536     /**
6537      * Returns the delegate for implementing accessibility support via
6538      * composition. For more details see {@link AccessibilityDelegate}.
6539      *
6540      * @return The delegate, or null if none set.
6541      *
6542      * @hide
6543      */
getAccessibilityDelegate()6544     public AccessibilityDelegate getAccessibilityDelegate() {
6545         return mAccessibilityDelegate;
6546     }
6547 
6548     /**
6549      * Sets a delegate for implementing accessibility support via composition as
6550      * opposed to inheritance. The delegate's primary use is for implementing
6551      * backwards compatible widgets. For more details see {@link AccessibilityDelegate}.
6552      *
6553      * @param delegate The delegate instance.
6554      *
6555      * @see AccessibilityDelegate
6556      */
setAccessibilityDelegate(@ullable AccessibilityDelegate delegate)6557     public void setAccessibilityDelegate(@Nullable AccessibilityDelegate delegate) {
6558         mAccessibilityDelegate = delegate;
6559     }
6560 
6561     /**
6562      * Gets the provider for managing a virtual view hierarchy rooted at this View
6563      * and reported to {@link android.accessibilityservice.AccessibilityService}s
6564      * that explore the window content.
6565      * <p>
6566      * If this method returns an instance, this instance is responsible for managing
6567      * {@link AccessibilityNodeInfo}s describing the virtual sub-tree rooted at this
6568      * View including the one representing the View itself. Similarly the returned
6569      * instance is responsible for performing accessibility actions on any virtual
6570      * view or the root view itself.
6571      * </p>
6572      * <p>
6573      * If an {@link AccessibilityDelegate} has been specified via calling
6574      * {@link #setAccessibilityDelegate(AccessibilityDelegate)} its
6575      * {@link AccessibilityDelegate#getAccessibilityNodeProvider(View)}
6576      * is responsible for handling this call.
6577      * </p>
6578      *
6579      * @return The provider.
6580      *
6581      * @see AccessibilityNodeProvider
6582      */
getAccessibilityNodeProvider()6583     public AccessibilityNodeProvider getAccessibilityNodeProvider() {
6584         if (mAccessibilityDelegate != null) {
6585             return mAccessibilityDelegate.getAccessibilityNodeProvider(this);
6586         } else {
6587             return null;
6588         }
6589     }
6590 
6591     /**
6592      * Gets the unique identifier of this view on the screen for accessibility purposes.
6593      * If this {@link View} is not attached to any window, {@value #NO_ID} is returned.
6594      *
6595      * @return The view accessibility id.
6596      *
6597      * @hide
6598      */
getAccessibilityViewId()6599     public int getAccessibilityViewId() {
6600         if (mAccessibilityViewId == NO_ID) {
6601             mAccessibilityViewId = sNextAccessibilityViewId++;
6602         }
6603         return mAccessibilityViewId;
6604     }
6605 
6606     /**
6607      * Gets the unique identifier of the window in which this View reseides.
6608      *
6609      * @return The window accessibility id.
6610      *
6611      * @hide
6612      */
getAccessibilityWindowId()6613     public int getAccessibilityWindowId() {
6614         return mAttachInfo != null ? mAttachInfo.mAccessibilityWindowId
6615                 : AccessibilityNodeInfo.UNDEFINED_ITEM_ID;
6616     }
6617 
6618     /**
6619      * Gets the {@link View} description. It briefly describes the view and is
6620      * primarily used for accessibility support. Set this property to enable
6621      * better accessibility support for your application. This is especially
6622      * true for views that do not have textual representation (For example,
6623      * ImageButton).
6624      *
6625      * @return The content description.
6626      *
6627      * @attr ref android.R.styleable#View_contentDescription
6628      */
6629     @ViewDebug.ExportedProperty(category = "accessibility")
getContentDescription()6630     public CharSequence getContentDescription() {
6631         return mContentDescription;
6632     }
6633 
6634     /**
6635      * Sets the {@link View} description. It briefly describes the view and is
6636      * primarily used for accessibility support. Set this property to enable
6637      * better accessibility support for your application. This is especially
6638      * true for views that do not have textual representation (For example,
6639      * ImageButton).
6640      *
6641      * @param contentDescription The content description.
6642      *
6643      * @attr ref android.R.styleable#View_contentDescription
6644      */
6645     @RemotableViewMethod
setContentDescription(CharSequence contentDescription)6646     public void setContentDescription(CharSequence contentDescription) {
6647         if (mContentDescription == null) {
6648             if (contentDescription == null) {
6649                 return;
6650             }
6651         } else if (mContentDescription.equals(contentDescription)) {
6652             return;
6653         }
6654         mContentDescription = contentDescription;
6655         final boolean nonEmptyDesc = contentDescription != null && contentDescription.length() > 0;
6656         if (nonEmptyDesc && getImportantForAccessibility() == IMPORTANT_FOR_ACCESSIBILITY_AUTO) {
6657             setImportantForAccessibility(IMPORTANT_FOR_ACCESSIBILITY_YES);
6658             notifySubtreeAccessibilityStateChangedIfNeeded();
6659         } else {
6660             notifyViewAccessibilityStateChangedIfNeeded(
6661                     AccessibilityEvent.CONTENT_CHANGE_TYPE_CONTENT_DESCRIPTION);
6662         }
6663     }
6664 
6665     /**
6666      * Sets the id of a view before which this one is visited in accessibility traversal.
6667      * A screen-reader must visit the content of this view before the content of the one
6668      * it precedes. For example, if view B is set to be before view A, then a screen-reader
6669      * will traverse the entire content of B before traversing the entire content of A,
6670      * regardles of what traversal strategy it is using.
6671      * <p>
6672      * Views that do not have specified before/after relationships are traversed in order
6673      * determined by the screen-reader.
6674      * </p>
6675      * <p>
6676      * Setting that this view is before a view that is not important for accessibility
6677      * or if this view is not important for accessibility will have no effect as the
6678      * screen-reader is not aware of unimportant views.
6679      * </p>
6680      *
6681      * @param beforeId The id of a view this one precedes in accessibility traversal.
6682      *
6683      * @attr ref android.R.styleable#View_accessibilityTraversalBefore
6684      *
6685      * @see #setImportantForAccessibility(int)
6686      */
6687     @RemotableViewMethod
setAccessibilityTraversalBefore(int beforeId)6688     public void setAccessibilityTraversalBefore(int beforeId) {
6689         if (mAccessibilityTraversalBeforeId == beforeId) {
6690             return;
6691         }
6692         mAccessibilityTraversalBeforeId = beforeId;
6693         notifyViewAccessibilityStateChangedIfNeeded(
6694                 AccessibilityEvent.CONTENT_CHANGE_TYPE_UNDEFINED);
6695     }
6696 
6697     /**
6698      * Gets the id of a view before which this one is visited in accessibility traversal.
6699      *
6700      * @return The id of a view this one precedes in accessibility traversal if
6701      *         specified, otherwise {@link #NO_ID}.
6702      *
6703      * @see #setAccessibilityTraversalBefore(int)
6704      */
getAccessibilityTraversalBefore()6705     public int getAccessibilityTraversalBefore() {
6706         return mAccessibilityTraversalBeforeId;
6707     }
6708 
6709     /**
6710      * Sets the id of a view after which this one is visited in accessibility traversal.
6711      * A screen-reader must visit the content of the other view before the content of this
6712      * one. For example, if view B is set to be after view A, then a screen-reader
6713      * will traverse the entire content of A before traversing the entire content of B,
6714      * regardles of what traversal strategy it is using.
6715      * <p>
6716      * Views that do not have specified before/after relationships are traversed in order
6717      * determined by the screen-reader.
6718      * </p>
6719      * <p>
6720      * Setting that this view is after a view that is not important for accessibility
6721      * or if this view is not important for accessibility will have no effect as the
6722      * screen-reader is not aware of unimportant views.
6723      * </p>
6724      *
6725      * @param afterId The id of a view this one succedees in accessibility traversal.
6726      *
6727      * @attr ref android.R.styleable#View_accessibilityTraversalAfter
6728      *
6729      * @see #setImportantForAccessibility(int)
6730      */
6731     @RemotableViewMethod
setAccessibilityTraversalAfter(int afterId)6732     public void setAccessibilityTraversalAfter(int afterId) {
6733         if (mAccessibilityTraversalAfterId == afterId) {
6734             return;
6735         }
6736         mAccessibilityTraversalAfterId = afterId;
6737         notifyViewAccessibilityStateChangedIfNeeded(
6738                 AccessibilityEvent.CONTENT_CHANGE_TYPE_UNDEFINED);
6739     }
6740 
6741     /**
6742      * Gets the id of a view after which this one is visited in accessibility traversal.
6743      *
6744      * @return The id of a view this one succeedes in accessibility traversal if
6745      *         specified, otherwise {@link #NO_ID}.
6746      *
6747      * @see #setAccessibilityTraversalAfter(int)
6748      */
getAccessibilityTraversalAfter()6749     public int getAccessibilityTraversalAfter() {
6750         return mAccessibilityTraversalAfterId;
6751     }
6752 
6753     /**
6754      * Gets the id of a view for which this view serves as a label for
6755      * accessibility purposes.
6756      *
6757      * @return The labeled view id.
6758      */
6759     @ViewDebug.ExportedProperty(category = "accessibility")
getLabelFor()6760     public int getLabelFor() {
6761         return mLabelForId;
6762     }
6763 
6764     /**
6765      * Sets the id of a view for which this view serves as a label for
6766      * accessibility purposes.
6767      *
6768      * @param id The labeled view id.
6769      */
6770     @RemotableViewMethod
setLabelFor(@dRes int id)6771     public void setLabelFor(@IdRes int id) {
6772         if (mLabelForId == id) {
6773             return;
6774         }
6775         mLabelForId = id;
6776         if (mLabelForId != View.NO_ID
6777                 && mID == View.NO_ID) {
6778             mID = generateViewId();
6779         }
6780         notifyViewAccessibilityStateChangedIfNeeded(
6781                 AccessibilityEvent.CONTENT_CHANGE_TYPE_UNDEFINED);
6782     }
6783 
6784     /**
6785      * Invoked whenever this view loses focus, either by losing window focus or by losing
6786      * focus within its window. This method can be used to clear any state tied to the
6787      * focus. For instance, if a button is held pressed with the trackball and the window
6788      * loses focus, this method can be used to cancel the press.
6789      *
6790      * Subclasses of View overriding this method should always call super.onFocusLost().
6791      *
6792      * @see #onFocusChanged(boolean, int, android.graphics.Rect)
6793      * @see #onWindowFocusChanged(boolean)
6794      *
6795      * @hide pending API council approval
6796      */
6797     @CallSuper
onFocusLost()6798     protected void onFocusLost() {
6799         resetPressedState();
6800     }
6801 
resetPressedState()6802     private void resetPressedState() {
6803         if ((mViewFlags & ENABLED_MASK) == DISABLED) {
6804             return;
6805         }
6806 
6807         if (isPressed()) {
6808             setPressed(false);
6809 
6810             if (!mHasPerformedLongPress) {
6811                 removeLongPressCallback();
6812             }
6813         }
6814     }
6815 
6816     /**
6817      * Returns true if this view has focus
6818      *
6819      * @return True if this view has focus, false otherwise.
6820      */
6821     @ViewDebug.ExportedProperty(category = "focus")
isFocused()6822     public boolean isFocused() {
6823         return (mPrivateFlags & PFLAG_FOCUSED) != 0;
6824     }
6825 
6826     /**
6827      * Find the view in the hierarchy rooted at this view that currently has
6828      * focus.
6829      *
6830      * @return The view that currently has focus, or null if no focused view can
6831      *         be found.
6832      */
findFocus()6833     public View findFocus() {
6834         return (mPrivateFlags & PFLAG_FOCUSED) != 0 ? this : null;
6835     }
6836 
6837     /**
6838      * Indicates whether this view is one of the set of scrollable containers in
6839      * its window.
6840      *
6841      * @return whether this view is one of the set of scrollable containers in
6842      * its window
6843      *
6844      * @attr ref android.R.styleable#View_isScrollContainer
6845      */
isScrollContainer()6846     public boolean isScrollContainer() {
6847         return (mPrivateFlags & PFLAG_SCROLL_CONTAINER_ADDED) != 0;
6848     }
6849 
6850     /**
6851      * Change whether this view is one of the set of scrollable containers in
6852      * its window.  This will be used to determine whether the window can
6853      * resize or must pan when a soft input area is open -- scrollable
6854      * containers allow the window to use resize mode since the container
6855      * will appropriately shrink.
6856      *
6857      * @attr ref android.R.styleable#View_isScrollContainer
6858      */
setScrollContainer(boolean isScrollContainer)6859     public void setScrollContainer(boolean isScrollContainer) {
6860         if (isScrollContainer) {
6861             if (mAttachInfo != null && (mPrivateFlags&PFLAG_SCROLL_CONTAINER_ADDED) == 0) {
6862                 mAttachInfo.mScrollContainers.add(this);
6863                 mPrivateFlags |= PFLAG_SCROLL_CONTAINER_ADDED;
6864             }
6865             mPrivateFlags |= PFLAG_SCROLL_CONTAINER;
6866         } else {
6867             if ((mPrivateFlags&PFLAG_SCROLL_CONTAINER_ADDED) != 0) {
6868                 mAttachInfo.mScrollContainers.remove(this);
6869             }
6870             mPrivateFlags &= ~(PFLAG_SCROLL_CONTAINER|PFLAG_SCROLL_CONTAINER_ADDED);
6871         }
6872     }
6873 
6874     /**
6875      * Returns the quality of the drawing cache.
6876      *
6877      * @return One of {@link #DRAWING_CACHE_QUALITY_AUTO},
6878      *         {@link #DRAWING_CACHE_QUALITY_LOW}, or {@link #DRAWING_CACHE_QUALITY_HIGH}
6879      *
6880      * @see #setDrawingCacheQuality(int)
6881      * @see #setDrawingCacheEnabled(boolean)
6882      * @see #isDrawingCacheEnabled()
6883      *
6884      * @attr ref android.R.styleable#View_drawingCacheQuality
6885      */
6886     @DrawingCacheQuality
getDrawingCacheQuality()6887     public int getDrawingCacheQuality() {
6888         return mViewFlags & DRAWING_CACHE_QUALITY_MASK;
6889     }
6890 
6891     /**
6892      * Set the drawing cache quality of this view. This value is used only when the
6893      * drawing cache is enabled
6894      *
6895      * @param quality One of {@link #DRAWING_CACHE_QUALITY_AUTO},
6896      *        {@link #DRAWING_CACHE_QUALITY_LOW}, or {@link #DRAWING_CACHE_QUALITY_HIGH}
6897      *
6898      * @see #getDrawingCacheQuality()
6899      * @see #setDrawingCacheEnabled(boolean)
6900      * @see #isDrawingCacheEnabled()
6901      *
6902      * @attr ref android.R.styleable#View_drawingCacheQuality
6903      */
setDrawingCacheQuality(@rawingCacheQuality int quality)6904     public void setDrawingCacheQuality(@DrawingCacheQuality int quality) {
6905         setFlags(quality, DRAWING_CACHE_QUALITY_MASK);
6906     }
6907 
6908     /**
6909      * Returns whether the screen should remain on, corresponding to the current
6910      * value of {@link #KEEP_SCREEN_ON}.
6911      *
6912      * @return Returns true if {@link #KEEP_SCREEN_ON} is set.
6913      *
6914      * @see #setKeepScreenOn(boolean)
6915      *
6916      * @attr ref android.R.styleable#View_keepScreenOn
6917      */
getKeepScreenOn()6918     public boolean getKeepScreenOn() {
6919         return (mViewFlags & KEEP_SCREEN_ON) != 0;
6920     }
6921 
6922     /**
6923      * Controls whether the screen should remain on, modifying the
6924      * value of {@link #KEEP_SCREEN_ON}.
6925      *
6926      * @param keepScreenOn Supply true to set {@link #KEEP_SCREEN_ON}.
6927      *
6928      * @see #getKeepScreenOn()
6929      *
6930      * @attr ref android.R.styleable#View_keepScreenOn
6931      */
setKeepScreenOn(boolean keepScreenOn)6932     public void setKeepScreenOn(boolean keepScreenOn) {
6933         setFlags(keepScreenOn ? KEEP_SCREEN_ON : 0, KEEP_SCREEN_ON);
6934     }
6935 
6936     /**
6937      * Gets the id of the view to use when the next focus is {@link #FOCUS_LEFT}.
6938      * @return The next focus ID, or {@link #NO_ID} if the framework should decide automatically.
6939      *
6940      * @attr ref android.R.styleable#View_nextFocusLeft
6941      */
getNextFocusLeftId()6942     public int getNextFocusLeftId() {
6943         return mNextFocusLeftId;
6944     }
6945 
6946     /**
6947      * Sets the id of the view to use when the next focus is {@link #FOCUS_LEFT}.
6948      * @param nextFocusLeftId The next focus ID, or {@link #NO_ID} if the framework should
6949      * decide automatically.
6950      *
6951      * @attr ref android.R.styleable#View_nextFocusLeft
6952      */
setNextFocusLeftId(int nextFocusLeftId)6953     public void setNextFocusLeftId(int nextFocusLeftId) {
6954         mNextFocusLeftId = nextFocusLeftId;
6955     }
6956 
6957     /**
6958      * Gets the id of the view to use when the next focus is {@link #FOCUS_RIGHT}.
6959      * @return The next focus ID, or {@link #NO_ID} if the framework should decide automatically.
6960      *
6961      * @attr ref android.R.styleable#View_nextFocusRight
6962      */
getNextFocusRightId()6963     public int getNextFocusRightId() {
6964         return mNextFocusRightId;
6965     }
6966 
6967     /**
6968      * Sets the id of the view to use when the next focus is {@link #FOCUS_RIGHT}.
6969      * @param nextFocusRightId The next focus ID, or {@link #NO_ID} if the framework should
6970      * decide automatically.
6971      *
6972      * @attr ref android.R.styleable#View_nextFocusRight
6973      */
setNextFocusRightId(int nextFocusRightId)6974     public void setNextFocusRightId(int nextFocusRightId) {
6975         mNextFocusRightId = nextFocusRightId;
6976     }
6977 
6978     /**
6979      * Gets the id of the view to use when the next focus is {@link #FOCUS_UP}.
6980      * @return The next focus ID, or {@link #NO_ID} if the framework should decide automatically.
6981      *
6982      * @attr ref android.R.styleable#View_nextFocusUp
6983      */
getNextFocusUpId()6984     public int getNextFocusUpId() {
6985         return mNextFocusUpId;
6986     }
6987 
6988     /**
6989      * Sets the id of the view to use when the next focus is {@link #FOCUS_UP}.
6990      * @param nextFocusUpId The next focus ID, or {@link #NO_ID} if the framework should
6991      * decide automatically.
6992      *
6993      * @attr ref android.R.styleable#View_nextFocusUp
6994      */
setNextFocusUpId(int nextFocusUpId)6995     public void setNextFocusUpId(int nextFocusUpId) {
6996         mNextFocusUpId = nextFocusUpId;
6997     }
6998 
6999     /**
7000      * Gets the id of the view to use when the next focus is {@link #FOCUS_DOWN}.
7001      * @return The next focus ID, or {@link #NO_ID} if the framework should decide automatically.
7002      *
7003      * @attr ref android.R.styleable#View_nextFocusDown
7004      */
getNextFocusDownId()7005     public int getNextFocusDownId() {
7006         return mNextFocusDownId;
7007     }
7008 
7009     /**
7010      * Sets the id of the view to use when the next focus is {@link #FOCUS_DOWN}.
7011      * @param nextFocusDownId The next focus ID, or {@link #NO_ID} if the framework should
7012      * decide automatically.
7013      *
7014      * @attr ref android.R.styleable#View_nextFocusDown
7015      */
setNextFocusDownId(int nextFocusDownId)7016     public void setNextFocusDownId(int nextFocusDownId) {
7017         mNextFocusDownId = nextFocusDownId;
7018     }
7019 
7020     /**
7021      * Gets the id of the view to use when the next focus is {@link #FOCUS_FORWARD}.
7022      * @return The next focus ID, or {@link #NO_ID} if the framework should decide automatically.
7023      *
7024      * @attr ref android.R.styleable#View_nextFocusForward
7025      */
getNextFocusForwardId()7026     public int getNextFocusForwardId() {
7027         return mNextFocusForwardId;
7028     }
7029 
7030     /**
7031      * Sets the id of the view to use when the next focus is {@link #FOCUS_FORWARD}.
7032      * @param nextFocusForwardId The next focus ID, or {@link #NO_ID} if the framework should
7033      * decide automatically.
7034      *
7035      * @attr ref android.R.styleable#View_nextFocusForward
7036      */
setNextFocusForwardId(int nextFocusForwardId)7037     public void setNextFocusForwardId(int nextFocusForwardId) {
7038         mNextFocusForwardId = nextFocusForwardId;
7039     }
7040 
7041     /**
7042      * Returns the visibility of this view and all of its ancestors
7043      *
7044      * @return True if this view and all of its ancestors are {@link #VISIBLE}
7045      */
isShown()7046     public boolean isShown() {
7047         View current = this;
7048         //noinspection ConstantConditions
7049         do {
7050             if ((current.mViewFlags & VISIBILITY_MASK) != VISIBLE) {
7051                 return false;
7052             }
7053             ViewParent parent = current.mParent;
7054             if (parent == null) {
7055                 return false; // We are not attached to the view root
7056             }
7057             if (!(parent instanceof View)) {
7058                 return true;
7059             }
7060             current = (View) parent;
7061         } while (current != null);
7062 
7063         return false;
7064     }
7065 
7066     /**
7067      * Called by the view hierarchy when the content insets for a window have
7068      * changed, to allow it to adjust its content to fit within those windows.
7069      * The content insets tell you the space that the status bar, input method,
7070      * and other system windows infringe on the application's window.
7071      *
7072      * <p>You do not normally need to deal with this function, since the default
7073      * window decoration given to applications takes care of applying it to the
7074      * content of the window.  If you use {@link #SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN}
7075      * or {@link #SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION} this will not be the case,
7076      * and your content can be placed under those system elements.  You can then
7077      * use this method within your view hierarchy if you have parts of your UI
7078      * which you would like to ensure are not being covered.
7079      *
7080      * <p>The default implementation of this method simply applies the content
7081      * insets to the view's padding, consuming that content (modifying the
7082      * insets to be 0), and returning true.  This behavior is off by default, but can
7083      * be enabled through {@link #setFitsSystemWindows(boolean)}.
7084      *
7085      * <p>This function's traversal down the hierarchy is depth-first.  The same content
7086      * insets object is propagated down the hierarchy, so any changes made to it will
7087      * be seen by all following views (including potentially ones above in
7088      * the hierarchy since this is a depth-first traversal).  The first view
7089      * that returns true will abort the entire traversal.
7090      *
7091      * <p>The default implementation works well for a situation where it is
7092      * used with a container that covers the entire window, allowing it to
7093      * apply the appropriate insets to its content on all edges.  If you need
7094      * a more complicated layout (such as two different views fitting system
7095      * windows, one on the top of the window, and one on the bottom),
7096      * you can override the method and handle the insets however you would like.
7097      * Note that the insets provided by the framework are always relative to the
7098      * far edges of the window, not accounting for the location of the called view
7099      * within that window.  (In fact when this method is called you do not yet know
7100      * where the layout will place the view, as it is done before layout happens.)
7101      *
7102      * <p>Note: unlike many View methods, there is no dispatch phase to this
7103      * call.  If you are overriding it in a ViewGroup and want to allow the
7104      * call to continue to your children, you must be sure to call the super
7105      * implementation.
7106      *
7107      * <p>Here is a sample layout that makes use of fitting system windows
7108      * to have controls for a video view placed inside of the window decorations
7109      * that it hides and shows.  This can be used with code like the second
7110      * sample (video player) shown in {@link #setSystemUiVisibility(int)}.
7111      *
7112      * {@sample development/samples/ApiDemos/res/layout/video_player.xml complete}
7113      *
7114      * @param insets Current content insets of the window.  Prior to
7115      * {@link android.os.Build.VERSION_CODES#JELLY_BEAN} you must not modify
7116      * the insets or else you and Android will be unhappy.
7117      *
7118      * @return {@code true} if this view applied the insets and it should not
7119      * continue propagating further down the hierarchy, {@code false} otherwise.
7120      * @see #getFitsSystemWindows()
7121      * @see #setFitsSystemWindows(boolean)
7122      * @see #setSystemUiVisibility(int)
7123      *
7124      * @deprecated As of API 20 use {@link #dispatchApplyWindowInsets(WindowInsets)} to apply
7125      * insets to views. Views should override {@link #onApplyWindowInsets(WindowInsets)} or use
7126      * {@link #setOnApplyWindowInsetsListener(android.view.View.OnApplyWindowInsetsListener)}
7127      * to implement handling their own insets.
7128      */
fitSystemWindows(Rect insets)7129     protected boolean fitSystemWindows(Rect insets) {
7130         if ((mPrivateFlags3 & PFLAG3_APPLYING_INSETS) == 0) {
7131             if (insets == null) {
7132                 // Null insets by definition have already been consumed.
7133                 // This call cannot apply insets since there are none to apply,
7134                 // so return false.
7135                 return false;
7136             }
7137             // If we're not in the process of dispatching the newer apply insets call,
7138             // that means we're not in the compatibility path. Dispatch into the newer
7139             // apply insets path and take things from there.
7140             try {
7141                 mPrivateFlags3 |= PFLAG3_FITTING_SYSTEM_WINDOWS;
7142                 return dispatchApplyWindowInsets(new WindowInsets(insets)).isConsumed();
7143             } finally {
7144                 mPrivateFlags3 &= ~PFLAG3_FITTING_SYSTEM_WINDOWS;
7145             }
7146         } else {
7147             // We're being called from the newer apply insets path.
7148             // Perform the standard fallback behavior.
7149             return fitSystemWindowsInt(insets);
7150         }
7151     }
7152 
fitSystemWindowsInt(Rect insets)7153     private boolean fitSystemWindowsInt(Rect insets) {
7154         if ((mViewFlags & FITS_SYSTEM_WINDOWS) == FITS_SYSTEM_WINDOWS) {
7155             mUserPaddingStart = UNDEFINED_PADDING;
7156             mUserPaddingEnd = UNDEFINED_PADDING;
7157             Rect localInsets = sThreadLocal.get();
7158             if (localInsets == null) {
7159                 localInsets = new Rect();
7160                 sThreadLocal.set(localInsets);
7161             }
7162             boolean res = computeFitSystemWindows(insets, localInsets);
7163             mUserPaddingLeftInitial = localInsets.left;
7164             mUserPaddingRightInitial = localInsets.right;
7165             internalSetPadding(localInsets.left, localInsets.top,
7166                     localInsets.right, localInsets.bottom);
7167             return res;
7168         }
7169         return false;
7170     }
7171 
7172     /**
7173      * Called when the view should apply {@link WindowInsets} according to its internal policy.
7174      *
7175      * <p>This method should be overridden by views that wish to apply a policy different from or
7176      * in addition to the default behavior. Clients that wish to force a view subtree
7177      * to apply insets should call {@link #dispatchApplyWindowInsets(WindowInsets)}.</p>
7178      *
7179      * <p>Clients may supply an {@link OnApplyWindowInsetsListener} to a view. If one is set
7180      * it will be called during dispatch instead of this method. The listener may optionally
7181      * call this method from its own implementation if it wishes to apply the view's default
7182      * insets policy in addition to its own.</p>
7183      *
7184      * <p>Implementations of this method should either return the insets parameter unchanged
7185      * or a new {@link WindowInsets} cloned from the supplied insets with any insets consumed
7186      * that this view applied itself. This allows new inset types added in future platform
7187      * versions to pass through existing implementations unchanged without being erroneously
7188      * consumed.</p>
7189      *
7190      * <p>By default if a view's {@link #setFitsSystemWindows(boolean) fitsSystemWindows}
7191      * property is set then the view will consume the system window insets and apply them
7192      * as padding for the view.</p>
7193      *
7194      * @param insets Insets to apply
7195      * @return The supplied insets with any applied insets consumed
7196      */
onApplyWindowInsets(WindowInsets insets)7197     public WindowInsets onApplyWindowInsets(WindowInsets insets) {
7198         if ((mPrivateFlags3 & PFLAG3_FITTING_SYSTEM_WINDOWS) == 0) {
7199             // We weren't called from within a direct call to fitSystemWindows,
7200             // call into it as a fallback in case we're in a class that overrides it
7201             // and has logic to perform.
7202             if (fitSystemWindows(insets.getSystemWindowInsets())) {
7203                 return insets.consumeSystemWindowInsets();
7204             }
7205         } else {
7206             // We were called from within a direct call to fitSystemWindows.
7207             if (fitSystemWindowsInt(insets.getSystemWindowInsets())) {
7208                 return insets.consumeSystemWindowInsets();
7209             }
7210         }
7211         return insets;
7212     }
7213 
7214     /**
7215      * Set an {@link OnApplyWindowInsetsListener} to take over the policy for applying
7216      * window insets to this view. The listener's
7217      * {@link OnApplyWindowInsetsListener#onApplyWindowInsets(View, WindowInsets) onApplyWindowInsets}
7218      * method will be called instead of the view's
7219      * {@link #onApplyWindowInsets(WindowInsets) onApplyWindowInsets} method.
7220      *
7221      * @param listener Listener to set
7222      *
7223      * @see #onApplyWindowInsets(WindowInsets)
7224      */
setOnApplyWindowInsetsListener(OnApplyWindowInsetsListener listener)7225     public void setOnApplyWindowInsetsListener(OnApplyWindowInsetsListener listener) {
7226         getListenerInfo().mOnApplyWindowInsetsListener = listener;
7227     }
7228 
7229     /**
7230      * Request to apply the given window insets to this view or another view in its subtree.
7231      *
7232      * <p>This method should be called by clients wishing to apply insets corresponding to areas
7233      * obscured by window decorations or overlays. This can include the status and navigation bars,
7234      * action bars, input methods and more. New inset categories may be added in the future.
7235      * The method returns the insets provided minus any that were applied by this view or its
7236      * children.</p>
7237      *
7238      * <p>Clients wishing to provide custom behavior should override the
7239      * {@link #onApplyWindowInsets(WindowInsets)} method or alternatively provide a
7240      * {@link OnApplyWindowInsetsListener} via the
7241      * {@link #setOnApplyWindowInsetsListener(View.OnApplyWindowInsetsListener) setOnApplyWindowInsetsListener}
7242      * method.</p>
7243      *
7244      * <p>This method replaces the older {@link #fitSystemWindows(Rect) fitSystemWindows} method.
7245      * </p>
7246      *
7247      * @param insets Insets to apply
7248      * @return The provided insets minus the insets that were consumed
7249      */
dispatchApplyWindowInsets(WindowInsets insets)7250     public WindowInsets dispatchApplyWindowInsets(WindowInsets insets) {
7251         try {
7252             mPrivateFlags3 |= PFLAG3_APPLYING_INSETS;
7253             if (mListenerInfo != null && mListenerInfo.mOnApplyWindowInsetsListener != null) {
7254                 return mListenerInfo.mOnApplyWindowInsetsListener.onApplyWindowInsets(this, insets);
7255             } else {
7256                 return onApplyWindowInsets(insets);
7257             }
7258         } finally {
7259             mPrivateFlags3 &= ~PFLAG3_APPLYING_INSETS;
7260         }
7261     }
7262 
7263     /**
7264      * Provide original WindowInsets that are dispatched to the view hierarchy. The insets are
7265      * only available if the view is attached.
7266      *
7267      * @return WindowInsets from the top of the view hierarchy or null if View is detached
7268      */
getRootWindowInsets()7269     public WindowInsets getRootWindowInsets() {
7270         if (mAttachInfo != null) {
7271             return mAttachInfo.mViewRootImpl.getWindowInsets(false /* forceConstruct */);
7272         }
7273         return null;
7274     }
7275 
7276     /**
7277      * @hide Compute the insets that should be consumed by this view and the ones
7278      * that should propagate to those under it.
7279      */
computeFitSystemWindows(Rect inoutInsets, Rect outLocalInsets)7280     protected boolean computeFitSystemWindows(Rect inoutInsets, Rect outLocalInsets) {
7281         if ((mViewFlags & OPTIONAL_FITS_SYSTEM_WINDOWS) == 0
7282                 || mAttachInfo == null
7283                 || ((mAttachInfo.mSystemUiVisibility & SYSTEM_UI_LAYOUT_FLAGS) == 0
7284                         && !mAttachInfo.mOverscanRequested)) {
7285             outLocalInsets.set(inoutInsets);
7286             inoutInsets.set(0, 0, 0, 0);
7287             return true;
7288         } else {
7289             // The application wants to take care of fitting system window for
7290             // the content...  however we still need to take care of any overscan here.
7291             final Rect overscan = mAttachInfo.mOverscanInsets;
7292             outLocalInsets.set(overscan);
7293             inoutInsets.left -= overscan.left;
7294             inoutInsets.top -= overscan.top;
7295             inoutInsets.right -= overscan.right;
7296             inoutInsets.bottom -= overscan.bottom;
7297             return false;
7298         }
7299     }
7300 
7301     /**
7302      * Compute insets that should be consumed by this view and the ones that should propagate
7303      * to those under it.
7304      *
7305      * @param in Insets currently being processed by this View, likely received as a parameter
7306      *           to {@link #onApplyWindowInsets(WindowInsets)}.
7307      * @param outLocalInsets A Rect that will receive the insets that should be consumed
7308      *                       by this view
7309      * @return Insets that should be passed along to views under this one
7310      */
computeSystemWindowInsets(WindowInsets in, Rect outLocalInsets)7311     public WindowInsets computeSystemWindowInsets(WindowInsets in, Rect outLocalInsets) {
7312         if ((mViewFlags & OPTIONAL_FITS_SYSTEM_WINDOWS) == 0
7313                 || mAttachInfo == null
7314                 || (mAttachInfo.mSystemUiVisibility & SYSTEM_UI_LAYOUT_FLAGS) == 0) {
7315             outLocalInsets.set(in.getSystemWindowInsets());
7316             return in.consumeSystemWindowInsets();
7317         } else {
7318             outLocalInsets.set(0, 0, 0, 0);
7319             return in;
7320         }
7321     }
7322 
7323     /**
7324      * Sets whether or not this view should account for system screen decorations
7325      * such as the status bar and inset its content; that is, controlling whether
7326      * the default implementation of {@link #fitSystemWindows(Rect)} will be
7327      * executed.  See that method for more details.
7328      *
7329      * <p>Note that if you are providing your own implementation of
7330      * {@link #fitSystemWindows(Rect)}, then there is no need to set this
7331      * flag to true -- your implementation will be overriding the default
7332      * implementation that checks this flag.
7333      *
7334      * @param fitSystemWindows If true, then the default implementation of
7335      * {@link #fitSystemWindows(Rect)} will be executed.
7336      *
7337      * @attr ref android.R.styleable#View_fitsSystemWindows
7338      * @see #getFitsSystemWindows()
7339      * @see #fitSystemWindows(Rect)
7340      * @see #setSystemUiVisibility(int)
7341      */
setFitsSystemWindows(boolean fitSystemWindows)7342     public void setFitsSystemWindows(boolean fitSystemWindows) {
7343         setFlags(fitSystemWindows ? FITS_SYSTEM_WINDOWS : 0, FITS_SYSTEM_WINDOWS);
7344     }
7345 
7346     /**
7347      * Check for state of {@link #setFitsSystemWindows(boolean)}. If this method
7348      * returns {@code true}, the default implementation of {@link #fitSystemWindows(Rect)}
7349      * will be executed.
7350      *
7351      * @return {@code true} if the default implementation of
7352      * {@link #fitSystemWindows(Rect)} will be executed.
7353      *
7354      * @attr ref android.R.styleable#View_fitsSystemWindows
7355      * @see #setFitsSystemWindows(boolean)
7356      * @see #fitSystemWindows(Rect)
7357      * @see #setSystemUiVisibility(int)
7358      */
7359     @ViewDebug.ExportedProperty
getFitsSystemWindows()7360     public boolean getFitsSystemWindows() {
7361         return (mViewFlags & FITS_SYSTEM_WINDOWS) == FITS_SYSTEM_WINDOWS;
7362     }
7363 
7364     /** @hide */
fitsSystemWindows()7365     public boolean fitsSystemWindows() {
7366         return getFitsSystemWindows();
7367     }
7368 
7369     /**
7370      * Ask that a new dispatch of {@link #fitSystemWindows(Rect)} be performed.
7371      * @deprecated Use {@link #requestApplyInsets()} for newer platform versions.
7372      */
requestFitSystemWindows()7373     public void requestFitSystemWindows() {
7374         if (mParent != null) {
7375             mParent.requestFitSystemWindows();
7376         }
7377     }
7378 
7379     /**
7380      * Ask that a new dispatch of {@link #onApplyWindowInsets(WindowInsets)} be performed.
7381      */
requestApplyInsets()7382     public void requestApplyInsets() {
7383         requestFitSystemWindows();
7384     }
7385 
7386     /**
7387      * For use by PhoneWindow to make its own system window fitting optional.
7388      * @hide
7389      */
makeOptionalFitsSystemWindows()7390     public void makeOptionalFitsSystemWindows() {
7391         setFlags(OPTIONAL_FITS_SYSTEM_WINDOWS, OPTIONAL_FITS_SYSTEM_WINDOWS);
7392     }
7393 
7394     /**
7395      * Returns the outsets, which areas of the device that aren't a surface, but we would like to
7396      * treat them as such.
7397      * @hide
7398      */
getOutsets(Rect outOutsetRect)7399     public void getOutsets(Rect outOutsetRect) {
7400         if (mAttachInfo != null) {
7401             outOutsetRect.set(mAttachInfo.mOutsets);
7402         } else {
7403             outOutsetRect.setEmpty();
7404         }
7405     }
7406 
7407     /**
7408      * Returns the visibility status for this view.
7409      *
7410      * @return One of {@link #VISIBLE}, {@link #INVISIBLE}, or {@link #GONE}.
7411      * @attr ref android.R.styleable#View_visibility
7412      */
7413     @ViewDebug.ExportedProperty(mapping = {
7414         @ViewDebug.IntToString(from = VISIBLE,   to = "VISIBLE"),
7415         @ViewDebug.IntToString(from = INVISIBLE, to = "INVISIBLE"),
7416         @ViewDebug.IntToString(from = GONE,      to = "GONE")
7417     })
7418     @Visibility
getVisibility()7419     public int getVisibility() {
7420         return mViewFlags & VISIBILITY_MASK;
7421     }
7422 
7423     /**
7424      * Set the enabled state of this view.
7425      *
7426      * @param visibility One of {@link #VISIBLE}, {@link #INVISIBLE}, or {@link #GONE}.
7427      * @attr ref android.R.styleable#View_visibility
7428      */
7429     @RemotableViewMethod
setVisibility(@isibility int visibility)7430     public void setVisibility(@Visibility int visibility) {
7431         setFlags(visibility, VISIBILITY_MASK);
7432     }
7433 
7434     /**
7435      * Returns the enabled status for this view. The interpretation of the
7436      * enabled state varies by subclass.
7437      *
7438      * @return True if this view is enabled, false otherwise.
7439      */
7440     @ViewDebug.ExportedProperty
isEnabled()7441     public boolean isEnabled() {
7442         return (mViewFlags & ENABLED_MASK) == ENABLED;
7443     }
7444 
7445     /**
7446      * Set the enabled state of this view. The interpretation of the enabled
7447      * state varies by subclass.
7448      *
7449      * @param enabled True if this view is enabled, false otherwise.
7450      */
7451     @RemotableViewMethod
setEnabled(boolean enabled)7452     public void setEnabled(boolean enabled) {
7453         if (enabled == isEnabled()) return;
7454 
7455         setFlags(enabled ? ENABLED : DISABLED, ENABLED_MASK);
7456 
7457         /*
7458          * The View most likely has to change its appearance, so refresh
7459          * the drawable state.
7460          */
7461         refreshDrawableState();
7462 
7463         // Invalidate too, since the default behavior for views is to be
7464         // be drawn at 50% alpha rather than to change the drawable.
7465         invalidate(true);
7466 
7467         if (!enabled) {
7468             cancelPendingInputEvents();
7469         }
7470     }
7471 
7472     /**
7473      * Set whether this view can receive the focus.
7474      *
7475      * Setting this to false will also ensure that this view is not focusable
7476      * in touch mode.
7477      *
7478      * @param focusable If true, this view can receive the focus.
7479      *
7480      * @see #setFocusableInTouchMode(boolean)
7481      * @attr ref android.R.styleable#View_focusable
7482      */
setFocusable(boolean focusable)7483     public void setFocusable(boolean focusable) {
7484         if (!focusable) {
7485             setFlags(0, FOCUSABLE_IN_TOUCH_MODE);
7486         }
7487         setFlags(focusable ? FOCUSABLE : NOT_FOCUSABLE, FOCUSABLE_MASK);
7488     }
7489 
7490     /**
7491      * Set whether this view can receive focus while in touch mode.
7492      *
7493      * Setting this to true will also ensure that this view is focusable.
7494      *
7495      * @param focusableInTouchMode If true, this view can receive the focus while
7496      *   in touch mode.
7497      *
7498      * @see #setFocusable(boolean)
7499      * @attr ref android.R.styleable#View_focusableInTouchMode
7500      */
setFocusableInTouchMode(boolean focusableInTouchMode)7501     public void setFocusableInTouchMode(boolean focusableInTouchMode) {
7502         // Focusable in touch mode should always be set before the focusable flag
7503         // otherwise, setting the focusable flag will trigger a focusableViewAvailable()
7504         // which, in touch mode, will not successfully request focus on this view
7505         // because the focusable in touch mode flag is not set
7506         setFlags(focusableInTouchMode ? FOCUSABLE_IN_TOUCH_MODE : 0, FOCUSABLE_IN_TOUCH_MODE);
7507         if (focusableInTouchMode) {
7508             setFlags(FOCUSABLE, FOCUSABLE_MASK);
7509         }
7510     }
7511 
7512     /**
7513      * Set whether this view should have sound effects enabled for events such as
7514      * clicking and touching.
7515      *
7516      * <p>You may wish to disable sound effects for a view if you already play sounds,
7517      * for instance, a dial key that plays dtmf tones.
7518      *
7519      * @param soundEffectsEnabled whether sound effects are enabled for this view.
7520      * @see #isSoundEffectsEnabled()
7521      * @see #playSoundEffect(int)
7522      * @attr ref android.R.styleable#View_soundEffectsEnabled
7523      */
setSoundEffectsEnabled(boolean soundEffectsEnabled)7524     public void setSoundEffectsEnabled(boolean soundEffectsEnabled) {
7525         setFlags(soundEffectsEnabled ? SOUND_EFFECTS_ENABLED: 0, SOUND_EFFECTS_ENABLED);
7526     }
7527 
7528     /**
7529      * @return whether this view should have sound effects enabled for events such as
7530      *     clicking and touching.
7531      *
7532      * @see #setSoundEffectsEnabled(boolean)
7533      * @see #playSoundEffect(int)
7534      * @attr ref android.R.styleable#View_soundEffectsEnabled
7535      */
7536     @ViewDebug.ExportedProperty
isSoundEffectsEnabled()7537     public boolean isSoundEffectsEnabled() {
7538         return SOUND_EFFECTS_ENABLED == (mViewFlags & SOUND_EFFECTS_ENABLED);
7539     }
7540 
7541     /**
7542      * Set whether this view should have haptic feedback for events such as
7543      * long presses.
7544      *
7545      * <p>You may wish to disable haptic feedback if your view already controls
7546      * its own haptic feedback.
7547      *
7548      * @param hapticFeedbackEnabled whether haptic feedback enabled for this view.
7549      * @see #isHapticFeedbackEnabled()
7550      * @see #performHapticFeedback(int)
7551      * @attr ref android.R.styleable#View_hapticFeedbackEnabled
7552      */
setHapticFeedbackEnabled(boolean hapticFeedbackEnabled)7553     public void setHapticFeedbackEnabled(boolean hapticFeedbackEnabled) {
7554         setFlags(hapticFeedbackEnabled ? HAPTIC_FEEDBACK_ENABLED: 0, HAPTIC_FEEDBACK_ENABLED);
7555     }
7556 
7557     /**
7558      * @return whether this view should have haptic feedback enabled for events
7559      * long presses.
7560      *
7561      * @see #setHapticFeedbackEnabled(boolean)
7562      * @see #performHapticFeedback(int)
7563      * @attr ref android.R.styleable#View_hapticFeedbackEnabled
7564      */
7565     @ViewDebug.ExportedProperty
isHapticFeedbackEnabled()7566     public boolean isHapticFeedbackEnabled() {
7567         return HAPTIC_FEEDBACK_ENABLED == (mViewFlags & HAPTIC_FEEDBACK_ENABLED);
7568     }
7569 
7570     /**
7571      * Returns the layout direction for this view.
7572      *
7573      * @return One of {@link #LAYOUT_DIRECTION_LTR},
7574      *   {@link #LAYOUT_DIRECTION_RTL},
7575      *   {@link #LAYOUT_DIRECTION_INHERIT} or
7576      *   {@link #LAYOUT_DIRECTION_LOCALE}.
7577      *
7578      * @attr ref android.R.styleable#View_layoutDirection
7579      *
7580      * @hide
7581      */
7582     @ViewDebug.ExportedProperty(category = "layout", mapping = {
7583         @ViewDebug.IntToString(from = LAYOUT_DIRECTION_LTR,     to = "LTR"),
7584         @ViewDebug.IntToString(from = LAYOUT_DIRECTION_RTL,     to = "RTL"),
7585         @ViewDebug.IntToString(from = LAYOUT_DIRECTION_INHERIT, to = "INHERIT"),
7586         @ViewDebug.IntToString(from = LAYOUT_DIRECTION_LOCALE,  to = "LOCALE")
7587     })
7588     @LayoutDir
getRawLayoutDirection()7589     public int getRawLayoutDirection() {
7590         return (mPrivateFlags2 & PFLAG2_LAYOUT_DIRECTION_MASK) >> PFLAG2_LAYOUT_DIRECTION_MASK_SHIFT;
7591     }
7592 
7593     /**
7594      * Set the layout direction for this view. This will propagate a reset of layout direction
7595      * resolution to the view's children and resolve layout direction for this view.
7596      *
7597      * @param layoutDirection the layout direction to set. Should be one of:
7598      *
7599      * {@link #LAYOUT_DIRECTION_LTR},
7600      * {@link #LAYOUT_DIRECTION_RTL},
7601      * {@link #LAYOUT_DIRECTION_INHERIT},
7602      * {@link #LAYOUT_DIRECTION_LOCALE}.
7603      *
7604      * Resolution will be done if the value is set to LAYOUT_DIRECTION_INHERIT. The resolution
7605      * proceeds up the parent chain of the view to get the value. If there is no parent, then it
7606      * will return the default {@link #LAYOUT_DIRECTION_LTR}.
7607      *
7608      * @attr ref android.R.styleable#View_layoutDirection
7609      */
7610     @RemotableViewMethod
setLayoutDirection(@ayoutDir int layoutDirection)7611     public void setLayoutDirection(@LayoutDir int layoutDirection) {
7612         if (getRawLayoutDirection() != layoutDirection) {
7613             // Reset the current layout direction and the resolved one
7614             mPrivateFlags2 &= ~PFLAG2_LAYOUT_DIRECTION_MASK;
7615             resetRtlProperties();
7616             // Set the new layout direction (filtered)
7617             mPrivateFlags2 |=
7618                     ((layoutDirection << PFLAG2_LAYOUT_DIRECTION_MASK_SHIFT) & PFLAG2_LAYOUT_DIRECTION_MASK);
7619             // We need to resolve all RTL properties as they all depend on layout direction
7620             resolveRtlPropertiesIfNeeded();
7621             requestLayout();
7622             invalidate(true);
7623         }
7624     }
7625 
7626     /**
7627      * Returns the resolved layout direction for this view.
7628      *
7629      * @return {@link #LAYOUT_DIRECTION_RTL} if the layout direction is RTL or returns
7630      * {@link #LAYOUT_DIRECTION_LTR} if the layout direction is not RTL.
7631      *
7632      * For compatibility, this will return {@link #LAYOUT_DIRECTION_LTR} if API version
7633      * is lower than {@link android.os.Build.VERSION_CODES#JELLY_BEAN_MR1}.
7634      *
7635      * @attr ref android.R.styleable#View_layoutDirection
7636      */
7637     @ViewDebug.ExportedProperty(category = "layout", mapping = {
7638         @ViewDebug.IntToString(from = LAYOUT_DIRECTION_LTR, to = "RESOLVED_DIRECTION_LTR"),
7639         @ViewDebug.IntToString(from = LAYOUT_DIRECTION_RTL, to = "RESOLVED_DIRECTION_RTL")
7640     })
7641     @ResolvedLayoutDir
getLayoutDirection()7642     public int getLayoutDirection() {
7643         final int targetSdkVersion = getContext().getApplicationInfo().targetSdkVersion;
7644         if (targetSdkVersion < JELLY_BEAN_MR1) {
7645             mPrivateFlags2 |= PFLAG2_LAYOUT_DIRECTION_RESOLVED;
7646             return LAYOUT_DIRECTION_RESOLVED_DEFAULT;
7647         }
7648         return ((mPrivateFlags2 & PFLAG2_LAYOUT_DIRECTION_RESOLVED_RTL) ==
7649                 PFLAG2_LAYOUT_DIRECTION_RESOLVED_RTL) ? LAYOUT_DIRECTION_RTL : LAYOUT_DIRECTION_LTR;
7650     }
7651 
7652     /**
7653      * Indicates whether or not this view's layout is right-to-left. This is resolved from
7654      * layout attribute and/or the inherited value from the parent
7655      *
7656      * @return true if the layout is right-to-left.
7657      *
7658      * @hide
7659      */
7660     @ViewDebug.ExportedProperty(category = "layout")
isLayoutRtl()7661     public boolean isLayoutRtl() {
7662         return (getLayoutDirection() == LAYOUT_DIRECTION_RTL);
7663     }
7664 
7665     /**
7666      * Indicates whether the view is currently tracking transient state that the
7667      * app should not need to concern itself with saving and restoring, but that
7668      * the framework should take special note to preserve when possible.
7669      *
7670      * <p>A view with transient state cannot be trivially rebound from an external
7671      * data source, such as an adapter binding item views in a list. This may be
7672      * because the view is performing an animation, tracking user selection
7673      * of content, or similar.</p>
7674      *
7675      * @return true if the view has transient state
7676      */
7677     @ViewDebug.ExportedProperty(category = "layout")
hasTransientState()7678     public boolean hasTransientState() {
7679         return (mPrivateFlags2 & PFLAG2_HAS_TRANSIENT_STATE) == PFLAG2_HAS_TRANSIENT_STATE;
7680     }
7681 
7682     /**
7683      * Set whether this view is currently tracking transient state that the
7684      * framework should attempt to preserve when possible. This flag is reference counted,
7685      * so every call to setHasTransientState(true) should be paired with a later call
7686      * to setHasTransientState(false).
7687      *
7688      * <p>A view with transient state cannot be trivially rebound from an external
7689      * data source, such as an adapter binding item views in a list. This may be
7690      * because the view is performing an animation, tracking user selection
7691      * of content, or similar.</p>
7692      *
7693      * @param hasTransientState true if this view has transient state
7694      */
setHasTransientState(boolean hasTransientState)7695     public void setHasTransientState(boolean hasTransientState) {
7696         mTransientStateCount = hasTransientState ? mTransientStateCount + 1 :
7697                 mTransientStateCount - 1;
7698         if (mTransientStateCount < 0) {
7699             mTransientStateCount = 0;
7700             Log.e(VIEW_LOG_TAG, "hasTransientState decremented below 0: " +
7701                     "unmatched pair of setHasTransientState calls");
7702         } else if ((hasTransientState && mTransientStateCount == 1) ||
7703                 (!hasTransientState && mTransientStateCount == 0)) {
7704             // update flag if we've just incremented up from 0 or decremented down to 0
7705             mPrivateFlags2 = (mPrivateFlags2 & ~PFLAG2_HAS_TRANSIENT_STATE) |
7706                     (hasTransientState ? PFLAG2_HAS_TRANSIENT_STATE : 0);
7707             if (mParent != null) {
7708                 try {
7709                     mParent.childHasTransientStateChanged(this, hasTransientState);
7710                 } catch (AbstractMethodError e) {
7711                     Log.e(VIEW_LOG_TAG, mParent.getClass().getSimpleName() +
7712                             " does not fully implement ViewParent", e);
7713                 }
7714             }
7715         }
7716     }
7717 
7718     /**
7719      * Returns true if this view is currently attached to a window.
7720      */
isAttachedToWindow()7721     public boolean isAttachedToWindow() {
7722         return mAttachInfo != null;
7723     }
7724 
7725     /**
7726      * Returns true if this view has been through at least one layout since it
7727      * was last attached to or detached from a window.
7728      */
isLaidOut()7729     public boolean isLaidOut() {
7730         return (mPrivateFlags3 & PFLAG3_IS_LAID_OUT) == PFLAG3_IS_LAID_OUT;
7731     }
7732 
7733     /**
7734      * If this view doesn't do any drawing on its own, set this flag to
7735      * allow further optimizations. By default, this flag is not set on
7736      * View, but could be set on some View subclasses such as ViewGroup.
7737      *
7738      * Typically, if you override {@link #onDraw(android.graphics.Canvas)}
7739      * you should clear this flag.
7740      *
7741      * @param willNotDraw whether or not this View draw on its own
7742      */
setWillNotDraw(boolean willNotDraw)7743     public void setWillNotDraw(boolean willNotDraw) {
7744         setFlags(willNotDraw ? WILL_NOT_DRAW : 0, DRAW_MASK);
7745     }
7746 
7747     /**
7748      * Returns whether or not this View draws on its own.
7749      *
7750      * @return true if this view has nothing to draw, false otherwise
7751      */
7752     @ViewDebug.ExportedProperty(category = "drawing")
willNotDraw()7753     public boolean willNotDraw() {
7754         return (mViewFlags & DRAW_MASK) == WILL_NOT_DRAW;
7755     }
7756 
7757     /**
7758      * When a View's drawing cache is enabled, drawing is redirected to an
7759      * offscreen bitmap. Some views, like an ImageView, must be able to
7760      * bypass this mechanism if they already draw a single bitmap, to avoid
7761      * unnecessary usage of the memory.
7762      *
7763      * @param willNotCacheDrawing true if this view does not cache its
7764      *        drawing, false otherwise
7765      */
setWillNotCacheDrawing(boolean willNotCacheDrawing)7766     public void setWillNotCacheDrawing(boolean willNotCacheDrawing) {
7767         setFlags(willNotCacheDrawing ? WILL_NOT_CACHE_DRAWING : 0, WILL_NOT_CACHE_DRAWING);
7768     }
7769 
7770     /**
7771      * Returns whether or not this View can cache its drawing or not.
7772      *
7773      * @return true if this view does not cache its drawing, false otherwise
7774      */
7775     @ViewDebug.ExportedProperty(category = "drawing")
willNotCacheDrawing()7776     public boolean willNotCacheDrawing() {
7777         return (mViewFlags & WILL_NOT_CACHE_DRAWING) == WILL_NOT_CACHE_DRAWING;
7778     }
7779 
7780     /**
7781      * Indicates whether this view reacts to click events or not.
7782      *
7783      * @return true if the view is clickable, false otherwise
7784      *
7785      * @see #setClickable(boolean)
7786      * @attr ref android.R.styleable#View_clickable
7787      */
7788     @ViewDebug.ExportedProperty
isClickable()7789     public boolean isClickable() {
7790         return (mViewFlags & CLICKABLE) == CLICKABLE;
7791     }
7792 
7793     /**
7794      * Enables or disables click events for this view. When a view
7795      * is clickable it will change its state to "pressed" on every click.
7796      * Subclasses should set the view clickable to visually react to
7797      * user's clicks.
7798      *
7799      * @param clickable true to make the view clickable, false otherwise
7800      *
7801      * @see #isClickable()
7802      * @attr ref android.R.styleable#View_clickable
7803      */
setClickable(boolean clickable)7804     public void setClickable(boolean clickable) {
7805         setFlags(clickable ? CLICKABLE : 0, CLICKABLE);
7806     }
7807 
7808     /**
7809      * Indicates whether this view reacts to long click events or not.
7810      *
7811      * @return true if the view is long clickable, false otherwise
7812      *
7813      * @see #setLongClickable(boolean)
7814      * @attr ref android.R.styleable#View_longClickable
7815      */
isLongClickable()7816     public boolean isLongClickable() {
7817         return (mViewFlags & LONG_CLICKABLE) == LONG_CLICKABLE;
7818     }
7819 
7820     /**
7821      * Enables or disables long click events for this view. When a view is long
7822      * clickable it reacts to the user holding down the button for a longer
7823      * duration than a tap. This event can either launch the listener or a
7824      * context menu.
7825      *
7826      * @param longClickable true to make the view long clickable, false otherwise
7827      * @see #isLongClickable()
7828      * @attr ref android.R.styleable#View_longClickable
7829      */
setLongClickable(boolean longClickable)7830     public void setLongClickable(boolean longClickable) {
7831         setFlags(longClickable ? LONG_CLICKABLE : 0, LONG_CLICKABLE);
7832     }
7833 
7834     /**
7835      * Indicates whether this view reacts to context clicks or not.
7836      *
7837      * @return true if the view is context clickable, false otherwise
7838      * @see #setContextClickable(boolean)
7839      * @attr ref android.R.styleable#View_contextClickable
7840      */
isContextClickable()7841     public boolean isContextClickable() {
7842         return (mViewFlags & CONTEXT_CLICKABLE) == CONTEXT_CLICKABLE;
7843     }
7844 
7845     /**
7846      * Enables or disables context clicking for this view. This event can launch the listener.
7847      *
7848      * @param contextClickable true to make the view react to a context click, false otherwise
7849      * @see #isContextClickable()
7850      * @attr ref android.R.styleable#View_contextClickable
7851      */
setContextClickable(boolean contextClickable)7852     public void setContextClickable(boolean contextClickable) {
7853         setFlags(contextClickable ? CONTEXT_CLICKABLE : 0, CONTEXT_CLICKABLE);
7854     }
7855 
7856     /**
7857      * Sets the pressed state for this view and provides a touch coordinate for
7858      * animation hinting.
7859      *
7860      * @param pressed Pass true to set the View's internal state to "pressed",
7861      *            or false to reverts the View's internal state from a
7862      *            previously set "pressed" state.
7863      * @param x The x coordinate of the touch that caused the press
7864      * @param y The y coordinate of the touch that caused the press
7865      */
setPressed(boolean pressed, float x, float y)7866     private void setPressed(boolean pressed, float x, float y) {
7867         if (pressed) {
7868             drawableHotspotChanged(x, y);
7869         }
7870 
7871         setPressed(pressed);
7872     }
7873 
7874     /**
7875      * Sets the pressed state for this view.
7876      *
7877      * @see #isClickable()
7878      * @see #setClickable(boolean)
7879      *
7880      * @param pressed Pass true to set the View's internal state to "pressed", or false to reverts
7881      *        the View's internal state from a previously set "pressed" state.
7882      */
setPressed(boolean pressed)7883     public void setPressed(boolean pressed) {
7884         final boolean needsRefresh = pressed != ((mPrivateFlags & PFLAG_PRESSED) == PFLAG_PRESSED);
7885 
7886         if (pressed) {
7887             mPrivateFlags |= PFLAG_PRESSED;
7888         } else {
7889             mPrivateFlags &= ~PFLAG_PRESSED;
7890         }
7891 
7892         if (needsRefresh) {
7893             refreshDrawableState();
7894         }
7895         dispatchSetPressed(pressed);
7896     }
7897 
7898     /**
7899      * Dispatch setPressed to all of this View's children.
7900      *
7901      * @see #setPressed(boolean)
7902      *
7903      * @param pressed The new pressed state
7904      */
dispatchSetPressed(boolean pressed)7905     protected void dispatchSetPressed(boolean pressed) {
7906     }
7907 
7908     /**
7909      * Indicates whether the view is currently in pressed state. Unless
7910      * {@link #setPressed(boolean)} is explicitly called, only clickable views can enter
7911      * the pressed state.
7912      *
7913      * @see #setPressed(boolean)
7914      * @see #isClickable()
7915      * @see #setClickable(boolean)
7916      *
7917      * @return true if the view is currently pressed, false otherwise
7918      */
7919     @ViewDebug.ExportedProperty
isPressed()7920     public boolean isPressed() {
7921         return (mPrivateFlags & PFLAG_PRESSED) == PFLAG_PRESSED;
7922     }
7923 
7924     /**
7925      * @hide
7926      * Indicates whether this view will participate in data collection through
7927      * {@link ViewStructure}.  If true, it will not provide any data
7928      * for itself or its children.  If false, the normal data collection will be allowed.
7929      *
7930      * @return Returns false if assist data collection is not blocked, else true.
7931      *
7932      * @see #setAssistBlocked(boolean)
7933      * @attr ref android.R.styleable#View_assistBlocked
7934      */
isAssistBlocked()7935     public boolean isAssistBlocked() {
7936         return (mPrivateFlags3 & PFLAG3_ASSIST_BLOCKED) != 0;
7937     }
7938 
7939     /**
7940      * @hide
7941      * Controls whether assist data collection from this view and its children is enabled
7942      * (that is, whether {@link #onProvideStructure} and
7943      * {@link #onProvideVirtualStructure} will be called).  The default value is false,
7944      * allowing normal assist collection.  Setting this to false will disable assist collection.
7945      *
7946      * @param enabled Set to true to <em>disable</em> assist data collection, or false
7947      * (the default) to allow it.
7948      *
7949      * @see #isAssistBlocked()
7950      * @see #onProvideStructure
7951      * @see #onProvideVirtualStructure
7952      * @attr ref android.R.styleable#View_assistBlocked
7953      */
setAssistBlocked(boolean enabled)7954     public void setAssistBlocked(boolean enabled) {
7955         if (enabled) {
7956             mPrivateFlags3 |= PFLAG3_ASSIST_BLOCKED;
7957         } else {
7958             mPrivateFlags3 &= ~PFLAG3_ASSIST_BLOCKED;
7959         }
7960     }
7961 
7962     /**
7963      * Indicates whether this view will save its state (that is,
7964      * whether its {@link #onSaveInstanceState} method will be called).
7965      *
7966      * @return Returns true if the view state saving is enabled, else false.
7967      *
7968      * @see #setSaveEnabled(boolean)
7969      * @attr ref android.R.styleable#View_saveEnabled
7970      */
isSaveEnabled()7971     public boolean isSaveEnabled() {
7972         return (mViewFlags & SAVE_DISABLED_MASK) != SAVE_DISABLED;
7973     }
7974 
7975     /**
7976      * Controls whether the saving of this view's state is
7977      * enabled (that is, whether its {@link #onSaveInstanceState} method
7978      * will be called).  Note that even if freezing is enabled, the
7979      * view still must have an id assigned to it (via {@link #setId(int)})
7980      * for its state to be saved.  This flag can only disable the
7981      * saving of this view; any child views may still have their state saved.
7982      *
7983      * @param enabled Set to false to <em>disable</em> state saving, or true
7984      * (the default) to allow it.
7985      *
7986      * @see #isSaveEnabled()
7987      * @see #setId(int)
7988      * @see #onSaveInstanceState()
7989      * @attr ref android.R.styleable#View_saveEnabled
7990      */
setSaveEnabled(boolean enabled)7991     public void setSaveEnabled(boolean enabled) {
7992         setFlags(enabled ? 0 : SAVE_DISABLED, SAVE_DISABLED_MASK);
7993     }
7994 
7995     /**
7996      * Gets whether the framework should discard touches when the view's
7997      * window is obscured by another visible window.
7998      * Refer to the {@link View} security documentation for more details.
7999      *
8000      * @return True if touch filtering is enabled.
8001      *
8002      * @see #setFilterTouchesWhenObscured(boolean)
8003      * @attr ref android.R.styleable#View_filterTouchesWhenObscured
8004      */
8005     @ViewDebug.ExportedProperty
getFilterTouchesWhenObscured()8006     public boolean getFilterTouchesWhenObscured() {
8007         return (mViewFlags & FILTER_TOUCHES_WHEN_OBSCURED) != 0;
8008     }
8009 
8010     /**
8011      * Sets whether the framework should discard touches when the view's
8012      * window is obscured by another visible window.
8013      * Refer to the {@link View} security documentation for more details.
8014      *
8015      * @param enabled True if touch filtering should be enabled.
8016      *
8017      * @see #getFilterTouchesWhenObscured
8018      * @attr ref android.R.styleable#View_filterTouchesWhenObscured
8019      */
setFilterTouchesWhenObscured(boolean enabled)8020     public void setFilterTouchesWhenObscured(boolean enabled) {
8021         setFlags(enabled ? FILTER_TOUCHES_WHEN_OBSCURED : 0,
8022                 FILTER_TOUCHES_WHEN_OBSCURED);
8023     }
8024 
8025     /**
8026      * Indicates whether the entire hierarchy under this view will save its
8027      * state when a state saving traversal occurs from its parent.  The default
8028      * is true; if false, these views will not be saved unless
8029      * {@link #saveHierarchyState(SparseArray)} is called directly on this view.
8030      *
8031      * @return Returns true if the view state saving from parent is enabled, else false.
8032      *
8033      * @see #setSaveFromParentEnabled(boolean)
8034      */
isSaveFromParentEnabled()8035     public boolean isSaveFromParentEnabled() {
8036         return (mViewFlags & PARENT_SAVE_DISABLED_MASK) != PARENT_SAVE_DISABLED;
8037     }
8038 
8039     /**
8040      * Controls whether the entire hierarchy under this view will save its
8041      * state when a state saving traversal occurs from its parent.  The default
8042      * is true; if false, these views will not be saved unless
8043      * {@link #saveHierarchyState(SparseArray)} is called directly on this view.
8044      *
8045      * @param enabled Set to false to <em>disable</em> state saving, or true
8046      * (the default) to allow it.
8047      *
8048      * @see #isSaveFromParentEnabled()
8049      * @see #setId(int)
8050      * @see #onSaveInstanceState()
8051      */
setSaveFromParentEnabled(boolean enabled)8052     public void setSaveFromParentEnabled(boolean enabled) {
8053         setFlags(enabled ? 0 : PARENT_SAVE_DISABLED, PARENT_SAVE_DISABLED_MASK);
8054     }
8055 
8056 
8057     /**
8058      * Returns whether this View is able to take focus.
8059      *
8060      * @return True if this view can take focus, or false otherwise.
8061      * @attr ref android.R.styleable#View_focusable
8062      */
8063     @ViewDebug.ExportedProperty(category = "focus")
isFocusable()8064     public final boolean isFocusable() {
8065         return FOCUSABLE == (mViewFlags & FOCUSABLE_MASK);
8066     }
8067 
8068     /**
8069      * When a view is focusable, it may not want to take focus when in touch mode.
8070      * For example, a button would like focus when the user is navigating via a D-pad
8071      * so that the user can click on it, but once the user starts touching the screen,
8072      * the button shouldn't take focus
8073      * @return Whether the view is focusable in touch mode.
8074      * @attr ref android.R.styleable#View_focusableInTouchMode
8075      */
8076     @ViewDebug.ExportedProperty
isFocusableInTouchMode()8077     public final boolean isFocusableInTouchMode() {
8078         return FOCUSABLE_IN_TOUCH_MODE == (mViewFlags & FOCUSABLE_IN_TOUCH_MODE);
8079     }
8080 
8081     /**
8082      * Find the nearest view in the specified direction that can take focus.
8083      * This does not actually give focus to that view.
8084      *
8085      * @param direction One of FOCUS_UP, FOCUS_DOWN, FOCUS_LEFT, and FOCUS_RIGHT
8086      *
8087      * @return The nearest focusable in the specified direction, or null if none
8088      *         can be found.
8089      */
focusSearch(@ocusRealDirection int direction)8090     public View focusSearch(@FocusRealDirection int direction) {
8091         if (mParent != null) {
8092             return mParent.focusSearch(this, direction);
8093         } else {
8094             return null;
8095         }
8096     }
8097 
8098     /**
8099      * This method is the last chance for the focused view and its ancestors to
8100      * respond to an arrow key. This is called when the focused view did not
8101      * consume the key internally, nor could the view system find a new view in
8102      * the requested direction to give focus to.
8103      *
8104      * @param focused The currently focused view.
8105      * @param direction The direction focus wants to move. One of FOCUS_UP,
8106      *        FOCUS_DOWN, FOCUS_LEFT, and FOCUS_RIGHT.
8107      * @return True if the this view consumed this unhandled move.
8108      */
dispatchUnhandledMove(View focused, @FocusRealDirection int direction)8109     public boolean dispatchUnhandledMove(View focused, @FocusRealDirection int direction) {
8110         return false;
8111     }
8112 
8113     /**
8114      * If a user manually specified the next view id for a particular direction,
8115      * use the root to look up the view.
8116      * @param root The root view of the hierarchy containing this view.
8117      * @param direction One of FOCUS_UP, FOCUS_DOWN, FOCUS_LEFT, FOCUS_RIGHT, FOCUS_FORWARD,
8118      * or FOCUS_BACKWARD.
8119      * @return The user specified next view, or null if there is none.
8120      */
findUserSetNextFocus(View root, @FocusDirection int direction)8121     View findUserSetNextFocus(View root, @FocusDirection int direction) {
8122         switch (direction) {
8123             case FOCUS_LEFT:
8124                 if (mNextFocusLeftId == View.NO_ID) return null;
8125                 return findViewInsideOutShouldExist(root, mNextFocusLeftId);
8126             case FOCUS_RIGHT:
8127                 if (mNextFocusRightId == View.NO_ID) return null;
8128                 return findViewInsideOutShouldExist(root, mNextFocusRightId);
8129             case FOCUS_UP:
8130                 if (mNextFocusUpId == View.NO_ID) return null;
8131                 return findViewInsideOutShouldExist(root, mNextFocusUpId);
8132             case FOCUS_DOWN:
8133                 if (mNextFocusDownId == View.NO_ID) return null;
8134                 return findViewInsideOutShouldExist(root, mNextFocusDownId);
8135             case FOCUS_FORWARD:
8136                 if (mNextFocusForwardId == View.NO_ID) return null;
8137                 return findViewInsideOutShouldExist(root, mNextFocusForwardId);
8138             case FOCUS_BACKWARD: {
8139                 if (mID == View.NO_ID) return null;
8140                 final int id = mID;
8141                 return root.findViewByPredicateInsideOut(this, new Predicate<View>() {
8142                     @Override
8143                     public boolean apply(View t) {
8144                         return t.mNextFocusForwardId == id;
8145                     }
8146                 });
8147             }
8148         }
8149         return null;
8150     }
8151 
8152     private View findViewInsideOutShouldExist(View root, int id) {
8153         if (mMatchIdPredicate == null) {
8154             mMatchIdPredicate = new MatchIdPredicate();
8155         }
8156         mMatchIdPredicate.mId = id;
8157         View result = root.findViewByPredicateInsideOut(this, mMatchIdPredicate);
8158         if (result == null) {
8159             Log.w(VIEW_LOG_TAG, "couldn't find view with id " + id);
8160         }
8161         return result;
8162     }
8163 
8164     /**
8165      * Find and return all focusable views that are descendants of this view,
8166      * possibly including this view if it is focusable itself.
8167      *
8168      * @param direction The direction of the focus
8169      * @return A list of focusable views
8170      */
8171     public ArrayList<View> getFocusables(@FocusDirection int direction) {
8172         ArrayList<View> result = new ArrayList<View>(24);
8173         addFocusables(result, direction);
8174         return result;
8175     }
8176 
8177     /**
8178      * Add any focusable views that are descendants of this view (possibly
8179      * including this view if it is focusable itself) to views.  If we are in touch mode,
8180      * only add views that are also focusable in touch mode.
8181      *
8182      * @param views Focusable views found so far
8183      * @param direction The direction of the focus
8184      */
8185     public void addFocusables(ArrayList<View> views, @FocusDirection int direction) {
8186         addFocusables(views, direction, FOCUSABLES_TOUCH_MODE);
8187     }
8188 
8189     /**
8190      * Adds any focusable views that are descendants of this view (possibly
8191      * including this view if it is focusable itself) to views. This method
8192      * adds all focusable views regardless if we are in touch mode or
8193      * only views focusable in touch mode if we are in touch mode or
8194      * only views that can take accessibility focus if accessibility is enabled
8195      * depending on the focusable mode parameter.
8196      *
8197      * @param views Focusable views found so far or null if all we are interested is
8198      *        the number of focusables.
8199      * @param direction The direction of the focus.
8200      * @param focusableMode The type of focusables to be added.
8201      *
8202      * @see #FOCUSABLES_ALL
8203      * @see #FOCUSABLES_TOUCH_MODE
8204      */
8205     public void addFocusables(ArrayList<View> views, @FocusDirection int direction,
8206             @FocusableMode int focusableMode) {
8207         if (views == null) {
8208             return;
8209         }
8210         if (!isFocusable()) {
8211             return;
8212         }
8213         if ((focusableMode & FOCUSABLES_TOUCH_MODE) == FOCUSABLES_TOUCH_MODE
8214                 && isInTouchMode() && !isFocusableInTouchMode()) {
8215             return;
8216         }
8217         views.add(this);
8218     }
8219 
8220     /**
8221      * Finds the Views that contain given text. The containment is case insensitive.
8222      * The search is performed by either the text that the View renders or the content
8223      * description that describes the view for accessibility purposes and the view does
8224      * not render or both. Clients can specify how the search is to be performed via
8225      * passing the {@link #FIND_VIEWS_WITH_TEXT} and
8226      * {@link #FIND_VIEWS_WITH_CONTENT_DESCRIPTION} flags.
8227      *
8228      * @param outViews The output list of matching Views.
8229      * @param searched The text to match against.
8230      *
8231      * @see #FIND_VIEWS_WITH_TEXT
8232      * @see #FIND_VIEWS_WITH_CONTENT_DESCRIPTION
8233      * @see #setContentDescription(CharSequence)
8234      */
8235     public void findViewsWithText(ArrayList<View> outViews, CharSequence searched,
8236             @FindViewFlags int flags) {
8237         if (getAccessibilityNodeProvider() != null) {
8238             if ((flags & FIND_VIEWS_WITH_ACCESSIBILITY_NODE_PROVIDERS) != 0) {
8239                 outViews.add(this);
8240             }
8241         } else if ((flags & FIND_VIEWS_WITH_CONTENT_DESCRIPTION) != 0
8242                 && (searched != null && searched.length() > 0)
8243                 && (mContentDescription != null && mContentDescription.length() > 0)) {
8244             String searchedLowerCase = searched.toString().toLowerCase();
8245             String contentDescriptionLowerCase = mContentDescription.toString().toLowerCase();
8246             if (contentDescriptionLowerCase.contains(searchedLowerCase)) {
8247                 outViews.add(this);
8248             }
8249         }
8250     }
8251 
8252     /**
8253      * Find and return all touchable views that are descendants of this view,
8254      * possibly including this view if it is touchable itself.
8255      *
8256      * @return A list of touchable views
8257      */
8258     public ArrayList<View> getTouchables() {
8259         ArrayList<View> result = new ArrayList<View>();
8260         addTouchables(result);
8261         return result;
8262     }
8263 
8264     /**
8265      * Add any touchable views that are descendants of this view (possibly
8266      * including this view if it is touchable itself) to views.
8267      *
8268      * @param views Touchable views found so far
8269      */
8270     public void addTouchables(ArrayList<View> views) {
8271         final int viewFlags = mViewFlags;
8272 
8273         if (((viewFlags & CLICKABLE) == CLICKABLE || (viewFlags & LONG_CLICKABLE) == LONG_CLICKABLE
8274                 || (viewFlags & CONTEXT_CLICKABLE) == CONTEXT_CLICKABLE)
8275                 && (viewFlags & ENABLED_MASK) == ENABLED) {
8276             views.add(this);
8277         }
8278     }
8279 
8280     /**
8281      * Returns whether this View is accessibility focused.
8282      *
8283      * @return True if this View is accessibility focused.
8284      */
8285     public boolean isAccessibilityFocused() {
8286         return (mPrivateFlags2 & PFLAG2_ACCESSIBILITY_FOCUSED) != 0;
8287     }
8288 
8289     /**
8290      * Call this to try to give accessibility focus to this view.
8291      *
8292      * A view will not actually take focus if {@link AccessibilityManager#isEnabled()}
8293      * returns false or the view is no visible or the view already has accessibility
8294      * focus.
8295      *
8296      * See also {@link #focusSearch(int)}, which is what you call to say that you
8297      * have focus, and you want your parent to look for the next one.
8298      *
8299      * @return Whether this view actually took accessibility focus.
8300      *
8301      * @hide
8302      */
8303     public boolean requestAccessibilityFocus() {
8304         AccessibilityManager manager = AccessibilityManager.getInstance(mContext);
8305         if (!manager.isEnabled() || !manager.isTouchExplorationEnabled()) {
8306             return false;
8307         }
8308         if ((mViewFlags & VISIBILITY_MASK) != VISIBLE) {
8309             return false;
8310         }
8311         if ((mPrivateFlags2 & PFLAG2_ACCESSIBILITY_FOCUSED) == 0) {
8312             mPrivateFlags2 |= PFLAG2_ACCESSIBILITY_FOCUSED;
8313             ViewRootImpl viewRootImpl = getViewRootImpl();
8314             if (viewRootImpl != null) {
8315                 viewRootImpl.setAccessibilityFocus(this, null);
8316             }
8317             invalidate();
8318             sendAccessibilityEvent(AccessibilityEvent.TYPE_VIEW_ACCESSIBILITY_FOCUSED);
8319             return true;
8320         }
8321         return false;
8322     }
8323 
8324     /**
8325      * Call this to try to clear accessibility focus of this view.
8326      *
8327      * See also {@link #focusSearch(int)}, which is what you call to say that you
8328      * have focus, and you want your parent to look for the next one.
8329      *
8330      * @hide
8331      */
8332     public void clearAccessibilityFocus() {
8333         clearAccessibilityFocusNoCallbacks();
8334         // Clear the global reference of accessibility focus if this
8335         // view or any of its descendants had accessibility focus.
8336         ViewRootImpl viewRootImpl = getViewRootImpl();
8337         if (viewRootImpl != null) {
8338             View focusHost = viewRootImpl.getAccessibilityFocusedHost();
8339             if (focusHost != null && ViewRootImpl.isViewDescendantOf(focusHost, this)) {
8340                 viewRootImpl.setAccessibilityFocus(null, null);
8341             }
8342         }
8343     }
8344 
8345     private void sendAccessibilityHoverEvent(int eventType) {
8346         // Since we are not delivering to a client accessibility events from not
8347         // important views (unless the clinet request that) we need to fire the
8348         // event from the deepest view exposed to the client. As a consequence if
8349         // the user crosses a not exposed view the client will see enter and exit
8350         // of the exposed predecessor followed by and enter and exit of that same
8351         // predecessor when entering and exiting the not exposed descendant. This
8352         // is fine since the client has a clear idea which view is hovered at the
8353         // price of a couple more events being sent. This is a simple and
8354         // working solution.
8355         View source = this;
8356         while (true) {
8357             if (source.includeForAccessibility()) {
8358                 source.sendAccessibilityEvent(eventType);
8359                 return;
8360             }
8361             ViewParent parent = source.getParent();
8362             if (parent instanceof View) {
8363                 source = (View) parent;
8364             } else {
8365                 return;
8366             }
8367         }
8368     }
8369 
8370     /**
8371      * Clears accessibility focus without calling any callback methods
8372      * normally invoked in {@link #clearAccessibilityFocus()}. This method
8373      * is used for clearing accessibility focus when giving this focus to
8374      * another view.
8375      */
8376     void clearAccessibilityFocusNoCallbacks() {
8377         if ((mPrivateFlags2 & PFLAG2_ACCESSIBILITY_FOCUSED) != 0) {
8378             mPrivateFlags2 &= ~PFLAG2_ACCESSIBILITY_FOCUSED;
8379             invalidate();
8380             sendAccessibilityEvent(AccessibilityEvent.TYPE_VIEW_ACCESSIBILITY_FOCUS_CLEARED);
8381         }
8382     }
8383 
8384     /**
8385      * Call this to try to give focus to a specific view or to one of its
8386      * descendants.
8387      *
8388      * A view will not actually take focus if it is not focusable ({@link #isFocusable} returns
8389      * false), or if it is focusable and it is not focusable in touch mode
8390      * ({@link #isFocusableInTouchMode}) while the device is in touch mode.
8391      *
8392      * See also {@link #focusSearch(int)}, which is what you call to say that you
8393      * have focus, and you want your parent to look for the next one.
8394      *
8395      * This is equivalent to calling {@link #requestFocus(int, Rect)} with arguments
8396      * {@link #FOCUS_DOWN} and <code>null</code>.
8397      *
8398      * @return Whether this view or one of its descendants actually took focus.
8399      */
8400     public final boolean requestFocus() {
8401         return requestFocus(View.FOCUS_DOWN);
8402     }
8403 
8404     /**
8405      * Call this to try to give focus to a specific view or to one of its
8406      * descendants and give it a hint about what direction focus is heading.
8407      *
8408      * A view will not actually take focus if it is not focusable ({@link #isFocusable} returns
8409      * false), or if it is focusable and it is not focusable in touch mode
8410      * ({@link #isFocusableInTouchMode}) while the device is in touch mode.
8411      *
8412      * See also {@link #focusSearch(int)}, which is what you call to say that you
8413      * have focus, and you want your parent to look for the next one.
8414      *
8415      * This is equivalent to calling {@link #requestFocus(int, Rect)} with
8416      * <code>null</code> set for the previously focused rectangle.
8417      *
8418      * @param direction One of FOCUS_UP, FOCUS_DOWN, FOCUS_LEFT, and FOCUS_RIGHT
8419      * @return Whether this view or one of its descendants actually took focus.
8420      */
8421     public final boolean requestFocus(int direction) {
8422         return requestFocus(direction, null);
8423     }
8424 
8425     /**
8426      * Call this to try to give focus to a specific view or to one of its descendants
8427      * and give it hints about the direction and a specific rectangle that the focus
8428      * is coming from.  The rectangle can help give larger views a finer grained hint
8429      * about where focus is coming from, and therefore, where to show selection, or
8430      * forward focus change internally.
8431      *
8432      * A view will not actually take focus if it is not focusable ({@link #isFocusable} returns
8433      * false), or if it is focusable and it is not focusable in touch mode
8434      * ({@link #isFocusableInTouchMode}) while the device is in touch mode.
8435      *
8436      * A View will not take focus if it is not visible.
8437      *
8438      * A View will not take focus if one of its parents has
8439      * {@link android.view.ViewGroup#getDescendantFocusability()} equal to
8440      * {@link ViewGroup#FOCUS_BLOCK_DESCENDANTS}.
8441      *
8442      * See also {@link #focusSearch(int)}, which is what you call to say that you
8443      * have focus, and you want your parent to look for the next one.
8444      *
8445      * You may wish to override this method if your custom {@link View} has an internal
8446      * {@link View} that it wishes to forward the request to.
8447      *
8448      * @param direction One of FOCUS_UP, FOCUS_DOWN, FOCUS_LEFT, and FOCUS_RIGHT
8449      * @param previouslyFocusedRect The rectangle (in this View's coordinate system)
8450      *        to give a finer grained hint about where focus is coming from.  May be null
8451      *        if there is no hint.
8452      * @return Whether this view or one of its descendants actually took focus.
8453      */
8454     public boolean requestFocus(int direction, Rect previouslyFocusedRect) {
8455         return requestFocusNoSearch(direction, previouslyFocusedRect);
8456     }
8457 
8458     private boolean requestFocusNoSearch(int direction, Rect previouslyFocusedRect) {
8459         // need to be focusable
8460         if ((mViewFlags & FOCUSABLE_MASK) != FOCUSABLE ||
8461                 (mViewFlags & VISIBILITY_MASK) != VISIBLE) {
8462             return false;
8463         }
8464 
8465         // need to be focusable in touch mode if in touch mode
8466         if (isInTouchMode() &&
8467             (FOCUSABLE_IN_TOUCH_MODE != (mViewFlags & FOCUSABLE_IN_TOUCH_MODE))) {
8468                return false;
8469         }
8470 
8471         // need to not have any parents blocking us
8472         if (hasAncestorThatBlocksDescendantFocus()) {
8473             return false;
8474         }
8475 
8476         handleFocusGainInternal(direction, previouslyFocusedRect);
8477         return true;
8478     }
8479 
8480     /**
8481      * Call this to try to give focus to a specific view or to one of its descendants. This is a
8482      * special variant of {@link #requestFocus() } that will allow views that are not focusable in
8483      * touch mode to request focus when they are touched.
8484      *
8485      * @return Whether this view or one of its descendants actually took focus.
8486      *
8487      * @see #isInTouchMode()
8488      *
8489      */
8490     public final boolean requestFocusFromTouch() {
8491         // Leave touch mode if we need to
8492         if (isInTouchMode()) {
8493             ViewRootImpl viewRoot = getViewRootImpl();
8494             if (viewRoot != null) {
8495                 viewRoot.ensureTouchMode(false);
8496             }
8497         }
8498         return requestFocus(View.FOCUS_DOWN);
8499     }
8500 
8501     /**
8502      * @return Whether any ancestor of this view blocks descendant focus.
8503      */
8504     private boolean hasAncestorThatBlocksDescendantFocus() {
8505         final boolean focusableInTouchMode = isFocusableInTouchMode();
8506         ViewParent ancestor = mParent;
8507         while (ancestor instanceof ViewGroup) {
8508             final ViewGroup vgAncestor = (ViewGroup) ancestor;
8509             if (vgAncestor.getDescendantFocusability() == ViewGroup.FOCUS_BLOCK_DESCENDANTS
8510                     || (!focusableInTouchMode && vgAncestor.shouldBlockFocusForTouchscreen())) {
8511                 return true;
8512             } else {
8513                 ancestor = vgAncestor.getParent();
8514             }
8515         }
8516         return false;
8517     }
8518 
8519     /**
8520      * Gets the mode for determining whether this View is important for accessibility
8521      * which is if it fires accessibility events and if it is reported to
8522      * accessibility services that query the screen.
8523      *
8524      * @return The mode for determining whether a View is important for accessibility.
8525      *
8526      * @attr ref android.R.styleable#View_importantForAccessibility
8527      *
8528      * @see #IMPORTANT_FOR_ACCESSIBILITY_YES
8529      * @see #IMPORTANT_FOR_ACCESSIBILITY_NO
8530      * @see #IMPORTANT_FOR_ACCESSIBILITY_NO_HIDE_DESCENDANTS
8531      * @see #IMPORTANT_FOR_ACCESSIBILITY_AUTO
8532      */
8533     @ViewDebug.ExportedProperty(category = "accessibility", mapping = {
8534             @ViewDebug.IntToString(from = IMPORTANT_FOR_ACCESSIBILITY_AUTO, to = "auto"),
8535             @ViewDebug.IntToString(from = IMPORTANT_FOR_ACCESSIBILITY_YES, to = "yes"),
8536             @ViewDebug.IntToString(from = IMPORTANT_FOR_ACCESSIBILITY_NO, to = "no"),
8537             @ViewDebug.IntToString(from = IMPORTANT_FOR_ACCESSIBILITY_NO_HIDE_DESCENDANTS,
8538                     to = "noHideDescendants")
8539         })
8540     public int getImportantForAccessibility() {
8541         return (mPrivateFlags2 & PFLAG2_IMPORTANT_FOR_ACCESSIBILITY_MASK)
8542                 >> PFLAG2_IMPORTANT_FOR_ACCESSIBILITY_SHIFT;
8543     }
8544 
8545     /**
8546      * Sets the live region mode for this view. This indicates to accessibility
8547      * services whether they should automatically notify the user about changes
8548      * to the view's content description or text, or to the content descriptions
8549      * or text of the view's children (where applicable).
8550      * <p>
8551      * For example, in a login screen with a TextView that displays an "incorrect
8552      * password" notification, that view should be marked as a live region with
8553      * mode {@link #ACCESSIBILITY_LIVE_REGION_POLITE}.
8554      * <p>
8555      * To disable change notifications for this view, use
8556      * {@link #ACCESSIBILITY_LIVE_REGION_NONE}. This is the default live region
8557      * mode for most views.
8558      * <p>
8559      * To indicate that the user should be notified of changes, use
8560      * {@link #ACCESSIBILITY_LIVE_REGION_POLITE}.
8561      * <p>
8562      * If the view's changes should interrupt ongoing speech and notify the user
8563      * immediately, use {@link #ACCESSIBILITY_LIVE_REGION_ASSERTIVE}.
8564      *
8565      * @param mode The live region mode for this view, one of:
8566      *        <ul>
8567      *        <li>{@link #ACCESSIBILITY_LIVE_REGION_NONE}
8568      *        <li>{@link #ACCESSIBILITY_LIVE_REGION_POLITE}
8569      *        <li>{@link #ACCESSIBILITY_LIVE_REGION_ASSERTIVE}
8570      *        </ul>
8571      * @attr ref android.R.styleable#View_accessibilityLiveRegion
8572      */
8573     public void setAccessibilityLiveRegion(int mode) {
8574         if (mode != getAccessibilityLiveRegion()) {
8575             mPrivateFlags2 &= ~PFLAG2_ACCESSIBILITY_LIVE_REGION_MASK;
8576             mPrivateFlags2 |= (mode << PFLAG2_ACCESSIBILITY_LIVE_REGION_SHIFT)
8577                     & PFLAG2_ACCESSIBILITY_LIVE_REGION_MASK;
8578             notifyViewAccessibilityStateChangedIfNeeded(
8579                     AccessibilityEvent.CONTENT_CHANGE_TYPE_UNDEFINED);
8580         }
8581     }
8582 
8583     /**
8584      * Gets the live region mode for this View.
8585      *
8586      * @return The live region mode for the view.
8587      *
8588      * @attr ref android.R.styleable#View_accessibilityLiveRegion
8589      *
8590      * @see #setAccessibilityLiveRegion(int)
8591      */
8592     public int getAccessibilityLiveRegion() {
8593         return (mPrivateFlags2 & PFLAG2_ACCESSIBILITY_LIVE_REGION_MASK)
8594                 >> PFLAG2_ACCESSIBILITY_LIVE_REGION_SHIFT;
8595     }
8596 
8597     /**
8598      * Sets how to determine whether this view is important for accessibility
8599      * which is if it fires accessibility events and if it is reported to
8600      * accessibility services that query the screen.
8601      *
8602      * @param mode How to determine whether this view is important for accessibility.
8603      *
8604      * @attr ref android.R.styleable#View_importantForAccessibility
8605      *
8606      * @see #IMPORTANT_FOR_ACCESSIBILITY_YES
8607      * @see #IMPORTANT_FOR_ACCESSIBILITY_NO
8608      * @see #IMPORTANT_FOR_ACCESSIBILITY_NO_HIDE_DESCENDANTS
8609      * @see #IMPORTANT_FOR_ACCESSIBILITY_AUTO
8610      */
8611     public void setImportantForAccessibility(int mode) {
8612         final int oldMode = getImportantForAccessibility();
8613         if (mode != oldMode) {
8614             // If we're moving between AUTO and another state, we might not need
8615             // to send a subtree changed notification. We'll store the computed
8616             // importance, since we'll need to check it later to make sure.
8617             final boolean maySkipNotify = oldMode == IMPORTANT_FOR_ACCESSIBILITY_AUTO
8618                     || mode == IMPORTANT_FOR_ACCESSIBILITY_AUTO;
8619             final boolean oldIncludeForAccessibility = maySkipNotify && includeForAccessibility();
8620             mPrivateFlags2 &= ~PFLAG2_IMPORTANT_FOR_ACCESSIBILITY_MASK;
8621             mPrivateFlags2 |= (mode << PFLAG2_IMPORTANT_FOR_ACCESSIBILITY_SHIFT)
8622                     & PFLAG2_IMPORTANT_FOR_ACCESSIBILITY_MASK;
8623             if (!maySkipNotify || oldIncludeForAccessibility != includeForAccessibility()) {
8624                 notifySubtreeAccessibilityStateChangedIfNeeded();
8625             } else {
8626                 notifyViewAccessibilityStateChangedIfNeeded(
8627                         AccessibilityEvent.CONTENT_CHANGE_TYPE_UNDEFINED);
8628             }
8629         }
8630     }
8631 
8632     /**
8633      * Computes whether this view should be exposed for accessibility. In
8634      * general, views that are interactive or provide information are exposed
8635      * while views that serve only as containers are hidden.
8636      * <p>
8637      * If an ancestor of this view has importance
8638      * {@link #IMPORTANT_FOR_ACCESSIBILITY_NO_HIDE_DESCENDANTS}, this method
8639      * returns <code>false</code>.
8640      * <p>
8641      * Otherwise, the value is computed according to the view's
8642      * {@link #getImportantForAccessibility()} value:
8643      * <ol>
8644      * <li>{@link #IMPORTANT_FOR_ACCESSIBILITY_NO} or
8645      * {@link #IMPORTANT_FOR_ACCESSIBILITY_NO_HIDE_DESCENDANTS}, return <code>false
8646      * </code>
8647      * <li>{@link #IMPORTANT_FOR_ACCESSIBILITY_YES}, return <code>true</code>
8648      * <li>{@link #IMPORTANT_FOR_ACCESSIBILITY_AUTO}, return <code>true</code> if
8649      * view satisfies any of the following:
8650      * <ul>
8651      * <li>Is actionable, e.g. {@link #isClickable()},
8652      * {@link #isLongClickable()}, or {@link #isFocusable()}
8653      * <li>Has an {@link AccessibilityDelegate}
8654      * <li>Has an interaction listener, e.g. {@link OnTouchListener},
8655      * {@link OnKeyListener}, etc.
8656      * <li>Is an accessibility live region, e.g.
8657      * {@link #getAccessibilityLiveRegion()} is not
8658      * {@link #ACCESSIBILITY_LIVE_REGION_NONE}.
8659      * </ul>
8660      * </ol>
8661      *
8662      * @return Whether the view is exposed for accessibility.
8663      * @see #setImportantForAccessibility(int)
8664      * @see #getImportantForAccessibility()
8665      */
8666     public boolean isImportantForAccessibility() {
8667         final int mode = (mPrivateFlags2 & PFLAG2_IMPORTANT_FOR_ACCESSIBILITY_MASK)
8668                 >> PFLAG2_IMPORTANT_FOR_ACCESSIBILITY_SHIFT;
8669         if (mode == IMPORTANT_FOR_ACCESSIBILITY_NO
8670                 || mode == IMPORTANT_FOR_ACCESSIBILITY_NO_HIDE_DESCENDANTS) {
8671             return false;
8672         }
8673 
8674         // Check parent mode to ensure we're not hidden.
8675         ViewParent parent = mParent;
8676         while (parent instanceof View) {
8677             if (((View) parent).getImportantForAccessibility()
8678                     == IMPORTANT_FOR_ACCESSIBILITY_NO_HIDE_DESCENDANTS) {
8679                 return false;
8680             }
8681             parent = parent.getParent();
8682         }
8683 
8684         return mode == IMPORTANT_FOR_ACCESSIBILITY_YES || isActionableForAccessibility()
8685                 || hasListenersForAccessibility() || getAccessibilityNodeProvider() != null
8686                 || getAccessibilityLiveRegion() != ACCESSIBILITY_LIVE_REGION_NONE;
8687     }
8688 
8689     /**
8690      * Gets the parent for accessibility purposes. Note that the parent for
8691      * accessibility is not necessary the immediate parent. It is the first
8692      * predecessor that is important for accessibility.
8693      *
8694      * @return The parent for accessibility purposes.
8695      */
8696     public ViewParent getParentForAccessibility() {
8697         if (mParent instanceof View) {
8698             View parentView = (View) mParent;
8699             if (parentView.includeForAccessibility()) {
8700                 return mParent;
8701             } else {
8702                 return mParent.getParentForAccessibility();
8703             }
8704         }
8705         return null;
8706     }
8707 
8708     /**
8709      * Adds the children of this View relevant for accessibility to the given list
8710      * as output. Since some Views are not important for accessibility the added
8711      * child views are not necessarily direct children of this view, rather they are
8712      * the first level of descendants important for accessibility.
8713      *
8714      * @param outChildren The output list that will receive children for accessibility.
8715      */
8716     public void addChildrenForAccessibility(ArrayList<View> outChildren) {
8717 
8718     }
8719 
8720     /**
8721      * Whether to regard this view for accessibility. A view is regarded for
8722      * accessibility if it is important for accessibility or the querying
8723      * accessibility service has explicitly requested that view not
8724      * important for accessibility are regarded.
8725      *
8726      * @return Whether to regard the view for accessibility.
8727      *
8728      * @hide
8729      */
8730     public boolean includeForAccessibility() {
8731         if (mAttachInfo != null) {
8732             return (mAttachInfo.mAccessibilityFetchFlags
8733                     & AccessibilityNodeInfo.FLAG_INCLUDE_NOT_IMPORTANT_VIEWS) != 0
8734                     || isImportantForAccessibility();
8735         }
8736         return false;
8737     }
8738 
8739     /**
8740      * Returns whether the View is considered actionable from
8741      * accessibility perspective. Such view are important for
8742      * accessibility.
8743      *
8744      * @return True if the view is actionable for accessibility.
8745      *
8746      * @hide
8747      */
8748     public boolean isActionableForAccessibility() {
8749         return (isClickable() || isLongClickable() || isFocusable());
8750     }
8751 
8752     /**
8753      * Returns whether the View has registered callbacks which makes it
8754      * important for accessibility.
8755      *
8756      * @return True if the view is actionable for accessibility.
8757      */
8758     private boolean hasListenersForAccessibility() {
8759         ListenerInfo info = getListenerInfo();
8760         return mTouchDelegate != null || info.mOnKeyListener != null
8761                 || info.mOnTouchListener != null || info.mOnGenericMotionListener != null
8762                 || info.mOnHoverListener != null || info.mOnDragListener != null;
8763     }
8764 
8765     /**
8766      * Notifies that the accessibility state of this view changed. The change
8767      * is local to this view and does not represent structural changes such
8768      * as children and parent. For example, the view became focusable. The
8769      * notification is at at most once every
8770      * {@link ViewConfiguration#getSendRecurringAccessibilityEventsInterval()}
8771      * to avoid unnecessary load to the system. Also once a view has a pending
8772      * notification this method is a NOP until the notification has been sent.
8773      *
8774      * @hide
8775      */
8776     public void notifyViewAccessibilityStateChangedIfNeeded(int changeType) {
8777         if (!AccessibilityManager.getInstance(mContext).isEnabled() || mAttachInfo == null) {
8778             return;
8779         }
8780         if (mSendViewStateChangedAccessibilityEvent == null) {
8781             mSendViewStateChangedAccessibilityEvent =
8782                     new SendViewStateChangedAccessibilityEvent();
8783         }
8784         mSendViewStateChangedAccessibilityEvent.runOrPost(changeType);
8785     }
8786 
8787     /**
8788      * Notifies that the accessibility state of this view changed. The change
8789      * is *not* local to this view and does represent structural changes such
8790      * as children and parent. For example, the view size changed. The
8791      * notification is at at most once every
8792      * {@link ViewConfiguration#getSendRecurringAccessibilityEventsInterval()}
8793      * to avoid unnecessary load to the system. Also once a view has a pending
8794      * notification this method is a NOP until the notification has been sent.
8795      *
8796      * @hide
8797      */
8798     public void notifySubtreeAccessibilityStateChangedIfNeeded() {
8799         if (!AccessibilityManager.getInstance(mContext).isEnabled() || mAttachInfo == null) {
8800             return;
8801         }
8802         if ((mPrivateFlags2 & PFLAG2_SUBTREE_ACCESSIBILITY_STATE_CHANGED) == 0) {
8803             mPrivateFlags2 |= PFLAG2_SUBTREE_ACCESSIBILITY_STATE_CHANGED;
8804             if (mParent != null) {
8805                 try {
8806                     mParent.notifySubtreeAccessibilityStateChanged(
8807                             this, this, AccessibilityEvent.CONTENT_CHANGE_TYPE_SUBTREE);
8808                 } catch (AbstractMethodError e) {
8809                     Log.e(VIEW_LOG_TAG, mParent.getClass().getSimpleName() +
8810                             " does not fully implement ViewParent", e);
8811                 }
8812             }
8813         }
8814     }
8815 
8816     /**
8817      * Change the visibility of the View without triggering any other changes. This is
8818      * important for transitions, where visibility changes should not adjust focus or
8819      * trigger a new layout. This is only used when the visibility has already been changed
8820      * and we need a transient value during an animation. When the animation completes,
8821      * the original visibility value is always restored.
8822      *
8823      * @param visibility One of {@link #VISIBLE}, {@link #INVISIBLE}, or {@link #GONE}.
8824      * @hide
8825      */
8826     public void setTransitionVisibility(@Visibility int visibility) {
8827         mViewFlags = (mViewFlags & ~View.VISIBILITY_MASK) | visibility;
8828     }
8829 
8830     /**
8831      * Reset the flag indicating the accessibility state of the subtree rooted
8832      * at this view changed.
8833      */
8834     void resetSubtreeAccessibilityStateChanged() {
8835         mPrivateFlags2 &= ~PFLAG2_SUBTREE_ACCESSIBILITY_STATE_CHANGED;
8836     }
8837 
8838     /**
8839      * Report an accessibility action to this view's parents for delegated processing.
8840      *
8841      * <p>Implementations of {@link #performAccessibilityAction(int, Bundle)} may internally
8842      * call this method to delegate an accessibility action to a supporting parent. If the parent
8843      * returns true from its
8844      * {@link ViewParent#onNestedPrePerformAccessibilityAction(View, int, android.os.Bundle)}
8845      * method this method will return true to signify that the action was consumed.</p>
8846      *
8847      * <p>This method is useful for implementing nested scrolling child views. If
8848      * {@link #isNestedScrollingEnabled()} returns true and the action is a scrolling action
8849      * a custom view implementation may invoke this method to allow a parent to consume the
8850      * scroll first. If this method returns true the custom view should skip its own scrolling
8851      * behavior.</p>
8852      *
8853      * @param action Accessibility action to delegate
8854      * @param arguments Optional action arguments
8855      * @return true if the action was consumed by a parent
8856      */
8857     public boolean dispatchNestedPrePerformAccessibilityAction(int action, Bundle arguments) {
8858         for (ViewParent p = getParent(); p != null; p = p.getParent()) {
8859             if (p.onNestedPrePerformAccessibilityAction(this, action, arguments)) {
8860                 return true;
8861             }
8862         }
8863         return false;
8864     }
8865 
8866     /**
8867      * Performs the specified accessibility action on the view. For
8868      * possible accessibility actions look at {@link AccessibilityNodeInfo}.
8869      * <p>
8870      * If an {@link AccessibilityDelegate} has been specified via calling
8871      * {@link #setAccessibilityDelegate(AccessibilityDelegate)} its
8872      * {@link AccessibilityDelegate#performAccessibilityAction(View, int, Bundle)}
8873      * is responsible for handling this call.
8874      * </p>
8875      *
8876      * <p>The default implementation will delegate
8877      * {@link AccessibilityNodeInfo#ACTION_SCROLL_BACKWARD} and
8878      * {@link AccessibilityNodeInfo#ACTION_SCROLL_FORWARD} to nested scrolling parents if
8879      * {@link #isNestedScrollingEnabled() nested scrolling is enabled} on this view.</p>
8880      *
8881      * @param action The action to perform.
8882      * @param arguments Optional action arguments.
8883      * @return Whether the action was performed.
8884      */
8885     public boolean performAccessibilityAction(int action, Bundle arguments) {
8886       if (mAccessibilityDelegate != null) {
8887           return mAccessibilityDelegate.performAccessibilityAction(this, action, arguments);
8888       } else {
8889           return performAccessibilityActionInternal(action, arguments);
8890       }
8891     }
8892 
8893    /**
8894     * @see #performAccessibilityAction(int, Bundle)
8895     *
8896     * Note: Called from the default {@link AccessibilityDelegate}.
8897     *
8898     * @hide
8899     */
8900     public boolean performAccessibilityActionInternal(int action, Bundle arguments) {
8901         if (isNestedScrollingEnabled()
8902                 && (action == AccessibilityNodeInfo.ACTION_SCROLL_BACKWARD
8903                 || action == AccessibilityNodeInfo.ACTION_SCROLL_FORWARD
8904                 || action == R.id.accessibilityActionScrollUp
8905                 || action == R.id.accessibilityActionScrollLeft
8906                 || action == R.id.accessibilityActionScrollDown
8907                 || action == R.id.accessibilityActionScrollRight)) {
8908             if (dispatchNestedPrePerformAccessibilityAction(action, arguments)) {
8909                 return true;
8910             }
8911         }
8912 
8913         switch (action) {
8914             case AccessibilityNodeInfo.ACTION_CLICK: {
8915                 if (isClickable()) {
8916                     performClick();
8917                     return true;
8918                 }
8919             } break;
8920             case AccessibilityNodeInfo.ACTION_LONG_CLICK: {
8921                 if (isLongClickable()) {
8922                     performLongClick();
8923                     return true;
8924                 }
8925             } break;
8926             case AccessibilityNodeInfo.ACTION_FOCUS: {
8927                 if (!hasFocus()) {
8928                     // Get out of touch mode since accessibility
8929                     // wants to move focus around.
8930                     getViewRootImpl().ensureTouchMode(false);
8931                     return requestFocus();
8932                 }
8933             } break;
8934             case AccessibilityNodeInfo.ACTION_CLEAR_FOCUS: {
8935                 if (hasFocus()) {
8936                     clearFocus();
8937                     return !isFocused();
8938                 }
8939             } break;
8940             case AccessibilityNodeInfo.ACTION_SELECT: {
8941                 if (!isSelected()) {
8942                     setSelected(true);
8943                     return isSelected();
8944                 }
8945             } break;
8946             case AccessibilityNodeInfo.ACTION_CLEAR_SELECTION: {
8947                 if (isSelected()) {
8948                     setSelected(false);
8949                     return !isSelected();
8950                 }
8951             } break;
8952             case AccessibilityNodeInfo.ACTION_ACCESSIBILITY_FOCUS: {
8953                 if (!isAccessibilityFocused()) {
8954                     return requestAccessibilityFocus();
8955                 }
8956             } break;
8957             case AccessibilityNodeInfo.ACTION_CLEAR_ACCESSIBILITY_FOCUS: {
8958                 if (isAccessibilityFocused()) {
8959                     clearAccessibilityFocus();
8960                     return true;
8961                 }
8962             } break;
8963             case AccessibilityNodeInfo.ACTION_NEXT_AT_MOVEMENT_GRANULARITY: {
8964                 if (arguments != null) {
8965                     final int granularity = arguments.getInt(
8966                             AccessibilityNodeInfo.ACTION_ARGUMENT_MOVEMENT_GRANULARITY_INT);
8967                     final boolean extendSelection = arguments.getBoolean(
8968                             AccessibilityNodeInfo.ACTION_ARGUMENT_EXTEND_SELECTION_BOOLEAN);
8969                     return traverseAtGranularity(granularity, true, extendSelection);
8970                 }
8971             } break;
8972             case AccessibilityNodeInfo.ACTION_PREVIOUS_AT_MOVEMENT_GRANULARITY: {
8973                 if (arguments != null) {
8974                     final int granularity = arguments.getInt(
8975                             AccessibilityNodeInfo.ACTION_ARGUMENT_MOVEMENT_GRANULARITY_INT);
8976                     final boolean extendSelection = arguments.getBoolean(
8977                             AccessibilityNodeInfo.ACTION_ARGUMENT_EXTEND_SELECTION_BOOLEAN);
8978                     return traverseAtGranularity(granularity, false, extendSelection);
8979                 }
8980             } break;
8981             case AccessibilityNodeInfo.ACTION_SET_SELECTION: {
8982                 CharSequence text = getIterableTextForAccessibility();
8983                 if (text == null) {
8984                     return false;
8985                 }
8986                 final int start = (arguments != null) ? arguments.getInt(
8987                         AccessibilityNodeInfo.ACTION_ARGUMENT_SELECTION_START_INT, -1) : -1;
8988                 final int end = (arguments != null) ? arguments.getInt(
8989                 AccessibilityNodeInfo.ACTION_ARGUMENT_SELECTION_END_INT, -1) : -1;
8990                 // Only cursor position can be specified (selection length == 0)
8991                 if ((getAccessibilitySelectionStart() != start
8992                         || getAccessibilitySelectionEnd() != end)
8993                         && (start == end)) {
8994                     setAccessibilitySelection(start, end);
8995                     notifyViewAccessibilityStateChangedIfNeeded(
8996                             AccessibilityEvent.CONTENT_CHANGE_TYPE_UNDEFINED);
8997                     return true;
8998                 }
8999             } break;
9000             case R.id.accessibilityActionShowOnScreen: {
9001                 if (mAttachInfo != null) {
9002                     final Rect r = mAttachInfo.mTmpInvalRect;
9003                     getDrawingRect(r);
9004                     return requestRectangleOnScreen(r, true);
9005                 }
9006             } break;
9007             case R.id.accessibilityActionContextClick: {
9008                 if (isContextClickable()) {
9009                     performContextClick();
9010                     return true;
9011                 }
9012             } break;
9013         }
9014         return false;
9015     }
9016 
9017     private boolean traverseAtGranularity(int granularity, boolean forward,
9018             boolean extendSelection) {
9019         CharSequence text = getIterableTextForAccessibility();
9020         if (text == null || text.length() == 0) {
9021             return false;
9022         }
9023         TextSegmentIterator iterator = getIteratorForGranularity(granularity);
9024         if (iterator == null) {
9025             return false;
9026         }
9027         int current = getAccessibilitySelectionEnd();
9028         if (current == ACCESSIBILITY_CURSOR_POSITION_UNDEFINED) {
9029             current = forward ? 0 : text.length();
9030         }
9031         final int[] range = forward ? iterator.following(current) : iterator.preceding(current);
9032         if (range == null) {
9033             return false;
9034         }
9035         final int segmentStart = range[0];
9036         final int segmentEnd = range[1];
9037         int selectionStart;
9038         int selectionEnd;
9039         if (extendSelection && isAccessibilitySelectionExtendable()) {
9040             selectionStart = getAccessibilitySelectionStart();
9041             if (selectionStart == ACCESSIBILITY_CURSOR_POSITION_UNDEFINED) {
9042                 selectionStart = forward ? segmentStart : segmentEnd;
9043             }
9044             selectionEnd = forward ? segmentEnd : segmentStart;
9045         } else {
9046             selectionStart = selectionEnd= forward ? segmentEnd : segmentStart;
9047         }
9048         setAccessibilitySelection(selectionStart, selectionEnd);
9049         final int action = forward ? AccessibilityNodeInfo.ACTION_NEXT_AT_MOVEMENT_GRANULARITY
9050                 : AccessibilityNodeInfo.ACTION_PREVIOUS_AT_MOVEMENT_GRANULARITY;
9051         sendViewTextTraversedAtGranularityEvent(action, granularity, segmentStart, segmentEnd);
9052         return true;
9053     }
9054 
9055     /**
9056      * Gets the text reported for accessibility purposes.
9057      *
9058      * @return The accessibility text.
9059      *
9060      * @hide
9061      */
9062     public CharSequence getIterableTextForAccessibility() {
9063         return getContentDescription();
9064     }
9065 
9066     /**
9067      * Gets whether accessibility selection can be extended.
9068      *
9069      * @return If selection is extensible.
9070      *
9071      * @hide
9072      */
9073     public boolean isAccessibilitySelectionExtendable() {
9074         return false;
9075     }
9076 
9077     /**
9078      * @hide
9079      */
9080     public int getAccessibilitySelectionStart() {
9081         return mAccessibilityCursorPosition;
9082     }
9083 
9084     /**
9085      * @hide
9086      */
9087     public int getAccessibilitySelectionEnd() {
9088         return getAccessibilitySelectionStart();
9089     }
9090 
9091     /**
9092      * @hide
9093      */
9094     public void setAccessibilitySelection(int start, int end) {
9095         if (start ==  end && end == mAccessibilityCursorPosition) {
9096             return;
9097         }
9098         if (start >= 0 && start == end && end <= getIterableTextForAccessibility().length()) {
9099             mAccessibilityCursorPosition = start;
9100         } else {
9101             mAccessibilityCursorPosition = ACCESSIBILITY_CURSOR_POSITION_UNDEFINED;
9102         }
9103         sendAccessibilityEvent(AccessibilityEvent.TYPE_VIEW_TEXT_SELECTION_CHANGED);
9104     }
9105 
9106     private void sendViewTextTraversedAtGranularityEvent(int action, int granularity,
9107             int fromIndex, int toIndex) {
9108         if (mParent == null) {
9109             return;
9110         }
9111         AccessibilityEvent event = AccessibilityEvent.obtain(
9112                 AccessibilityEvent.TYPE_VIEW_TEXT_TRAVERSED_AT_MOVEMENT_GRANULARITY);
9113         onInitializeAccessibilityEvent(event);
9114         onPopulateAccessibilityEvent(event);
9115         event.setFromIndex(fromIndex);
9116         event.setToIndex(toIndex);
9117         event.setAction(action);
9118         event.setMovementGranularity(granularity);
9119         mParent.requestSendAccessibilityEvent(this, event);
9120     }
9121 
9122     /**
9123      * @hide
9124      */
9125     public TextSegmentIterator getIteratorForGranularity(int granularity) {
9126         switch (granularity) {
9127             case AccessibilityNodeInfo.MOVEMENT_GRANULARITY_CHARACTER: {
9128                 CharSequence text = getIterableTextForAccessibility();
9129                 if (text != null && text.length() > 0) {
9130                     CharacterTextSegmentIterator iterator =
9131                         CharacterTextSegmentIterator.getInstance(
9132                                 mContext.getResources().getConfiguration().locale);
9133                     iterator.initialize(text.toString());
9134                     return iterator;
9135                 }
9136             } break;
9137             case AccessibilityNodeInfo.MOVEMENT_GRANULARITY_WORD: {
9138                 CharSequence text = getIterableTextForAccessibility();
9139                 if (text != null && text.length() > 0) {
9140                     WordTextSegmentIterator iterator =
9141                         WordTextSegmentIterator.getInstance(
9142                                 mContext.getResources().getConfiguration().locale);
9143                     iterator.initialize(text.toString());
9144                     return iterator;
9145                 }
9146             } break;
9147             case AccessibilityNodeInfo.MOVEMENT_GRANULARITY_PARAGRAPH: {
9148                 CharSequence text = getIterableTextForAccessibility();
9149                 if (text != null && text.length() > 0) {
9150                     ParagraphTextSegmentIterator iterator =
9151                         ParagraphTextSegmentIterator.getInstance();
9152                     iterator.initialize(text.toString());
9153                     return iterator;
9154                 }
9155             } break;
9156         }
9157         return null;
9158     }
9159 
9160     /**
9161      * @hide
9162      */
9163     public void dispatchStartTemporaryDetach() {
9164         onStartTemporaryDetach();
9165     }
9166 
9167     /**
9168      * This is called when a container is going to temporarily detach a child, with
9169      * {@link ViewGroup#detachViewFromParent(View) ViewGroup.detachViewFromParent}.
9170      * It will either be followed by {@link #onFinishTemporaryDetach()} or
9171      * {@link #onDetachedFromWindow()} when the container is done.
9172      */
9173     public void onStartTemporaryDetach() {
9174         removeUnsetPressCallback();
9175         mPrivateFlags |= PFLAG_CANCEL_NEXT_UP_EVENT;
9176     }
9177 
9178     /**
9179      * @hide
9180      */
9181     public void dispatchFinishTemporaryDetach() {
9182         onFinishTemporaryDetach();
9183     }
9184 
9185     /**
9186      * Called after {@link #onStartTemporaryDetach} when the container is done
9187      * changing the view.
9188      */
9189     public void onFinishTemporaryDetach() {
9190     }
9191 
9192     /**
9193      * Return the global {@link KeyEvent.DispatcherState KeyEvent.DispatcherState}
9194      * for this view's window.  Returns null if the view is not currently attached
9195      * to the window.  Normally you will not need to use this directly, but
9196      * just use the standard high-level event callbacks like
9197      * {@link #onKeyDown(int, KeyEvent)}.
9198      */
9199     public KeyEvent.DispatcherState getKeyDispatcherState() {
9200         return mAttachInfo != null ? mAttachInfo.mKeyDispatchState : null;
9201     }
9202 
9203     /**
9204      * Dispatch a key event before it is processed by any input method
9205      * associated with the view hierarchy.  This can be used to intercept
9206      * key events in special situations before the IME consumes them; a
9207      * typical example would be handling the BACK key to update the application's
9208      * UI instead of allowing the IME to see it and close itself.
9209      *
9210      * @param event The key event to be dispatched.
9211      * @return True if the event was handled, false otherwise.
9212      */
9213     public boolean dispatchKeyEventPreIme(KeyEvent event) {
9214         return onKeyPreIme(event.getKeyCode(), event);
9215     }
9216 
9217     /**
9218      * Dispatch a key event to the next view on the focus path. This path runs
9219      * from the top of the view tree down to the currently focused view. If this
9220      * view has focus, it will dispatch to itself. Otherwise it will dispatch
9221      * the next node down the focus path. This method also fires any key
9222      * listeners.
9223      *
9224      * @param event The key event to be dispatched.
9225      * @return True if the event was handled, false otherwise.
9226      */
9227     public boolean dispatchKeyEvent(KeyEvent event) {
9228         if (mInputEventConsistencyVerifier != null) {
9229             mInputEventConsistencyVerifier.onKeyEvent(event, 0);
9230         }
9231 
9232         // Give any attached key listener a first crack at the event.
9233         //noinspection SimplifiableIfStatement
9234         ListenerInfo li = mListenerInfo;
9235         if (li != null && li.mOnKeyListener != null && (mViewFlags & ENABLED_MASK) == ENABLED
9236                 && li.mOnKeyListener.onKey(this, event.getKeyCode(), event)) {
9237             return true;
9238         }
9239 
9240         if (event.dispatch(this, mAttachInfo != null
9241                 ? mAttachInfo.mKeyDispatchState : null, this)) {
9242             return true;
9243         }
9244 
9245         if (mInputEventConsistencyVerifier != null) {
9246             mInputEventConsistencyVerifier.onUnhandledEvent(event, 0);
9247         }
9248         return false;
9249     }
9250 
9251     /**
9252      * Dispatches a key shortcut event.
9253      *
9254      * @param event The key event to be dispatched.
9255      * @return True if the event was handled by the view, false otherwise.
9256      */
9257     public boolean dispatchKeyShortcutEvent(KeyEvent event) {
9258         return onKeyShortcut(event.getKeyCode(), event);
9259     }
9260 
9261     /**
9262      * Pass the touch screen motion event down to the target view, or this
9263      * view if it is the target.
9264      *
9265      * @param event The motion event to be dispatched.
9266      * @return True if the event was handled by the view, false otherwise.
9267      */
9268     public boolean dispatchTouchEvent(MotionEvent event) {
9269         // If the event should be handled by accessibility focus first.
9270         if (event.isTargetAccessibilityFocus()) {
9271             // We don't have focus or no virtual descendant has it, do not handle the event.
9272             if (!isAccessibilityFocusedViewOrHost()) {
9273                 return false;
9274             }
9275             // We have focus and got the event, then use normal event dispatch.
9276             event.setTargetAccessibilityFocus(false);
9277         }
9278 
9279         boolean result = false;
9280 
9281         if (mInputEventConsistencyVerifier != null) {
9282             mInputEventConsistencyVerifier.onTouchEvent(event, 0);
9283         }
9284 
9285         final int actionMasked = event.getActionMasked();
9286         if (actionMasked == MotionEvent.ACTION_DOWN) {
9287             // Defensive cleanup for new gesture
9288             stopNestedScroll();
9289         }
9290 
9291         if (onFilterTouchEventForSecurity(event)) {
9292             //noinspection SimplifiableIfStatement
9293             ListenerInfo li = mListenerInfo;
9294             if (li != null && li.mOnTouchListener != null
9295                     && (mViewFlags & ENABLED_MASK) == ENABLED
9296                     && li.mOnTouchListener.onTouch(this, event)) {
9297                 result = true;
9298             }
9299 
9300             if (!result && onTouchEvent(event)) {
9301                 result = true;
9302             }
9303         }
9304 
9305         if (!result && mInputEventConsistencyVerifier != null) {
9306             mInputEventConsistencyVerifier.onUnhandledEvent(event, 0);
9307         }
9308 
9309         // Clean up after nested scrolls if this is the end of a gesture;
9310         // also cancel it if we tried an ACTION_DOWN but we didn't want the rest
9311         // of the gesture.
9312         if (actionMasked == MotionEvent.ACTION_UP ||
9313                 actionMasked == MotionEvent.ACTION_CANCEL ||
9314                 (actionMasked == MotionEvent.ACTION_DOWN && !result)) {
9315             stopNestedScroll();
9316         }
9317 
9318         return result;
9319     }
9320 
9321     boolean isAccessibilityFocusedViewOrHost() {
9322         return isAccessibilityFocused() || (getViewRootImpl() != null && getViewRootImpl()
9323                 .getAccessibilityFocusedHost() == this);
9324     }
9325 
9326     /**
9327      * Filter the touch event to apply security policies.
9328      *
9329      * @param event The motion event to be filtered.
9330      * @return True if the event should be dispatched, false if the event should be dropped.
9331      *
9332      * @see #getFilterTouchesWhenObscured
9333      */
9334     public boolean onFilterTouchEventForSecurity(MotionEvent event) {
9335         //noinspection RedundantIfStatement
9336         if ((mViewFlags & FILTER_TOUCHES_WHEN_OBSCURED) != 0
9337                 && (event.getFlags() & MotionEvent.FLAG_WINDOW_IS_OBSCURED) != 0) {
9338             // Window is obscured, drop this touch.
9339             return false;
9340         }
9341         return true;
9342     }
9343 
9344     /**
9345      * Pass a trackball motion event down to the focused view.
9346      *
9347      * @param event The motion event to be dispatched.
9348      * @return True if the event was handled by the view, false otherwise.
9349      */
9350     public boolean dispatchTrackballEvent(MotionEvent event) {
9351         if (mInputEventConsistencyVerifier != null) {
9352             mInputEventConsistencyVerifier.onTrackballEvent(event, 0);
9353         }
9354 
9355         return onTrackballEvent(event);
9356     }
9357 
9358     /**
9359      * Dispatch a generic motion event.
9360      * <p>
9361      * Generic motion events with source class {@link InputDevice#SOURCE_CLASS_POINTER}
9362      * are delivered to the view under the pointer.  All other generic motion events are
9363      * delivered to the focused view.  Hover events are handled specially and are delivered
9364      * to {@link #onHoverEvent(MotionEvent)}.
9365      * </p>
9366      *
9367      * @param event The motion event to be dispatched.
9368      * @return True if the event was handled by the view, false otherwise.
9369      */
9370     public boolean dispatchGenericMotionEvent(MotionEvent event) {
9371         if (mInputEventConsistencyVerifier != null) {
9372             mInputEventConsistencyVerifier.onGenericMotionEvent(event, 0);
9373         }
9374 
9375         final int source = event.getSource();
9376         if ((source & InputDevice.SOURCE_CLASS_POINTER) != 0) {
9377             final int action = event.getAction();
9378             if (action == MotionEvent.ACTION_HOVER_ENTER
9379                     || action == MotionEvent.ACTION_HOVER_MOVE
9380                     || action == MotionEvent.ACTION_HOVER_EXIT) {
9381                 if (dispatchHoverEvent(event)) {
9382                     return true;
9383                 }
9384             } else if (dispatchGenericPointerEvent(event)) {
9385                 return true;
9386             }
9387         } else if (dispatchGenericFocusedEvent(event)) {
9388             return true;
9389         }
9390 
9391         if (dispatchGenericMotionEventInternal(event)) {
9392             return true;
9393         }
9394 
9395         if (mInputEventConsistencyVerifier != null) {
9396             mInputEventConsistencyVerifier.onUnhandledEvent(event, 0);
9397         }
9398         return false;
9399     }
9400 
9401     private boolean dispatchGenericMotionEventInternal(MotionEvent event) {
9402         //noinspection SimplifiableIfStatement
9403         ListenerInfo li = mListenerInfo;
9404         if (li != null && li.mOnGenericMotionListener != null
9405                 && (mViewFlags & ENABLED_MASK) == ENABLED
9406                 && li.mOnGenericMotionListener.onGenericMotion(this, event)) {
9407             return true;
9408         }
9409 
9410         if (onGenericMotionEvent(event)) {
9411             return true;
9412         }
9413 
9414         final int actionButton = event.getActionButton();
9415         switch (event.getActionMasked()) {
9416             case MotionEvent.ACTION_BUTTON_PRESS:
9417                 if (isContextClickable() && !mInContextButtonPress && !mHasPerformedLongPress
9418                         && (actionButton == MotionEvent.BUTTON_STYLUS_PRIMARY
9419                         || actionButton == MotionEvent.BUTTON_SECONDARY)) {
9420                     if (performContextClick()) {
9421                         mInContextButtonPress = true;
9422                         setPressed(true, event.getX(), event.getY());
9423                         removeTapCallback();
9424                         removeLongPressCallback();
9425                         return true;
9426                     }
9427                 }
9428                 break;
9429 
9430             case MotionEvent.ACTION_BUTTON_RELEASE:
9431                 if (mInContextButtonPress && (actionButton == MotionEvent.BUTTON_STYLUS_PRIMARY
9432                         || actionButton == MotionEvent.BUTTON_SECONDARY)) {
9433                     mInContextButtonPress = false;
9434                     mIgnoreNextUpEvent = true;
9435                 }
9436                 break;
9437         }
9438 
9439         if (mInputEventConsistencyVerifier != null) {
9440             mInputEventConsistencyVerifier.onUnhandledEvent(event, 0);
9441         }
9442         return false;
9443     }
9444 
9445     /**
9446      * Dispatch a hover event.
9447      * <p>
9448      * Do not call this method directly.
9449      * Call {@link #dispatchGenericMotionEvent(MotionEvent)} instead.
9450      * </p>
9451      *
9452      * @param event The motion event to be dispatched.
9453      * @return True if the event was handled by the view, false otherwise.
9454      */
9455     protected boolean dispatchHoverEvent(MotionEvent event) {
9456         ListenerInfo li = mListenerInfo;
9457         //noinspection SimplifiableIfStatement
9458         if (li != null && li.mOnHoverListener != null
9459                 && (mViewFlags & ENABLED_MASK) == ENABLED
9460                 && li.mOnHoverListener.onHover(this, event)) {
9461             return true;
9462         }
9463 
9464         return onHoverEvent(event);
9465     }
9466 
9467     /**
9468      * Returns true if the view has a child to which it has recently sent
9469      * {@link MotionEvent#ACTION_HOVER_ENTER}.  If this view is hovered and
9470      * it does not have a hovered child, then it must be the innermost hovered view.
9471      * @hide
9472      */
9473     protected boolean hasHoveredChild() {
9474         return false;
9475     }
9476 
9477     /**
9478      * Dispatch a generic motion event to the view under the first pointer.
9479      * <p>
9480      * Do not call this method directly.
9481      * Call {@link #dispatchGenericMotionEvent(MotionEvent)} instead.
9482      * </p>
9483      *
9484      * @param event The motion event to be dispatched.
9485      * @return True if the event was handled by the view, false otherwise.
9486      */
9487     protected boolean dispatchGenericPointerEvent(MotionEvent event) {
9488         return false;
9489     }
9490 
9491     /**
9492      * Dispatch a generic motion event to the currently focused view.
9493      * <p>
9494      * Do not call this method directly.
9495      * Call {@link #dispatchGenericMotionEvent(MotionEvent)} instead.
9496      * </p>
9497      *
9498      * @param event The motion event to be dispatched.
9499      * @return True if the event was handled by the view, false otherwise.
9500      */
9501     protected boolean dispatchGenericFocusedEvent(MotionEvent event) {
9502         return false;
9503     }
9504 
9505     /**
9506      * Dispatch a pointer event.
9507      * <p>
9508      * Dispatches touch related pointer events to {@link #onTouchEvent(MotionEvent)} and all
9509      * other events to {@link #onGenericMotionEvent(MotionEvent)}.  This separation of concerns
9510      * reinforces the invariant that {@link #onTouchEvent(MotionEvent)} is really about touches
9511      * and should not be expected to handle other pointing device features.
9512      * </p>
9513      *
9514      * @param event The motion event to be dispatched.
9515      * @return True if the event was handled by the view, false otherwise.
9516      * @hide
9517      */
9518     public final boolean dispatchPointerEvent(MotionEvent event) {
9519         if (event.isTouchEvent()) {
9520             return dispatchTouchEvent(event);
9521         } else {
9522             return dispatchGenericMotionEvent(event);
9523         }
9524     }
9525 
9526     /**
9527      * Called when the window containing this view gains or loses window focus.
9528      * ViewGroups should override to route to their children.
9529      *
9530      * @param hasFocus True if the window containing this view now has focus,
9531      *        false otherwise.
9532      */
9533     public void dispatchWindowFocusChanged(boolean hasFocus) {
9534         onWindowFocusChanged(hasFocus);
9535     }
9536 
9537     /**
9538      * Called when the window containing this view gains or loses focus.  Note
9539      * that this is separate from view focus: to receive key events, both
9540      * your view and its window must have focus.  If a window is displayed
9541      * on top of yours that takes input focus, then your own window will lose
9542      * focus but the view focus will remain unchanged.
9543      *
9544      * @param hasWindowFocus True if the window containing this view now has
9545      *        focus, false otherwise.
9546      */
9547     public void onWindowFocusChanged(boolean hasWindowFocus) {
9548         InputMethodManager imm = InputMethodManager.peekInstance();
9549         if (!hasWindowFocus) {
9550             if (isPressed()) {
9551                 setPressed(false);
9552             }
9553             if (imm != null && (mPrivateFlags & PFLAG_FOCUSED) != 0) {
9554                 imm.focusOut(this);
9555             }
9556             removeLongPressCallback();
9557             removeTapCallback();
9558             onFocusLost();
9559         } else if (imm != null && (mPrivateFlags & PFLAG_FOCUSED) != 0) {
9560             imm.focusIn(this);
9561         }
9562         refreshDrawableState();
9563     }
9564 
9565     /**
9566      * Returns true if this view is in a window that currently has window focus.
9567      * Note that this is not the same as the view itself having focus.
9568      *
9569      * @return True if this view is in a window that currently has window focus.
9570      */
9571     public boolean hasWindowFocus() {
9572         return mAttachInfo != null && mAttachInfo.mHasWindowFocus;
9573     }
9574 
9575     /**
9576      * Dispatch a view visibility change down the view hierarchy.
9577      * ViewGroups should override to route to their children.
9578      * @param changedView The view whose visibility changed. Could be 'this' or
9579      * an ancestor view.
9580      * @param visibility The new visibility of changedView: {@link #VISIBLE},
9581      * {@link #INVISIBLE} or {@link #GONE}.
9582      */
9583     protected void dispatchVisibilityChanged(@NonNull View changedView,
9584             @Visibility int visibility) {
9585         onVisibilityChanged(changedView, visibility);
9586     }
9587 
9588     /**
9589      * Called when the visibility of the view or an ancestor of the view has
9590      * changed.
9591      *
9592      * @param changedView The view whose visibility changed. May be
9593      *                    {@code this} or an ancestor view.
9594      * @param visibility The new visibility, one of {@link #VISIBLE},
9595      *                   {@link #INVISIBLE} or {@link #GONE}.
9596      */
9597     protected void onVisibilityChanged(@NonNull View changedView, @Visibility int visibility) {
9598         final boolean visible = visibility == VISIBLE && getVisibility() == VISIBLE;
9599         if (visible && mAttachInfo != null) {
9600             initialAwakenScrollBars();
9601         }
9602 
9603         final Drawable dr = mBackground;
9604         if (dr != null && visible != dr.isVisible()) {
9605             dr.setVisible(visible, false);
9606         }
9607         final Drawable fg = mForegroundInfo != null ? mForegroundInfo.mDrawable : null;
9608         if (fg != null && visible != fg.isVisible()) {
9609             fg.setVisible(visible, false);
9610         }
9611     }
9612 
9613     /**
9614      * Dispatch a hint about whether this view is displayed. For instance, when
9615      * a View moves out of the screen, it might receives a display hint indicating
9616      * the view is not displayed. Applications should not <em>rely</em> on this hint
9617      * as there is no guarantee that they will receive one.
9618      *
9619      * @param hint A hint about whether or not this view is displayed:
9620      * {@link #VISIBLE} or {@link #INVISIBLE}.
9621      */
9622     public void dispatchDisplayHint(@Visibility int hint) {
9623         onDisplayHint(hint);
9624     }
9625 
9626     /**
9627      * Gives this view a hint about whether is displayed or not. For instance, when
9628      * a View moves out of the screen, it might receives a display hint indicating
9629      * the view is not displayed. Applications should not <em>rely</em> on this hint
9630      * as there is no guarantee that they will receive one.
9631      *
9632      * @param hint A hint about whether or not this view is displayed:
9633      * {@link #VISIBLE} or {@link #INVISIBLE}.
9634      */
9635     protected void onDisplayHint(@Visibility int hint) {
9636     }
9637 
9638     /**
9639      * Dispatch a window visibility change down the view hierarchy.
9640      * ViewGroups should override to route to their children.
9641      *
9642      * @param visibility The new visibility of the window.
9643      *
9644      * @see #onWindowVisibilityChanged(int)
9645      */
9646     public void dispatchWindowVisibilityChanged(@Visibility int visibility) {
9647         onWindowVisibilityChanged(visibility);
9648     }
9649 
9650     /**
9651      * Called when the window containing has change its visibility
9652      * (between {@link #GONE}, {@link #INVISIBLE}, and {@link #VISIBLE}).  Note
9653      * that this tells you whether or not your window is being made visible
9654      * to the window manager; this does <em>not</em> tell you whether or not
9655      * your window is obscured by other windows on the screen, even if it
9656      * is itself visible.
9657      *
9658      * @param visibility The new visibility of the window.
9659      */
9660     protected void onWindowVisibilityChanged(@Visibility int visibility) {
9661         if (visibility == VISIBLE) {
9662             initialAwakenScrollBars();
9663         }
9664     }
9665 
9666     /**
9667      * Returns the current visibility of the window this view is attached to
9668      * (either {@link #GONE}, {@link #INVISIBLE}, or {@link #VISIBLE}).
9669      *
9670      * @return Returns the current visibility of the view's window.
9671      */
9672     @Visibility
9673     public int getWindowVisibility() {
9674         return mAttachInfo != null ? mAttachInfo.mWindowVisibility : GONE;
9675     }
9676 
9677     /**
9678      * Retrieve the overall visible display size in which the window this view is
9679      * attached to has been positioned in.  This takes into account screen
9680      * decorations above the window, for both cases where the window itself
9681      * is being position inside of them or the window is being placed under
9682      * then and covered insets are used for the window to position its content
9683      * inside.  In effect, this tells you the available area where content can
9684      * be placed and remain visible to users.
9685      *
9686      * <p>This function requires an IPC back to the window manager to retrieve
9687      * the requested information, so should not be used in performance critical
9688      * code like drawing.
9689      *
9690      * @param outRect Filled in with the visible display frame.  If the view
9691      * is not attached to a window, this is simply the raw display size.
9692      */
9693     public void getWindowVisibleDisplayFrame(Rect outRect) {
9694         if (mAttachInfo != null) {
9695             try {
9696                 mAttachInfo.mSession.getDisplayFrame(mAttachInfo.mWindow, outRect);
9697             } catch (RemoteException e) {
9698                 return;
9699             }
9700             // XXX This is really broken, and probably all needs to be done
9701             // in the window manager, and we need to know more about whether
9702             // we want the area behind or in front of the IME.
9703             final Rect insets = mAttachInfo.mVisibleInsets;
9704             outRect.left += insets.left;
9705             outRect.top += insets.top;
9706             outRect.right -= insets.right;
9707             outRect.bottom -= insets.bottom;
9708             return;
9709         }
9710         // The view is not attached to a display so we don't have a context.
9711         // Make a best guess about the display size.
9712         Display d = DisplayManagerGlobal.getInstance().getRealDisplay(Display.DEFAULT_DISPLAY);
9713         d.getRectSize(outRect);
9714     }
9715 
9716     /**
9717      * Dispatch a notification about a resource configuration change down
9718      * the view hierarchy.
9719      * ViewGroups should override to route to their children.
9720      *
9721      * @param newConfig The new resource configuration.
9722      *
9723      * @see #onConfigurationChanged(android.content.res.Configuration)
9724      */
9725     public void dispatchConfigurationChanged(Configuration newConfig) {
9726         onConfigurationChanged(newConfig);
9727     }
9728 
9729     /**
9730      * Called when the current configuration of the resources being used
9731      * by the application have changed.  You can use this to decide when
9732      * to reload resources that can changed based on orientation and other
9733      * configuration characteristics.  You only need to use this if you are
9734      * not relying on the normal {@link android.app.Activity} mechanism of
9735      * recreating the activity instance upon a configuration change.
9736      *
9737      * @param newConfig The new resource configuration.
9738      */
9739     protected void onConfigurationChanged(Configuration newConfig) {
9740     }
9741 
9742     /**
9743      * Private function to aggregate all per-view attributes in to the view
9744      * root.
9745      */
9746     void dispatchCollectViewAttributes(AttachInfo attachInfo, int visibility) {
9747         performCollectViewAttributes(attachInfo, visibility);
9748     }
9749 
9750     void performCollectViewAttributes(AttachInfo attachInfo, int visibility) {
9751         if ((visibility & VISIBILITY_MASK) == VISIBLE) {
9752             if ((mViewFlags & KEEP_SCREEN_ON) == KEEP_SCREEN_ON) {
9753                 attachInfo.mKeepScreenOn = true;
9754             }
9755             attachInfo.mSystemUiVisibility |= mSystemUiVisibility;
9756             ListenerInfo li = mListenerInfo;
9757             if (li != null && li.mOnSystemUiVisibilityChangeListener != null) {
9758                 attachInfo.mHasSystemUiListeners = true;
9759             }
9760         }
9761     }
9762 
9763     void needGlobalAttributesUpdate(boolean force) {
9764         final AttachInfo ai = mAttachInfo;
9765         if (ai != null && !ai.mRecomputeGlobalAttributes) {
9766             if (force || ai.mKeepScreenOn || (ai.mSystemUiVisibility != 0)
9767                     || ai.mHasSystemUiListeners) {
9768                 ai.mRecomputeGlobalAttributes = true;
9769             }
9770         }
9771     }
9772 
9773     /**
9774      * Returns whether the device is currently in touch mode.  Touch mode is entered
9775      * once the user begins interacting with the device by touch, and affects various
9776      * things like whether focus is always visible to the user.
9777      *
9778      * @return Whether the device is in touch mode.
9779      */
9780     @ViewDebug.ExportedProperty
9781     public boolean isInTouchMode() {
9782         if (mAttachInfo != null) {
9783             return mAttachInfo.mInTouchMode;
9784         } else {
9785             return ViewRootImpl.isInTouchMode();
9786         }
9787     }
9788 
9789     /**
9790      * Returns the context the view is running in, through which it can
9791      * access the current theme, resources, etc.
9792      *
9793      * @return The view's Context.
9794      */
9795     @ViewDebug.CapturedViewProperty
9796     public final Context getContext() {
9797         return mContext;
9798     }
9799 
9800     /**
9801      * Handle a key event before it is processed by any input method
9802      * associated with the view hierarchy.  This can be used to intercept
9803      * key events in special situations before the IME consumes them; a
9804      * typical example would be handling the BACK key to update the application's
9805      * UI instead of allowing the IME to see it and close itself.
9806      *
9807      * @param keyCode The value in event.getKeyCode().
9808      * @param event Description of the key event.
9809      * @return If you handled the event, return true. If you want to allow the
9810      *         event to be handled by the next receiver, return false.
9811      */
9812     public boolean onKeyPreIme(int keyCode, KeyEvent event) {
9813         return false;
9814     }
9815 
9816     /**
9817      * Default implementation of {@link KeyEvent.Callback#onKeyDown(int, KeyEvent)
9818      * KeyEvent.Callback.onKeyDown()}: perform press of the view
9819      * when {@link KeyEvent#KEYCODE_DPAD_CENTER} or {@link KeyEvent#KEYCODE_ENTER}
9820      * is released, if the view is enabled and clickable.
9821      *
9822      * <p>Key presses in software keyboards will generally NOT trigger this listener,
9823      * although some may elect to do so in some situations. Do not rely on this to
9824      * catch software key presses.
9825      *
9826      * @param keyCode A key code that represents the button pressed, from
9827      *                {@link android.view.KeyEvent}.
9828      * @param event   The KeyEvent object that defines the button action.
9829      */
9830     public boolean onKeyDown(int keyCode, KeyEvent event) {
9831         boolean result = false;
9832 
9833         if (KeyEvent.isConfirmKey(keyCode)) {
9834             if ((mViewFlags & ENABLED_MASK) == DISABLED) {
9835                 return true;
9836             }
9837             // Long clickable items don't necessarily have to be clickable
9838             if (((mViewFlags & CLICKABLE) == CLICKABLE ||
9839                     (mViewFlags & LONG_CLICKABLE) == LONG_CLICKABLE) &&
9840                     (event.getRepeatCount() == 0)) {
9841                 setPressed(true);
9842                 checkForLongClick(0);
9843                 return true;
9844             }
9845         }
9846         return result;
9847     }
9848 
9849     /**
9850      * Default implementation of {@link KeyEvent.Callback#onKeyLongPress(int, KeyEvent)
9851      * KeyEvent.Callback.onKeyLongPress()}: always returns false (doesn't handle
9852      * the event).
9853      * <p>Key presses in software keyboards will generally NOT trigger this listener,
9854      * although some may elect to do so in some situations. Do not rely on this to
9855      * catch software key presses.
9856      */
9857     public boolean onKeyLongPress(int keyCode, KeyEvent event) {
9858         return false;
9859     }
9860 
9861     /**
9862      * Default implementation of {@link KeyEvent.Callback#onKeyUp(int, KeyEvent)
9863      * KeyEvent.Callback.onKeyUp()}: perform clicking of the view
9864      * when {@link KeyEvent#KEYCODE_DPAD_CENTER} or
9865      * {@link KeyEvent#KEYCODE_ENTER} is released.
9866      * <p>Key presses in software keyboards will generally NOT trigger this listener,
9867      * although some may elect to do so in some situations. Do not rely on this to
9868      * catch software key presses.
9869      *
9870      * @param keyCode A key code that represents the button pressed, from
9871      *                {@link android.view.KeyEvent}.
9872      * @param event   The KeyEvent object that defines the button action.
9873      */
9874     public boolean onKeyUp(int keyCode, KeyEvent event) {
9875         if (KeyEvent.isConfirmKey(keyCode)) {
9876             if ((mViewFlags & ENABLED_MASK) == DISABLED) {
9877                 return true;
9878             }
9879             if ((mViewFlags & CLICKABLE) == CLICKABLE && isPressed()) {
9880                 setPressed(false);
9881 
9882                 if (!mHasPerformedLongPress) {
9883                     // This is a tap, so remove the longpress check
9884                     removeLongPressCallback();
9885                     return performClick();
9886                 }
9887             }
9888         }
9889         return false;
9890     }
9891 
9892     /**
9893      * Default implementation of {@link KeyEvent.Callback#onKeyMultiple(int, int, KeyEvent)
9894      * KeyEvent.Callback.onKeyMultiple()}: always returns false (doesn't handle
9895      * the event).
9896      * <p>Key presses in software keyboards will generally NOT trigger this listener,
9897      * although some may elect to do so in some situations. Do not rely on this to
9898      * catch software key presses.
9899      *
9900      * @param keyCode     A key code that represents the button pressed, from
9901      *                    {@link android.view.KeyEvent}.
9902      * @param repeatCount The number of times the action was made.
9903      * @param event       The KeyEvent object that defines the button action.
9904      */
9905     public boolean onKeyMultiple(int keyCode, int repeatCount, KeyEvent event) {
9906         return false;
9907     }
9908 
9909     /**
9910      * Called on the focused view when a key shortcut event is not handled.
9911      * Override this method to implement local key shortcuts for the View.
9912      * Key shortcuts can also be implemented by setting the
9913      * {@link MenuItem#setShortcut(char, char) shortcut} property of menu items.
9914      *
9915      * @param keyCode The value in event.getKeyCode().
9916      * @param event Description of the key event.
9917      * @return If you handled the event, return true. If you want to allow the
9918      *         event to be handled by the next receiver, return false.
9919      */
9920     public boolean onKeyShortcut(int keyCode, KeyEvent event) {
9921         return false;
9922     }
9923 
9924     /**
9925      * Check whether the called view is a text editor, in which case it
9926      * would make sense to automatically display a soft input window for
9927      * it.  Subclasses should override this if they implement
9928      * {@link #onCreateInputConnection(EditorInfo)} to return true if
9929      * a call on that method would return a non-null InputConnection, and
9930      * they are really a first-class editor that the user would normally
9931      * start typing on when the go into a window containing your view.
9932      *
9933      * <p>The default implementation always returns false.  This does
9934      * <em>not</em> mean that its {@link #onCreateInputConnection(EditorInfo)}
9935      * will not be called or the user can not otherwise perform edits on your
9936      * view; it is just a hint to the system that this is not the primary
9937      * purpose of this view.
9938      *
9939      * @return Returns true if this view is a text editor, else false.
9940      */
9941     public boolean onCheckIsTextEditor() {
9942         return false;
9943     }
9944 
9945     /**
9946      * Create a new InputConnection for an InputMethod to interact
9947      * with the view.  The default implementation returns null, since it doesn't
9948      * support input methods.  You can override this to implement such support.
9949      * This is only needed for views that take focus and text input.
9950      *
9951      * <p>When implementing this, you probably also want to implement
9952      * {@link #onCheckIsTextEditor()} to indicate you will return a
9953      * non-null InputConnection.</p>
9954      *
9955      * <p>Also, take good care to fill in the {@link android.view.inputmethod.EditorInfo}
9956      * object correctly and in its entirety, so that the connected IME can rely
9957      * on its values. For example, {@link android.view.inputmethod.EditorInfo#initialSelStart}
9958      * and  {@link android.view.inputmethod.EditorInfo#initialSelEnd} members
9959      * must be filled in with the correct cursor position for IMEs to work correctly
9960      * with your application.</p>
9961      *
9962      * @param outAttrs Fill in with attribute information about the connection.
9963      */
9964     public InputConnection onCreateInputConnection(EditorInfo outAttrs) {
9965         return null;
9966     }
9967 
9968     /**
9969      * Called by the {@link android.view.inputmethod.InputMethodManager}
9970      * when a view who is not the current
9971      * input connection target is trying to make a call on the manager.  The
9972      * default implementation returns false; you can override this to return
9973      * true for certain views if you are performing InputConnection proxying
9974      * to them.
9975      * @param view The View that is making the InputMethodManager call.
9976      * @return Return true to allow the call, false to reject.
9977      */
9978     public boolean checkInputConnectionProxy(View view) {
9979         return false;
9980     }
9981 
9982     /**
9983      * Show the context menu for this view. It is not safe to hold on to the
9984      * menu after returning from this method.
9985      *
9986      * You should normally not overload this method. Overload
9987      * {@link #onCreateContextMenu(ContextMenu)} or define an
9988      * {@link OnCreateContextMenuListener} to add items to the context menu.
9989      *
9990      * @param menu The context menu to populate
9991      */
9992     public void createContextMenu(ContextMenu menu) {
9993         ContextMenuInfo menuInfo = getContextMenuInfo();
9994 
9995         // Sets the current menu info so all items added to menu will have
9996         // my extra info set.
9997         ((MenuBuilder)menu).setCurrentMenuInfo(menuInfo);
9998 
9999         onCreateContextMenu(menu);
10000         ListenerInfo li = mListenerInfo;
10001         if (li != null && li.mOnCreateContextMenuListener != null) {
10002             li.mOnCreateContextMenuListener.onCreateContextMenu(menu, this, menuInfo);
10003         }
10004 
10005         // Clear the extra information so subsequent items that aren't mine don't
10006         // have my extra info.
10007         ((MenuBuilder)menu).setCurrentMenuInfo(null);
10008 
10009         if (mParent != null) {
10010             mParent.createContextMenu(menu);
10011         }
10012     }
10013 
10014     /**
10015      * Views should implement this if they have extra information to associate
10016      * with the context menu. The return result is supplied as a parameter to
10017      * the {@link OnCreateContextMenuListener#onCreateContextMenu(ContextMenu, View, ContextMenuInfo)}
10018      * callback.
10019      *
10020      * @return Extra information about the item for which the context menu
10021      *         should be shown. This information will vary across different
10022      *         subclasses of View.
10023      */
10024     protected ContextMenuInfo getContextMenuInfo() {
10025         return null;
10026     }
10027 
10028     /**
10029      * Views should implement this if the view itself is going to add items to
10030      * the context menu.
10031      *
10032      * @param menu the context menu to populate
10033      */
10034     protected void onCreateContextMenu(ContextMenu menu) {
10035     }
10036 
10037     /**
10038      * Implement this method to handle trackball motion events.  The
10039      * <em>relative</em> movement of the trackball since the last event
10040      * can be retrieve with {@link MotionEvent#getX MotionEvent.getX()} and
10041      * {@link MotionEvent#getY MotionEvent.getY()}.  These are normalized so
10042      * that a movement of 1 corresponds to the user pressing one DPAD key (so
10043      * they will often be fractional values, representing the more fine-grained
10044      * movement information available from a trackball).
10045      *
10046      * @param event The motion event.
10047      * @return True if the event was handled, false otherwise.
10048      */
10049     public boolean onTrackballEvent(MotionEvent event) {
10050         return false;
10051     }
10052 
10053     /**
10054      * Implement this method to handle generic motion events.
10055      * <p>
10056      * Generic motion events describe joystick movements, mouse hovers, track pad
10057      * touches, scroll wheel movements and other input events.  The
10058      * {@link MotionEvent#getSource() source} of the motion event specifies
10059      * the class of input that was received.  Implementations of this method
10060      * must examine the bits in the source before processing the event.
10061      * The following code example shows how this is done.
10062      * </p><p>
10063      * Generic motion events with source class {@link InputDevice#SOURCE_CLASS_POINTER}
10064      * are delivered to the view under the pointer.  All other generic motion events are
10065      * delivered to the focused view.
10066      * </p>
10067      * <pre> public boolean onGenericMotionEvent(MotionEvent event) {
10068      *     if (event.isFromSource(InputDevice.SOURCE_CLASS_JOYSTICK)) {
10069      *         if (event.getAction() == MotionEvent.ACTION_MOVE) {
10070      *             // process the joystick movement...
10071      *             return true;
10072      *         }
10073      *     }
10074      *     if (event.isFromSource(InputDevice.SOURCE_CLASS_POINTER)) {
10075      *         switch (event.getAction()) {
10076      *             case MotionEvent.ACTION_HOVER_MOVE:
10077      *                 // process the mouse hover movement...
10078      *                 return true;
10079      *             case MotionEvent.ACTION_SCROLL:
10080      *                 // process the scroll wheel movement...
10081      *                 return true;
10082      *         }
10083      *     }
10084      *     return super.onGenericMotionEvent(event);
10085      * }</pre>
10086      *
10087      * @param event The generic motion event being processed.
10088      * @return True if the event was handled, false otherwise.
10089      */
10090     public boolean onGenericMotionEvent(MotionEvent event) {
10091         return false;
10092     }
10093 
10094     /**
10095      * Implement this method to handle hover events.
10096      * <p>
10097      * This method is called whenever a pointer is hovering into, over, or out of the
10098      * bounds of a view and the view is not currently being touched.
10099      * Hover events are represented as pointer events with action
10100      * {@link MotionEvent#ACTION_HOVER_ENTER}, {@link MotionEvent#ACTION_HOVER_MOVE},
10101      * or {@link MotionEvent#ACTION_HOVER_EXIT}.
10102      * </p>
10103      * <ul>
10104      * <li>The view receives a hover event with action {@link MotionEvent#ACTION_HOVER_ENTER}
10105      * when the pointer enters the bounds of the view.</li>
10106      * <li>The view receives a hover event with action {@link MotionEvent#ACTION_HOVER_MOVE}
10107      * when the pointer has already entered the bounds of the view and has moved.</li>
10108      * <li>The view receives a hover event with action {@link MotionEvent#ACTION_HOVER_EXIT}
10109      * when the pointer has exited the bounds of the view or when the pointer is
10110      * about to go down due to a button click, tap, or similar user action that
10111      * causes the view to be touched.</li>
10112      * </ul>
10113      * <p>
10114      * The view should implement this method to return true to indicate that it is
10115      * handling the hover event, such as by changing its drawable state.
10116      * </p><p>
10117      * The default implementation calls {@link #setHovered} to update the hovered state
10118      * of the view when a hover enter or hover exit event is received, if the view
10119      * is enabled and is clickable.  The default implementation also sends hover
10120      * accessibility events.
10121      * </p>
10122      *
10123      * @param event The motion event that describes the hover.
10124      * @return True if the view handled the hover event.
10125      *
10126      * @see #isHovered
10127      * @see #setHovered
10128      * @see #onHoverChanged
10129      */
10130     public boolean onHoverEvent(MotionEvent event) {
10131         // The root view may receive hover (or touch) events that are outside the bounds of
10132         // the window.  This code ensures that we only send accessibility events for
10133         // hovers that are actually within the bounds of the root view.
10134         final int action = event.getActionMasked();
10135         if (!mSendingHoverAccessibilityEvents) {
10136             if ((action == MotionEvent.ACTION_HOVER_ENTER
10137                     || action == MotionEvent.ACTION_HOVER_MOVE)
10138                     && !hasHoveredChild()
10139                     && pointInView(event.getX(), event.getY())) {
10140                 sendAccessibilityHoverEvent(AccessibilityEvent.TYPE_VIEW_HOVER_ENTER);
10141                 mSendingHoverAccessibilityEvents = true;
10142             }
10143         } else {
10144             if (action == MotionEvent.ACTION_HOVER_EXIT
10145                     || (action == MotionEvent.ACTION_MOVE
10146                             && !pointInView(event.getX(), event.getY()))) {
10147                 mSendingHoverAccessibilityEvents = false;
10148                 sendAccessibilityHoverEvent(AccessibilityEvent.TYPE_VIEW_HOVER_EXIT);
10149             }
10150         }
10151 
10152         if (isHoverable()) {
10153             switch (action) {
10154                 case MotionEvent.ACTION_HOVER_ENTER:
10155                     setHovered(true);
10156                     break;
10157                 case MotionEvent.ACTION_HOVER_EXIT:
10158                     setHovered(false);
10159                     break;
10160             }
10161 
10162             // Dispatch the event to onGenericMotionEvent before returning true.
10163             // This is to provide compatibility with existing applications that
10164             // handled HOVER_MOVE events in onGenericMotionEvent and that would
10165             // break because of the new default handling for hoverable views
10166             // in onHoverEvent.
10167             // Note that onGenericMotionEvent will be called by default when
10168             // onHoverEvent returns false (refer to dispatchGenericMotionEvent).
10169             dispatchGenericMotionEventInternal(event);
10170             // The event was already handled by calling setHovered(), so always
10171             // return true.
10172             return true;
10173         }
10174 
10175         return false;
10176     }
10177 
10178     /**
10179      * Returns true if the view should handle {@link #onHoverEvent}
10180      * by calling {@link #setHovered} to change its hovered state.
10181      *
10182      * @return True if the view is hoverable.
10183      */
10184     private boolean isHoverable() {
10185         final int viewFlags = mViewFlags;
10186         if ((viewFlags & ENABLED_MASK) == DISABLED) {
10187             return false;
10188         }
10189 
10190         return (viewFlags & CLICKABLE) == CLICKABLE
10191                 || (viewFlags & LONG_CLICKABLE) == LONG_CLICKABLE
10192                 || (viewFlags & CONTEXT_CLICKABLE) == CONTEXT_CLICKABLE;
10193     }
10194 
10195     /**
10196      * Returns true if the view is currently hovered.
10197      *
10198      * @return True if the view is currently hovered.
10199      *
10200      * @see #setHovered
10201      * @see #onHoverChanged
10202      */
10203     @ViewDebug.ExportedProperty
10204     public boolean isHovered() {
10205         return (mPrivateFlags & PFLAG_HOVERED) != 0;
10206     }
10207 
10208     /**
10209      * Sets whether the view is currently hovered.
10210      * <p>
10211      * Calling this method also changes the drawable state of the view.  This
10212      * enables the view to react to hover by using different drawable resources
10213      * to change its appearance.
10214      * </p><p>
10215      * The {@link #onHoverChanged} method is called when the hovered state changes.
10216      * </p>
10217      *
10218      * @param hovered True if the view is hovered.
10219      *
10220      * @see #isHovered
10221      * @see #onHoverChanged
10222      */
10223     public void setHovered(boolean hovered) {
10224         if (hovered) {
10225             if ((mPrivateFlags & PFLAG_HOVERED) == 0) {
10226                 mPrivateFlags |= PFLAG_HOVERED;
10227                 refreshDrawableState();
10228                 onHoverChanged(true);
10229             }
10230         } else {
10231             if ((mPrivateFlags & PFLAG_HOVERED) != 0) {
10232                 mPrivateFlags &= ~PFLAG_HOVERED;
10233                 refreshDrawableState();
10234                 onHoverChanged(false);
10235             }
10236         }
10237     }
10238 
10239     /**
10240      * Implement this method to handle hover state changes.
10241      * <p>
10242      * This method is called whenever the hover state changes as a result of a
10243      * call to {@link #setHovered}.
10244      * </p>
10245      *
10246      * @param hovered The current hover state, as returned by {@link #isHovered}.
10247      *
10248      * @see #isHovered
10249      * @see #setHovered
10250      */
10251     public void onHoverChanged(boolean hovered) {
10252     }
10253 
10254     /**
10255      * Implement this method to handle touch screen motion events.
10256      * <p>
10257      * If this method is used to detect click actions, it is recommended that
10258      * the actions be performed by implementing and calling
10259      * {@link #performClick()}. This will ensure consistent system behavior,
10260      * including:
10261      * <ul>
10262      * <li>obeying click sound preferences
10263      * <li>dispatching OnClickListener calls
10264      * <li>handling {@link AccessibilityNodeInfo#ACTION_CLICK ACTION_CLICK} when
10265      * accessibility features are enabled
10266      * </ul>
10267      *
10268      * @param event The motion event.
10269      * @return True if the event was handled, false otherwise.
10270      */
10271     public boolean onTouchEvent(MotionEvent event) {
10272         final float x = event.getX();
10273         final float y = event.getY();
10274         final int viewFlags = mViewFlags;
10275         final int action = event.getAction();
10276 
10277         if ((viewFlags & ENABLED_MASK) == DISABLED) {
10278             if (action == MotionEvent.ACTION_UP && (mPrivateFlags & PFLAG_PRESSED) != 0) {
10279                 setPressed(false);
10280             }
10281             // A disabled view that is clickable still consumes the touch
10282             // events, it just doesn't respond to them.
10283             return (((viewFlags & CLICKABLE) == CLICKABLE
10284                     || (viewFlags & LONG_CLICKABLE) == LONG_CLICKABLE)
10285                     || (viewFlags & CONTEXT_CLICKABLE) == CONTEXT_CLICKABLE);
10286         }
10287 
10288         if (mTouchDelegate != null) {
10289             if (mTouchDelegate.onTouchEvent(event)) {
10290                 return true;
10291             }
10292         }
10293 
10294         if (((viewFlags & CLICKABLE) == CLICKABLE ||
10295                 (viewFlags & LONG_CLICKABLE) == LONG_CLICKABLE) ||
10296                 (viewFlags & CONTEXT_CLICKABLE) == CONTEXT_CLICKABLE) {
10297             switch (action) {
10298                 case MotionEvent.ACTION_UP:
10299                     boolean prepressed = (mPrivateFlags & PFLAG_PREPRESSED) != 0;
10300                     if ((mPrivateFlags & PFLAG_PRESSED) != 0 || prepressed) {
10301                         // take focus if we don't have it already and we should in
10302                         // touch mode.
10303                         boolean focusTaken = false;
10304                         if (isFocusable() && isFocusableInTouchMode() && !isFocused()) {
10305                             focusTaken = requestFocus();
10306                         }
10307 
10308                         if (prepressed) {
10309                             // The button is being released before we actually
10310                             // showed it as pressed.  Make it show the pressed
10311                             // state now (before scheduling the click) to ensure
10312                             // the user sees it.
10313                             setPressed(true, x, y);
10314                        }
10315 
10316                         if (!mHasPerformedLongPress && !mIgnoreNextUpEvent) {
10317                             // This is a tap, so remove the longpress check
10318                             removeLongPressCallback();
10319 
10320                             // Only perform take click actions if we were in the pressed state
10321                             if (!focusTaken) {
10322                                 // Use a Runnable and post this rather than calling
10323                                 // performClick directly. This lets other visual state
10324                                 // of the view update before click actions start.
10325                                 if (mPerformClick == null) {
10326                                     mPerformClick = new PerformClick();
10327                                 }
10328                                 if (!post(mPerformClick)) {
10329                                     performClick();
10330                                 }
10331                             }
10332                         }
10333 
10334                         if (mUnsetPressedState == null) {
10335                             mUnsetPressedState = new UnsetPressedState();
10336                         }
10337 
10338                         if (prepressed) {
10339                             postDelayed(mUnsetPressedState,
10340                                     ViewConfiguration.getPressedStateDuration());
10341                         } else if (!post(mUnsetPressedState)) {
10342                             // If the post failed, unpress right now
10343                             mUnsetPressedState.run();
10344                         }
10345 
10346                         removeTapCallback();
10347                     }
10348                     mIgnoreNextUpEvent = false;
10349                     break;
10350 
10351                 case MotionEvent.ACTION_DOWN:
10352                     mHasPerformedLongPress = false;
10353 
10354                     if (performButtonActionOnTouchDown(event)) {
10355                         break;
10356                     }
10357 
10358                     // Walk up the hierarchy to determine if we're inside a scrolling container.
10359                     boolean isInScrollingContainer = isInScrollingContainer();
10360 
10361                     // For views inside a scrolling container, delay the pressed feedback for
10362                     // a short period in case this is a scroll.
10363                     if (isInScrollingContainer) {
10364                         mPrivateFlags |= PFLAG_PREPRESSED;
10365                         if (mPendingCheckForTap == null) {
10366                             mPendingCheckForTap = new CheckForTap();
10367                         }
10368                         mPendingCheckForTap.x = event.getX();
10369                         mPendingCheckForTap.y = event.getY();
10370                         postDelayed(mPendingCheckForTap, ViewConfiguration.getTapTimeout());
10371                     } else {
10372                         // Not inside a scrolling container, so show the feedback right away
10373                         setPressed(true, x, y);
10374                         checkForLongClick(0);
10375                     }
10376                     break;
10377 
10378                 case MotionEvent.ACTION_CANCEL:
10379                     setPressed(false);
10380                     removeTapCallback();
10381                     removeLongPressCallback();
10382                     mInContextButtonPress = false;
10383                     mHasPerformedLongPress = false;
10384                     mIgnoreNextUpEvent = false;
10385                     break;
10386 
10387                 case MotionEvent.ACTION_MOVE:
10388                     drawableHotspotChanged(x, y);
10389 
10390                     // Be lenient about moving outside of buttons
10391                     if (!pointInView(x, y, mTouchSlop)) {
10392                         // Outside button
10393                         removeTapCallback();
10394                         if ((mPrivateFlags & PFLAG_PRESSED) != 0) {
10395                             // Remove any future long press/tap checks
10396                             removeLongPressCallback();
10397 
10398                             setPressed(false);
10399                         }
10400                     }
10401                     break;
10402             }
10403 
10404             return true;
10405         }
10406 
10407         return false;
10408     }
10409 
10410     /**
10411      * @hide
10412      */
10413     public boolean isInScrollingContainer() {
10414         ViewParent p = getParent();
10415         while (p != null && p instanceof ViewGroup) {
10416             if (((ViewGroup) p).shouldDelayChildPressedState()) {
10417                 return true;
10418             }
10419             p = p.getParent();
10420         }
10421         return false;
10422     }
10423 
10424     /**
10425      * Remove the longpress detection timer.
10426      */
10427     private void removeLongPressCallback() {
10428         if (mPendingCheckForLongPress != null) {
10429           removeCallbacks(mPendingCheckForLongPress);
10430         }
10431     }
10432 
10433     /**
10434      * Remove the pending click action
10435      */
10436     private void removePerformClickCallback() {
10437         if (mPerformClick != null) {
10438             removeCallbacks(mPerformClick);
10439         }
10440     }
10441 
10442     /**
10443      * Remove the prepress detection timer.
10444      */
10445     private void removeUnsetPressCallback() {
10446         if ((mPrivateFlags & PFLAG_PRESSED) != 0 && mUnsetPressedState != null) {
10447             setPressed(false);
10448             removeCallbacks(mUnsetPressedState);
10449         }
10450     }
10451 
10452     /**
10453      * Remove the tap detection timer.
10454      */
10455     private void removeTapCallback() {
10456         if (mPendingCheckForTap != null) {
10457             mPrivateFlags &= ~PFLAG_PREPRESSED;
10458             removeCallbacks(mPendingCheckForTap);
10459         }
10460     }
10461 
10462     /**
10463      * Cancels a pending long press.  Your subclass can use this if you
10464      * want the context menu to come up if the user presses and holds
10465      * at the same place, but you don't want it to come up if they press
10466      * and then move around enough to cause scrolling.
10467      */
10468     public void cancelLongPress() {
10469         removeLongPressCallback();
10470 
10471         /*
10472          * The prepressed state handled by the tap callback is a display
10473          * construct, but the tap callback will post a long press callback
10474          * less its own timeout. Remove it here.
10475          */
10476         removeTapCallback();
10477     }
10478 
10479     /**
10480      * Remove the pending callback for sending a
10481      * {@link AccessibilityEvent#TYPE_VIEW_SCROLLED} accessibility event.
10482      */
10483     private void removeSendViewScrolledAccessibilityEventCallback() {
10484         if (mSendViewScrolledAccessibilityEvent != null) {
10485             removeCallbacks(mSendViewScrolledAccessibilityEvent);
10486             mSendViewScrolledAccessibilityEvent.mIsPending = false;
10487         }
10488     }
10489 
10490     /**
10491      * Sets the TouchDelegate for this View.
10492      */
10493     public void setTouchDelegate(TouchDelegate delegate) {
10494         mTouchDelegate = delegate;
10495     }
10496 
10497     /**
10498      * Gets the TouchDelegate for this View.
10499      */
10500     public TouchDelegate getTouchDelegate() {
10501         return mTouchDelegate;
10502     }
10503 
10504     /**
10505      * Request unbuffered dispatch of the given stream of MotionEvents to this View.
10506      *
10507      * Until this View receives a corresponding {@link MotionEvent#ACTION_UP}, ask that the input
10508      * system not batch {@link MotionEvent}s but instead deliver them as soon as they're
10509      * available. This method should only be called for touch events.
10510      *
10511      * <p class="note">This api is not intended for most applications. Buffered dispatch
10512      * provides many of benefits, and just requesting unbuffered dispatch on most MotionEvent
10513      * streams will not improve your input latency. Side effects include: increased latency,
10514      * jittery scrolls and inability to take advantage of system resampling. Talk to your input
10515      * professional to see if {@link #requestUnbufferedDispatch(MotionEvent)} is right for
10516      * you.</p>
10517      */
10518     public final void requestUnbufferedDispatch(MotionEvent event) {
10519         final int action = event.getAction();
10520         if (mAttachInfo == null
10521                 || action != MotionEvent.ACTION_DOWN && action != MotionEvent.ACTION_MOVE
10522                 || !event.isTouchEvent()) {
10523             return;
10524         }
10525         mAttachInfo.mUnbufferedDispatchRequested = true;
10526     }
10527 
10528     /**
10529      * Set flags controlling behavior of this view.
10530      *
10531      * @param flags Constant indicating the value which should be set
10532      * @param mask Constant indicating the bit range that should be changed
10533      */
10534     void setFlags(int flags, int mask) {
10535         final boolean accessibilityEnabled =
10536                 AccessibilityManager.getInstance(mContext).isEnabled();
10537         final boolean oldIncludeForAccessibility = accessibilityEnabled && includeForAccessibility();
10538 
10539         int old = mViewFlags;
10540         mViewFlags = (mViewFlags & ~mask) | (flags & mask);
10541 
10542         int changed = mViewFlags ^ old;
10543         if (changed == 0) {
10544             return;
10545         }
10546         int privateFlags = mPrivateFlags;
10547 
10548         /* Check if the FOCUSABLE bit has changed */
10549         if (((changed & FOCUSABLE_MASK) != 0) &&
10550                 ((privateFlags & PFLAG_HAS_BOUNDS) !=0)) {
10551             if (((old & FOCUSABLE_MASK) == FOCUSABLE)
10552                     && ((privateFlags & PFLAG_FOCUSED) != 0)) {
10553                 /* Give up focus if we are no longer focusable */
10554                 clearFocus();
10555             } else if (((old & FOCUSABLE_MASK) == NOT_FOCUSABLE)
10556                     && ((privateFlags & PFLAG_FOCUSED) == 0)) {
10557                 /*
10558                  * Tell the view system that we are now available to take focus
10559                  * if no one else already has it.
10560                  */
10561                 if (mParent != null) mParent.focusableViewAvailable(this);
10562             }
10563         }
10564 
10565         final int newVisibility = flags & VISIBILITY_MASK;
10566         if (newVisibility == VISIBLE) {
10567             if ((changed & VISIBILITY_MASK) != 0) {
10568                 /*
10569                  * If this view is becoming visible, invalidate it in case it changed while
10570                  * it was not visible. Marking it drawn ensures that the invalidation will
10571                  * go through.
10572                  */
10573                 mPrivateFlags |= PFLAG_DRAWN;
10574                 invalidate(true);
10575 
10576                 needGlobalAttributesUpdate(true);
10577 
10578                 // a view becoming visible is worth notifying the parent
10579                 // about in case nothing has focus.  even if this specific view
10580                 // isn't focusable, it may contain something that is, so let
10581                 // the root view try to give this focus if nothing else does.
10582                 if ((mParent != null) && (mBottom > mTop) && (mRight > mLeft)) {
10583                     mParent.focusableViewAvailable(this);
10584                 }
10585             }
10586         }
10587 
10588         /* Check if the GONE bit has changed */
10589         if ((changed & GONE) != 0) {
10590             needGlobalAttributesUpdate(false);
10591             requestLayout();
10592 
10593             if (((mViewFlags & VISIBILITY_MASK) == GONE)) {
10594                 if (hasFocus()) clearFocus();
10595                 clearAccessibilityFocus();
10596                 destroyDrawingCache();
10597                 if (mParent instanceof View) {
10598                     // GONE views noop invalidation, so invalidate the parent
10599                     ((View) mParent).invalidate(true);
10600                 }
10601                 // Mark the view drawn to ensure that it gets invalidated properly the next
10602                 // time it is visible and gets invalidated
10603                 mPrivateFlags |= PFLAG_DRAWN;
10604             }
10605             if (mAttachInfo != null) {
10606                 mAttachInfo.mViewVisibilityChanged = true;
10607             }
10608         }
10609 
10610         /* Check if the VISIBLE bit has changed */
10611         if ((changed & INVISIBLE) != 0) {
10612             needGlobalAttributesUpdate(false);
10613             /*
10614              * If this view is becoming invisible, set the DRAWN flag so that
10615              * the next invalidate() will not be skipped.
10616              */
10617             mPrivateFlags |= PFLAG_DRAWN;
10618 
10619             if (((mViewFlags & VISIBILITY_MASK) == INVISIBLE)) {
10620                 // root view becoming invisible shouldn't clear focus and accessibility focus
10621                 if (getRootView() != this) {
10622                     if (hasFocus()) clearFocus();
10623                     clearAccessibilityFocus();
10624                 }
10625             }
10626             if (mAttachInfo != null) {
10627                 mAttachInfo.mViewVisibilityChanged = true;
10628             }
10629         }
10630 
10631         if ((changed & VISIBILITY_MASK) != 0) {
10632             // If the view is invisible, cleanup its display list to free up resources
10633             if (newVisibility != VISIBLE && mAttachInfo != null) {
10634                 cleanupDraw();
10635             }
10636 
10637             if (mParent instanceof ViewGroup) {
10638                 ((ViewGroup) mParent).onChildVisibilityChanged(this,
10639                         (changed & VISIBILITY_MASK), newVisibility);
10640                 ((View) mParent).invalidate(true);
10641             } else if (mParent != null) {
10642                 mParent.invalidateChild(this, null);
10643             }
10644 
10645             if (mAttachInfo != null) {
10646                 dispatchVisibilityChanged(this, newVisibility);
10647                 notifySubtreeAccessibilityStateChangedIfNeeded();
10648             }
10649         }
10650 
10651         if ((changed & WILL_NOT_CACHE_DRAWING) != 0) {
10652             destroyDrawingCache();
10653         }
10654 
10655         if ((changed & DRAWING_CACHE_ENABLED) != 0) {
10656             destroyDrawingCache();
10657             mPrivateFlags &= ~PFLAG_DRAWING_CACHE_VALID;
10658             invalidateParentCaches();
10659         }
10660 
10661         if ((changed & DRAWING_CACHE_QUALITY_MASK) != 0) {
10662             destroyDrawingCache();
10663             mPrivateFlags &= ~PFLAG_DRAWING_CACHE_VALID;
10664         }
10665 
10666         if ((changed & DRAW_MASK) != 0) {
10667             if ((mViewFlags & WILL_NOT_DRAW) != 0) {
10668                 if (mBackground != null
10669                         || (mForegroundInfo != null && mForegroundInfo.mDrawable != null)) {
10670                     mPrivateFlags &= ~PFLAG_SKIP_DRAW;
10671                 } else {
10672                     mPrivateFlags |= PFLAG_SKIP_DRAW;
10673                 }
10674             } else {
10675                 mPrivateFlags &= ~PFLAG_SKIP_DRAW;
10676             }
10677             requestLayout();
10678             invalidate(true);
10679         }
10680 
10681         if ((changed & KEEP_SCREEN_ON) != 0) {
10682             if (mParent != null && mAttachInfo != null && !mAttachInfo.mRecomputeGlobalAttributes) {
10683                 mParent.recomputeViewAttributes(this);
10684             }
10685         }
10686 
10687         if (accessibilityEnabled) {
10688             if ((changed & FOCUSABLE_MASK) != 0 || (changed & VISIBILITY_MASK) != 0
10689                     || (changed & CLICKABLE) != 0 || (changed & LONG_CLICKABLE) != 0
10690                     || (changed & CONTEXT_CLICKABLE) != 0) {
10691                 if (oldIncludeForAccessibility != includeForAccessibility()) {
10692                     notifySubtreeAccessibilityStateChangedIfNeeded();
10693                 } else {
10694                     notifyViewAccessibilityStateChangedIfNeeded(
10695                             AccessibilityEvent.CONTENT_CHANGE_TYPE_UNDEFINED);
10696                 }
10697             } else if ((changed & ENABLED_MASK) != 0) {
10698                 notifyViewAccessibilityStateChangedIfNeeded(
10699                         AccessibilityEvent.CONTENT_CHANGE_TYPE_UNDEFINED);
10700             }
10701         }
10702     }
10703 
10704     /**
10705      * Change the view's z order in the tree, so it's on top of other sibling
10706      * views. This ordering change may affect layout, if the parent container
10707      * uses an order-dependent layout scheme (e.g., LinearLayout). Prior
10708      * to {@link android.os.Build.VERSION_CODES#KITKAT} this
10709      * method should be followed by calls to {@link #requestLayout()} and
10710      * {@link View#invalidate()} on the view's parent to force the parent to redraw
10711      * with the new child ordering.
10712      *
10713      * @see ViewGroup#bringChildToFront(View)
10714      */
10715     public void bringToFront() {
10716         if (mParent != null) {
10717             mParent.bringChildToFront(this);
10718         }
10719     }
10720 
10721     /**
10722      * This is called in response to an internal scroll in this view (i.e., the
10723      * view scrolled its own contents). This is typically as a result of
10724      * {@link #scrollBy(int, int)} or {@link #scrollTo(int, int)} having been
10725      * called.
10726      *
10727      * @param l Current horizontal scroll origin.
10728      * @param t Current vertical scroll origin.
10729      * @param oldl Previous horizontal scroll origin.
10730      * @param oldt Previous vertical scroll origin.
10731      */
10732     protected void onScrollChanged(int l, int t, int oldl, int oldt) {
10733         notifySubtreeAccessibilityStateChangedIfNeeded();
10734 
10735         if (AccessibilityManager.getInstance(mContext).isEnabled()) {
10736             postSendViewScrolledAccessibilityEventCallback();
10737         }
10738 
10739         mBackgroundSizeChanged = true;
10740         if (mForegroundInfo != null) {
10741             mForegroundInfo.mBoundsChanged = true;
10742         }
10743 
10744         final AttachInfo ai = mAttachInfo;
10745         if (ai != null) {
10746             ai.mViewScrollChanged = true;
10747         }
10748 
10749         if (mListenerInfo != null && mListenerInfo.mOnScrollChangeListener != null) {
10750             mListenerInfo.mOnScrollChangeListener.onScrollChange(this, l, t, oldl, oldt);
10751         }
10752     }
10753 
10754     /**
10755      * Interface definition for a callback to be invoked when the scroll
10756      * X or Y positions of a view change.
10757      * <p>
10758      * <b>Note:</b> Some views handle scrolling independently from View and may
10759      * have their own separate listeners for scroll-type events. For example,
10760      * {@link android.widget.ListView ListView} allows clients to register an
10761      * {@link android.widget.ListView#setOnScrollListener(android.widget.AbsListView.OnScrollListener) AbsListView.OnScrollListener}
10762      * to listen for changes in list scroll position.
10763      *
10764      * @see #setOnScrollChangeListener(View.OnScrollChangeListener)
10765      */
10766     public interface OnScrollChangeListener {
10767         /**
10768          * Called when the scroll position of a view changes.
10769          *
10770          * @param v The view whose scroll position has changed.
10771          * @param scrollX Current horizontal scroll origin.
10772          * @param scrollY Current vertical scroll origin.
10773          * @param oldScrollX Previous horizontal scroll origin.
10774          * @param oldScrollY Previous vertical scroll origin.
10775          */
10776         void onScrollChange(View v, int scrollX, int scrollY, int oldScrollX, int oldScrollY);
10777     }
10778 
10779     /**
10780      * Interface definition for a callback to be invoked when the layout bounds of a view
10781      * changes due to layout processing.
10782      */
10783     public interface OnLayoutChangeListener {
10784         /**
10785          * Called when the layout bounds of a view changes due to layout processing.
10786          *
10787          * @param v The view whose bounds have changed.
10788          * @param left The new value of the view's left property.
10789          * @param top The new value of the view's top property.
10790          * @param right The new value of the view's right property.
10791          * @param bottom The new value of the view's bottom property.
10792          * @param oldLeft The previous value of the view's left property.
10793          * @param oldTop The previous value of the view's top property.
10794          * @param oldRight The previous value of the view's right property.
10795          * @param oldBottom The previous value of the view's bottom property.
10796          */
10797         void onLayoutChange(View v, int left, int top, int right, int bottom,
10798             int oldLeft, int oldTop, int oldRight, int oldBottom);
10799     }
10800 
10801     /**
10802      * This is called during layout when the size of this view has changed. If
10803      * you were just added to the view hierarchy, you're called with the old
10804      * values of 0.
10805      *
10806      * @param w Current width of this view.
10807      * @param h Current height of this view.
10808      * @param oldw Old width of this view.
10809      * @param oldh Old height of this view.
10810      */
10811     protected void onSizeChanged(int w, int h, int oldw, int oldh) {
10812     }
10813 
10814     /**
10815      * Called by draw to draw the child views. This may be overridden
10816      * by derived classes to gain control just before its children are drawn
10817      * (but after its own view has been drawn).
10818      * @param canvas the canvas on which to draw the view
10819      */
10820     protected void dispatchDraw(Canvas canvas) {
10821 
10822     }
10823 
10824     /**
10825      * Gets the parent of this view. Note that the parent is a
10826      * ViewParent and not necessarily a View.
10827      *
10828      * @return Parent of this view.
10829      */
10830     public final ViewParent getParent() {
10831         return mParent;
10832     }
10833 
10834     /**
10835      * Set the horizontal scrolled position of your view. This will cause a call to
10836      * {@link #onScrollChanged(int, int, int, int)} and the view will be
10837      * invalidated.
10838      * @param value the x position to scroll to
10839      */
10840     public void setScrollX(int value) {
10841         scrollTo(value, mScrollY);
10842     }
10843 
10844     /**
10845      * Set the vertical scrolled position of your view. This will cause a call to
10846      * {@link #onScrollChanged(int, int, int, int)} and the view will be
10847      * invalidated.
10848      * @param value the y position to scroll to
10849      */
10850     public void setScrollY(int value) {
10851         scrollTo(mScrollX, value);
10852     }
10853 
10854     /**
10855      * Return the scrolled left position of this view. This is the left edge of
10856      * the displayed part of your view. You do not need to draw any pixels
10857      * farther left, since those are outside of the frame of your view on
10858      * screen.
10859      *
10860      * @return The left edge of the displayed part of your view, in pixels.
10861      */
10862     public final int getScrollX() {
10863         return mScrollX;
10864     }
10865 
10866     /**
10867      * Return the scrolled top position of this view. This is the top edge of
10868      * the displayed part of your view. You do not need to draw any pixels above
10869      * it, since those are outside of the frame of your view on screen.
10870      *
10871      * @return The top edge of the displayed part of your view, in pixels.
10872      */
10873     public final int getScrollY() {
10874         return mScrollY;
10875     }
10876 
10877     /**
10878      * Return the width of the your view.
10879      *
10880      * @return The width of your view, in pixels.
10881      */
10882     @ViewDebug.ExportedProperty(category = "layout")
10883     public final int getWidth() {
10884         return mRight - mLeft;
10885     }
10886 
10887     /**
10888      * Return the height of your view.
10889      *
10890      * @return The height of your view, in pixels.
10891      */
10892     @ViewDebug.ExportedProperty(category = "layout")
10893     public final int getHeight() {
10894         return mBottom - mTop;
10895     }
10896 
10897     /**
10898      * Return the visible drawing bounds of your view. Fills in the output
10899      * rectangle with the values from getScrollX(), getScrollY(),
10900      * getWidth(), and getHeight(). These bounds do not account for any
10901      * transformation properties currently set on the view, such as
10902      * {@link #setScaleX(float)} or {@link #setRotation(float)}.
10903      *
10904      * @param outRect The (scrolled) drawing bounds of the view.
10905      */
10906     public void getDrawingRect(Rect outRect) {
10907         outRect.left = mScrollX;
10908         outRect.top = mScrollY;
10909         outRect.right = mScrollX + (mRight - mLeft);
10910         outRect.bottom = mScrollY + (mBottom - mTop);
10911     }
10912 
10913     /**
10914      * Like {@link #getMeasuredWidthAndState()}, but only returns the
10915      * raw width component (that is the result is masked by
10916      * {@link #MEASURED_SIZE_MASK}).
10917      *
10918      * @return The raw measured width of this view.
10919      */
10920     public final int getMeasuredWidth() {
10921         return mMeasuredWidth & MEASURED_SIZE_MASK;
10922     }
10923 
10924     /**
10925      * Return the full width measurement information for this view as computed
10926      * by the most recent call to {@link #measure(int, int)}.  This result is a bit mask
10927      * as defined by {@link #MEASURED_SIZE_MASK} and {@link #MEASURED_STATE_TOO_SMALL}.
10928      * This should be used during measurement and layout calculations only. Use
10929      * {@link #getWidth()} to see how wide a view is after layout.
10930      *
10931      * @return The measured width of this view as a bit mask.
10932      */
10933     @ViewDebug.ExportedProperty(category = "measurement", flagMapping = {
10934             @ViewDebug.FlagToString(mask = MEASURED_STATE_MASK, equals = MEASURED_STATE_TOO_SMALL,
10935                     name = "MEASURED_STATE_TOO_SMALL"),
10936     })
10937     public final int getMeasuredWidthAndState() {
10938         return mMeasuredWidth;
10939     }
10940 
10941     /**
10942      * Like {@link #getMeasuredHeightAndState()}, but only returns the
10943      * raw width component (that is the result is masked by
10944      * {@link #MEASURED_SIZE_MASK}).
10945      *
10946      * @return The raw measured height of this view.
10947      */
10948     public final int getMeasuredHeight() {
10949         return mMeasuredHeight & MEASURED_SIZE_MASK;
10950     }
10951 
10952     /**
10953      * Return the full height measurement information for this view as computed
10954      * by the most recent call to {@link #measure(int, int)}.  This result is a bit mask
10955      * as defined by {@link #MEASURED_SIZE_MASK} and {@link #MEASURED_STATE_TOO_SMALL}.
10956      * This should be used during measurement and layout calculations only. Use
10957      * {@link #getHeight()} to see how wide a view is after layout.
10958      *
10959      * @return The measured width of this view as a bit mask.
10960      */
10961     @ViewDebug.ExportedProperty(category = "measurement", flagMapping = {
10962             @ViewDebug.FlagToString(mask = MEASURED_STATE_MASK, equals = MEASURED_STATE_TOO_SMALL,
10963                     name = "MEASURED_STATE_TOO_SMALL"),
10964     })
10965     public final int getMeasuredHeightAndState() {
10966         return mMeasuredHeight;
10967     }
10968 
10969     /**
10970      * Return only the state bits of {@link #getMeasuredWidthAndState()}
10971      * and {@link #getMeasuredHeightAndState()}, combined into one integer.
10972      * The width component is in the regular bits {@link #MEASURED_STATE_MASK}
10973      * and the height component is at the shifted bits
10974      * {@link #MEASURED_HEIGHT_STATE_SHIFT}>>{@link #MEASURED_STATE_MASK}.
10975      */
10976     public final int getMeasuredState() {
10977         return (mMeasuredWidth&MEASURED_STATE_MASK)
10978                 | ((mMeasuredHeight>>MEASURED_HEIGHT_STATE_SHIFT)
10979                         & (MEASURED_STATE_MASK>>MEASURED_HEIGHT_STATE_SHIFT));
10980     }
10981 
10982     /**
10983      * The transform matrix of this view, which is calculated based on the current
10984      * rotation, scale, and pivot properties.
10985      *
10986      * @see #getRotation()
10987      * @see #getScaleX()
10988      * @see #getScaleY()
10989      * @see #getPivotX()
10990      * @see #getPivotY()
10991      * @return The current transform matrix for the view
10992      */
10993     public Matrix getMatrix() {
10994         ensureTransformationInfo();
10995         final Matrix matrix = mTransformationInfo.mMatrix;
10996         mRenderNode.getMatrix(matrix);
10997         return matrix;
10998     }
10999 
11000     /**
11001      * Returns true if the transform matrix is the identity matrix.
11002      * Recomputes the matrix if necessary.
11003      *
11004      * @return True if the transform matrix is the identity matrix, false otherwise.
11005      */
11006     final boolean hasIdentityMatrix() {
11007         return mRenderNode.hasIdentityMatrix();
11008     }
11009 
11010     void ensureTransformationInfo() {
11011         if (mTransformationInfo == null) {
11012             mTransformationInfo = new TransformationInfo();
11013         }
11014     }
11015 
11016    /**
11017      * Utility method to retrieve the inverse of the current mMatrix property.
11018      * We cache the matrix to avoid recalculating it when transform properties
11019      * have not changed.
11020      *
11021      * @return The inverse of the current matrix of this view.
11022      * @hide
11023      */
11024     public final Matrix getInverseMatrix() {
11025         ensureTransformationInfo();
11026         if (mTransformationInfo.mInverseMatrix == null) {
11027             mTransformationInfo.mInverseMatrix = new Matrix();
11028         }
11029         final Matrix matrix = mTransformationInfo.mInverseMatrix;
11030         mRenderNode.getInverseMatrix(matrix);
11031         return matrix;
11032     }
11033 
11034     /**
11035      * Gets the distance along the Z axis from the camera to this view.
11036      *
11037      * @see #setCameraDistance(float)
11038      *
11039      * @return The distance along the Z axis.
11040      */
11041     public float getCameraDistance() {
11042         final float dpi = mResources.getDisplayMetrics().densityDpi;
11043         return -(mRenderNode.getCameraDistance() * dpi);
11044     }
11045 
11046     /**
11047      * <p>Sets the distance along the Z axis (orthogonal to the X/Y plane on which
11048      * views are drawn) from the camera to this view. The camera's distance
11049      * affects 3D transformations, for instance rotations around the X and Y
11050      * axis. If the rotationX or rotationY properties are changed and this view is
11051      * large (more than half the size of the screen), it is recommended to always
11052      * use a camera distance that's greater than the height (X axis rotation) or
11053      * the width (Y axis rotation) of this view.</p>
11054      *
11055      * <p>The distance of the camera from the view plane can have an affect on the
11056      * perspective distortion of the view when it is rotated around the x or y axis.
11057      * For example, a large distance will result in a large viewing angle, and there
11058      * will not be much perspective distortion of the view as it rotates. A short
11059      * distance may cause much more perspective distortion upon rotation, and can
11060      * also result in some drawing artifacts if the rotated view ends up partially
11061      * behind the camera (which is why the recommendation is to use a distance at
11062      * least as far as the size of the view, if the view is to be rotated.)</p>
11063      *
11064      * <p>The distance is expressed in "depth pixels." The default distance depends
11065      * on the screen density. For instance, on a medium density display, the
11066      * default distance is 1280. On a high density display, the default distance
11067      * is 1920.</p>
11068      *
11069      * <p>If you want to specify a distance that leads to visually consistent
11070      * results across various densities, use the following formula:</p>
11071      * <pre>
11072      * float scale = context.getResources().getDisplayMetrics().density;
11073      * view.setCameraDistance(distance * scale);
11074      * </pre>
11075      *
11076      * <p>The density scale factor of a high density display is 1.5,
11077      * and 1920 = 1280 * 1.5.</p>
11078      *
11079      * @param distance The distance in "depth pixels", if negative the opposite
11080      *        value is used
11081      *
11082      * @see #setRotationX(float)
11083      * @see #setRotationY(float)
11084      */
11085     public void setCameraDistance(float distance) {
11086         final float dpi = mResources.getDisplayMetrics().densityDpi;
11087 
11088         invalidateViewProperty(true, false);
11089         mRenderNode.setCameraDistance(-Math.abs(distance) / dpi);
11090         invalidateViewProperty(false, false);
11091 
11092         invalidateParentIfNeededAndWasQuickRejected();
11093     }
11094 
11095     /**
11096      * The degrees that the view is rotated around the pivot point.
11097      *
11098      * @see #setRotation(float)
11099      * @see #getPivotX()
11100      * @see #getPivotY()
11101      *
11102      * @return The degrees of rotation.
11103      */
11104     @ViewDebug.ExportedProperty(category = "drawing")
11105     public float getRotation() {
11106         return mRenderNode.getRotation();
11107     }
11108 
11109     /**
11110      * Sets the degrees that the view is rotated around the pivot point. Increasing values
11111      * result in clockwise rotation.
11112      *
11113      * @param rotation The degrees of rotation.
11114      *
11115      * @see #getRotation()
11116      * @see #getPivotX()
11117      * @see #getPivotY()
11118      * @see #setRotationX(float)
11119      * @see #setRotationY(float)
11120      *
11121      * @attr ref android.R.styleable#View_rotation
11122      */
11123     public void setRotation(float rotation) {
11124         if (rotation != getRotation()) {
11125             // Double-invalidation is necessary to capture view's old and new areas
11126             invalidateViewProperty(true, false);
11127             mRenderNode.setRotation(rotation);
11128             invalidateViewProperty(false, true);
11129 
11130             invalidateParentIfNeededAndWasQuickRejected();
11131             notifySubtreeAccessibilityStateChangedIfNeeded();
11132         }
11133     }
11134 
11135     /**
11136      * The degrees that the view is rotated around the vertical axis through the pivot point.
11137      *
11138      * @see #getPivotX()
11139      * @see #getPivotY()
11140      * @see #setRotationY(float)
11141      *
11142      * @return The degrees of Y rotation.
11143      */
11144     @ViewDebug.ExportedProperty(category = "drawing")
11145     public float getRotationY() {
11146         return mRenderNode.getRotationY();
11147     }
11148 
11149     /**
11150      * Sets the degrees that the view is rotated around the vertical axis through the pivot point.
11151      * Increasing values result in counter-clockwise rotation from the viewpoint of looking
11152      * down the y axis.
11153      *
11154      * When rotating large views, it is recommended to adjust the camera distance
11155      * accordingly. Refer to {@link #setCameraDistance(float)} for more information.
11156      *
11157      * @param rotationY The degrees of Y rotation.
11158      *
11159      * @see #getRotationY()
11160      * @see #getPivotX()
11161      * @see #getPivotY()
11162      * @see #setRotation(float)
11163      * @see #setRotationX(float)
11164      * @see #setCameraDistance(float)
11165      *
11166      * @attr ref android.R.styleable#View_rotationY
11167      */
11168     public void setRotationY(float rotationY) {
11169         if (rotationY != getRotationY()) {
11170             invalidateViewProperty(true, false);
11171             mRenderNode.setRotationY(rotationY);
11172             invalidateViewProperty(false, true);
11173 
11174             invalidateParentIfNeededAndWasQuickRejected();
11175             notifySubtreeAccessibilityStateChangedIfNeeded();
11176         }
11177     }
11178 
11179     /**
11180      * The degrees that the view is rotated around the horizontal axis through the pivot point.
11181      *
11182      * @see #getPivotX()
11183      * @see #getPivotY()
11184      * @see #setRotationX(float)
11185      *
11186      * @return The degrees of X rotation.
11187      */
11188     @ViewDebug.ExportedProperty(category = "drawing")
11189     public float getRotationX() {
11190         return mRenderNode.getRotationX();
11191     }
11192 
11193     /**
11194      * Sets the degrees that the view is rotated around the horizontal axis through the pivot point.
11195      * Increasing values result in clockwise rotation from the viewpoint of looking down the
11196      * x axis.
11197      *
11198      * When rotating large views, it is recommended to adjust the camera distance
11199      * accordingly. Refer to {@link #setCameraDistance(float)} for more information.
11200      *
11201      * @param rotationX The degrees of X rotation.
11202      *
11203      * @see #getRotationX()
11204      * @see #getPivotX()
11205      * @see #getPivotY()
11206      * @see #setRotation(float)
11207      * @see #setRotationY(float)
11208      * @see #setCameraDistance(float)
11209      *
11210      * @attr ref android.R.styleable#View_rotationX
11211      */
11212     public void setRotationX(float rotationX) {
11213         if (rotationX != getRotationX()) {
11214             invalidateViewProperty(true, false);
11215             mRenderNode.setRotationX(rotationX);
11216             invalidateViewProperty(false, true);
11217 
11218             invalidateParentIfNeededAndWasQuickRejected();
11219             notifySubtreeAccessibilityStateChangedIfNeeded();
11220         }
11221     }
11222 
11223     /**
11224      * The amount that the view is scaled in x around the pivot point, as a proportion of
11225      * the view's unscaled width. A value of 1, the default, means that no scaling is applied.
11226      *
11227      * <p>By default, this is 1.0f.
11228      *
11229      * @see #getPivotX()
11230      * @see #getPivotY()
11231      * @return The scaling factor.
11232      */
11233     @ViewDebug.ExportedProperty(category = "drawing")
11234     public float getScaleX() {
11235         return mRenderNode.getScaleX();
11236     }
11237 
11238     /**
11239      * Sets the amount that the view is scaled in x around the pivot point, as a proportion of
11240      * the view's unscaled width. A value of 1 means that no scaling is applied.
11241      *
11242      * @param scaleX The scaling factor.
11243      * @see #getPivotX()
11244      * @see #getPivotY()
11245      *
11246      * @attr ref android.R.styleable#View_scaleX
11247      */
11248     public void setScaleX(float scaleX) {
11249         if (scaleX != getScaleX()) {
11250             invalidateViewProperty(true, false);
11251             mRenderNode.setScaleX(scaleX);
11252             invalidateViewProperty(false, true);
11253 
11254             invalidateParentIfNeededAndWasQuickRejected();
11255             notifySubtreeAccessibilityStateChangedIfNeeded();
11256         }
11257     }
11258 
11259     /**
11260      * The amount that the view is scaled in y around the pivot point, as a proportion of
11261      * the view's unscaled height. A value of 1, the default, means that no scaling is applied.
11262      *
11263      * <p>By default, this is 1.0f.
11264      *
11265      * @see #getPivotX()
11266      * @see #getPivotY()
11267      * @return The scaling factor.
11268      */
11269     @ViewDebug.ExportedProperty(category = "drawing")
11270     public float getScaleY() {
11271         return mRenderNode.getScaleY();
11272     }
11273 
11274     /**
11275      * Sets the amount that the view is scaled in Y around the pivot point, as a proportion of
11276      * the view's unscaled width. A value of 1 means that no scaling is applied.
11277      *
11278      * @param scaleY The scaling factor.
11279      * @see #getPivotX()
11280      * @see #getPivotY()
11281      *
11282      * @attr ref android.R.styleable#View_scaleY
11283      */
11284     public void setScaleY(float scaleY) {
11285         if (scaleY != getScaleY()) {
11286             invalidateViewProperty(true, false);
11287             mRenderNode.setScaleY(scaleY);
11288             invalidateViewProperty(false, true);
11289 
11290             invalidateParentIfNeededAndWasQuickRejected();
11291             notifySubtreeAccessibilityStateChangedIfNeeded();
11292         }
11293     }
11294 
11295     /**
11296      * The x location of the point around which the view is {@link #setRotation(float) rotated}
11297      * and {@link #setScaleX(float) scaled}.
11298      *
11299      * @see #getRotation()
11300      * @see #getScaleX()
11301      * @see #getScaleY()
11302      * @see #getPivotY()
11303      * @return The x location of the pivot point.
11304      *
11305      * @attr ref android.R.styleable#View_transformPivotX
11306      */
11307     @ViewDebug.ExportedProperty(category = "drawing")
11308     public float getPivotX() {
11309         return mRenderNode.getPivotX();
11310     }
11311 
11312     /**
11313      * Sets the x location of the point around which the view is
11314      * {@link #setRotation(float) rotated} and {@link #setScaleX(float) scaled}.
11315      * By default, the pivot point is centered on the object.
11316      * Setting this property disables this behavior and causes the view to use only the
11317      * explicitly set pivotX and pivotY values.
11318      *
11319      * @param pivotX The x location of the pivot point.
11320      * @see #getRotation()
11321      * @see #getScaleX()
11322      * @see #getScaleY()
11323      * @see #getPivotY()
11324      *
11325      * @attr ref android.R.styleable#View_transformPivotX
11326      */
11327     public void setPivotX(float pivotX) {
11328         if (!mRenderNode.isPivotExplicitlySet() || pivotX != getPivotX()) {
11329             invalidateViewProperty(true, false);
11330             mRenderNode.setPivotX(pivotX);
11331             invalidateViewProperty(false, true);
11332 
11333             invalidateParentIfNeededAndWasQuickRejected();
11334         }
11335     }
11336 
11337     /**
11338      * The y location of the point around which the view is {@link #setRotation(float) rotated}
11339      * and {@link #setScaleY(float) scaled}.
11340      *
11341      * @see #getRotation()
11342      * @see #getScaleX()
11343      * @see #getScaleY()
11344      * @see #getPivotY()
11345      * @return The y location of the pivot point.
11346      *
11347      * @attr ref android.R.styleable#View_transformPivotY
11348      */
11349     @ViewDebug.ExportedProperty(category = "drawing")
11350     public float getPivotY() {
11351         return mRenderNode.getPivotY();
11352     }
11353 
11354     /**
11355      * Sets the y location of the point around which the view is {@link #setRotation(float) rotated}
11356      * and {@link #setScaleY(float) scaled}. By default, the pivot point is centered on the object.
11357      * Setting this property disables this behavior and causes the view to use only the
11358      * explicitly set pivotX and pivotY values.
11359      *
11360      * @param pivotY The y location of the pivot point.
11361      * @see #getRotation()
11362      * @see #getScaleX()
11363      * @see #getScaleY()
11364      * @see #getPivotY()
11365      *
11366      * @attr ref android.R.styleable#View_transformPivotY
11367      */
11368     public void setPivotY(float pivotY) {
11369         if (!mRenderNode.isPivotExplicitlySet() || pivotY != getPivotY()) {
11370             invalidateViewProperty(true, false);
11371             mRenderNode.setPivotY(pivotY);
11372             invalidateViewProperty(false, true);
11373 
11374             invalidateParentIfNeededAndWasQuickRejected();
11375         }
11376     }
11377 
11378     /**
11379      * The opacity of the view. This is a value from 0 to 1, where 0 means the view is
11380      * completely transparent and 1 means the view is completely opaque.
11381      *
11382      * <p>By default this is 1.0f.
11383      * @return The opacity of the view.
11384      */
11385     @ViewDebug.ExportedProperty(category = "drawing")
11386     public float getAlpha() {
11387         return mTransformationInfo != null ? mTransformationInfo.mAlpha : 1;
11388     }
11389 
11390     /**
11391      * Returns whether this View has content which overlaps.
11392      *
11393      * <p>This function, intended to be overridden by specific View types, is an optimization when
11394      * alpha is set on a view. If rendering overlaps in a view with alpha < 1, that view is drawn to
11395      * an offscreen buffer and then composited into place, which can be expensive. If the view has
11396      * no overlapping rendering, the view can draw each primitive with the appropriate alpha value
11397      * directly. An example of overlapping rendering is a TextView with a background image, such as
11398      * a Button. An example of non-overlapping rendering is a TextView with no background, or an
11399      * ImageView with only the foreground image. The default implementation returns true; subclasses
11400      * should override if they have cases which can be optimized.</p>
11401      *
11402      * <p>The current implementation of the saveLayer and saveLayerAlpha methods in {@link Canvas}
11403      * necessitates that a View return true if it uses the methods internally without passing the
11404      * {@link Canvas#CLIP_TO_LAYER_SAVE_FLAG}.</p>
11405      *
11406      * @return true if the content in this view might overlap, false otherwise.
11407      */
11408     @ViewDebug.ExportedProperty(category = "drawing")
11409     public boolean hasOverlappingRendering() {
11410         return true;
11411     }
11412 
11413     /**
11414      * Sets the opacity of the view to a value from 0 to 1, where 0 means the view is
11415      * completely transparent and 1 means the view is completely opaque.
11416      *
11417      * <p class="note"><strong>Note:</strong> setting alpha to a translucent value (0 < alpha < 1)
11418      * can have significant performance implications, especially for large views. It is best to use
11419      * the alpha property sparingly and transiently, as in the case of fading animations.</p>
11420      *
11421      * <p>For a view with a frequently changing alpha, such as during a fading animation, it is
11422      * strongly recommended for performance reasons to either override
11423      * {@link #hasOverlappingRendering()} to return <code>false</code> if appropriate, or setting a
11424      * {@link #setLayerType(int, android.graphics.Paint) layer type} on the view for the duration
11425      * of the animation. On versions {@link android.os.Build.VERSION_CODES#M} and below,
11426      * the default path for rendering an unlayered View with alpha could add multiple milliseconds
11427      * of rendering cost, even for simple or small views. Starting with
11428      * {@link android.os.Build.VERSION_CODES#M}, {@link #LAYER_TYPE_HARDWARE} is automatically
11429      * applied to the view at the rendering level.</p>
11430      *
11431      * <p>If this view overrides {@link #onSetAlpha(int)} to return true, then this view is
11432      * responsible for applying the opacity itself.</p>
11433      *
11434      * <p>On versions {@link android.os.Build.VERSION_CODES#LOLLIPOP_MR1} and below, note that if
11435      * the view is backed by a {@link #setLayerType(int, android.graphics.Paint) layer} and is
11436      * associated with a {@link #setLayerPaint(android.graphics.Paint) layer paint}, setting an
11437      * alpha value less than 1.0 will supersede the alpha of the layer paint.</p>
11438      *
11439      * <p>Starting with {@link android.os.Build.VERSION_CODES#M}, setting a translucent alpha
11440      * value will clip a View to its bounds, unless the View returns <code>false</code> from
11441      * {@link #hasOverlappingRendering}.</p>
11442      *
11443      * @param alpha The opacity of the view.
11444      *
11445      * @see #hasOverlappingRendering()
11446      * @see #setLayerType(int, android.graphics.Paint)
11447      *
11448      * @attr ref android.R.styleable#View_alpha
11449      */
11450     public void setAlpha(@FloatRange(from=0.0, to=1.0) float alpha) {
11451         ensureTransformationInfo();
11452         if (mTransformationInfo.mAlpha != alpha) {
11453             mTransformationInfo.mAlpha = alpha;
11454             if (onSetAlpha((int) (alpha * 255))) {
11455                 mPrivateFlags |= PFLAG_ALPHA_SET;
11456                 // subclass is handling alpha - don't optimize rendering cache invalidation
11457                 invalidateParentCaches();
11458                 invalidate(true);
11459             } else {
11460                 mPrivateFlags &= ~PFLAG_ALPHA_SET;
11461                 invalidateViewProperty(true, false);
11462                 mRenderNode.setAlpha(getFinalAlpha());
11463                 notifyViewAccessibilityStateChangedIfNeeded(
11464                         AccessibilityEvent.CONTENT_CHANGE_TYPE_UNDEFINED);
11465             }
11466         }
11467     }
11468 
11469     /**
11470      * Faster version of setAlpha() which performs the same steps except there are
11471      * no calls to invalidate(). The caller of this function should perform proper invalidation
11472      * on the parent and this object. The return value indicates whether the subclass handles
11473      * alpha (the return value for onSetAlpha()).
11474      *
11475      * @param alpha The new value for the alpha property
11476      * @return true if the View subclass handles alpha (the return value for onSetAlpha()) and
11477      *         the new value for the alpha property is different from the old value
11478      */
11479     boolean setAlphaNoInvalidation(float alpha) {
11480         ensureTransformationInfo();
11481         if (mTransformationInfo.mAlpha != alpha) {
11482             mTransformationInfo.mAlpha = alpha;
11483             boolean subclassHandlesAlpha = onSetAlpha((int) (alpha * 255));
11484             if (subclassHandlesAlpha) {
11485                 mPrivateFlags |= PFLAG_ALPHA_SET;
11486                 return true;
11487             } else {
11488                 mPrivateFlags &= ~PFLAG_ALPHA_SET;
11489                 mRenderNode.setAlpha(getFinalAlpha());
11490             }
11491         }
11492         return false;
11493     }
11494 
11495     /**
11496      * This property is hidden and intended only for use by the Fade transition, which
11497      * animates it to produce a visual translucency that does not side-effect (or get
11498      * affected by) the real alpha property. This value is composited with the other
11499      * alpha value (and the AlphaAnimation value, when that is present) to produce
11500      * a final visual translucency result, which is what is passed into the DisplayList.
11501      *
11502      * @hide
11503      */
11504     public void setTransitionAlpha(float alpha) {
11505         ensureTransformationInfo();
11506         if (mTransformationInfo.mTransitionAlpha != alpha) {
11507             mTransformationInfo.mTransitionAlpha = alpha;
11508             mPrivateFlags &= ~PFLAG_ALPHA_SET;
11509             invalidateViewProperty(true, false);
11510             mRenderNode.setAlpha(getFinalAlpha());
11511         }
11512     }
11513 
11514     /**
11515      * Calculates the visual alpha of this view, which is a combination of the actual
11516      * alpha value and the transitionAlpha value (if set).
11517      */
11518     private float getFinalAlpha() {
11519         if (mTransformationInfo != null) {
11520             return mTransformationInfo.mAlpha * mTransformationInfo.mTransitionAlpha;
11521         }
11522         return 1;
11523     }
11524 
11525     /**
11526      * This property is hidden and intended only for use by the Fade transition, which
11527      * animates it to produce a visual translucency that does not side-effect (or get
11528      * affected by) the real alpha property. This value is composited with the other
11529      * alpha value (and the AlphaAnimation value, when that is present) to produce
11530      * a final visual translucency result, which is what is passed into the DisplayList.
11531      *
11532      * @hide
11533      */
11534     @ViewDebug.ExportedProperty(category = "drawing")
11535     public float getTransitionAlpha() {
11536         return mTransformationInfo != null ? mTransformationInfo.mTransitionAlpha : 1;
11537     }
11538 
11539     /**
11540      * Top position of this view relative to its parent.
11541      *
11542      * @return The top of this view, in pixels.
11543      */
11544     @ViewDebug.CapturedViewProperty
11545     public final int getTop() {
11546         return mTop;
11547     }
11548 
11549     /**
11550      * Sets the top position of this view relative to its parent. This method is meant to be called
11551      * by the layout system and should not generally be called otherwise, because the property
11552      * may be changed at any time by the layout.
11553      *
11554      * @param top The top of this view, in pixels.
11555      */
11556     public final void setTop(int top) {
11557         if (top != mTop) {
11558             final boolean matrixIsIdentity = hasIdentityMatrix();
11559             if (matrixIsIdentity) {
11560                 if (mAttachInfo != null) {
11561                     int minTop;
11562                     int yLoc;
11563                     if (top < mTop) {
11564                         minTop = top;
11565                         yLoc = top - mTop;
11566                     } else {
11567                         minTop = mTop;
11568                         yLoc = 0;
11569                     }
11570                     invalidate(0, yLoc, mRight - mLeft, mBottom - minTop);
11571                 }
11572             } else {
11573                 // Double-invalidation is necessary to capture view's old and new areas
11574                 invalidate(true);
11575             }
11576 
11577             int width = mRight - mLeft;
11578             int oldHeight = mBottom - mTop;
11579 
11580             mTop = top;
11581             mRenderNode.setTop(mTop);
11582 
11583             sizeChange(width, mBottom - mTop, width, oldHeight);
11584 
11585             if (!matrixIsIdentity) {
11586                 mPrivateFlags |= PFLAG_DRAWN; // force another invalidation with the new orientation
11587                 invalidate(true);
11588             }
11589             mBackgroundSizeChanged = true;
11590             if (mForegroundInfo != null) {
11591                 mForegroundInfo.mBoundsChanged = true;
11592             }
11593             invalidateParentIfNeeded();
11594             if ((mPrivateFlags2 & PFLAG2_VIEW_QUICK_REJECTED) == PFLAG2_VIEW_QUICK_REJECTED) {
11595                 // View was rejected last time it was drawn by its parent; this may have changed
11596                 invalidateParentIfNeeded();
11597             }
11598         }
11599     }
11600 
11601     /**
11602      * Bottom position of this view relative to its parent.
11603      *
11604      * @return The bottom of this view, in pixels.
11605      */
11606     @ViewDebug.CapturedViewProperty
11607     public final int getBottom() {
11608         return mBottom;
11609     }
11610 
11611     /**
11612      * True if this view has changed since the last time being drawn.
11613      *
11614      * @return The dirty state of this view.
11615      */
11616     public boolean isDirty() {
11617         return (mPrivateFlags & PFLAG_DIRTY_MASK) != 0;
11618     }
11619 
11620     /**
11621      * Sets the bottom position of this view relative to its parent. This method is meant to be
11622      * called by the layout system and should not generally be called otherwise, because the
11623      * property may be changed at any time by the layout.
11624      *
11625      * @param bottom The bottom of this view, in pixels.
11626      */
11627     public final void setBottom(int bottom) {
11628         if (bottom != mBottom) {
11629             final boolean matrixIsIdentity = hasIdentityMatrix();
11630             if (matrixIsIdentity) {
11631                 if (mAttachInfo != null) {
11632                     int maxBottom;
11633                     if (bottom < mBottom) {
11634                         maxBottom = mBottom;
11635                     } else {
11636                         maxBottom = bottom;
11637                     }
11638                     invalidate(0, 0, mRight - mLeft, maxBottom - mTop);
11639                 }
11640             } else {
11641                 // Double-invalidation is necessary to capture view's old and new areas
11642                 invalidate(true);
11643             }
11644 
11645             int width = mRight - mLeft;
11646             int oldHeight = mBottom - mTop;
11647 
11648             mBottom = bottom;
11649             mRenderNode.setBottom(mBottom);
11650 
11651             sizeChange(width, mBottom - mTop, width, oldHeight);
11652 
11653             if (!matrixIsIdentity) {
11654                 mPrivateFlags |= PFLAG_DRAWN; // force another invalidation with the new orientation
11655                 invalidate(true);
11656             }
11657             mBackgroundSizeChanged = true;
11658             if (mForegroundInfo != null) {
11659                 mForegroundInfo.mBoundsChanged = true;
11660             }
11661             invalidateParentIfNeeded();
11662             if ((mPrivateFlags2 & PFLAG2_VIEW_QUICK_REJECTED) == PFLAG2_VIEW_QUICK_REJECTED) {
11663                 // View was rejected last time it was drawn by its parent; this may have changed
11664                 invalidateParentIfNeeded();
11665             }
11666         }
11667     }
11668 
11669     /**
11670      * Left position of this view relative to its parent.
11671      *
11672      * @return The left edge of this view, in pixels.
11673      */
11674     @ViewDebug.CapturedViewProperty
11675     public final int getLeft() {
11676         return mLeft;
11677     }
11678 
11679     /**
11680      * Sets the left position of this view relative to its parent. This method is meant to be called
11681      * by the layout system and should not generally be called otherwise, because the property
11682      * may be changed at any time by the layout.
11683      *
11684      * @param left The left of this view, in pixels.
11685      */
11686     public final void setLeft(int left) {
11687         if (left != mLeft) {
11688             final boolean matrixIsIdentity = hasIdentityMatrix();
11689             if (matrixIsIdentity) {
11690                 if (mAttachInfo != null) {
11691                     int minLeft;
11692                     int xLoc;
11693                     if (left < mLeft) {
11694                         minLeft = left;
11695                         xLoc = left - mLeft;
11696                     } else {
11697                         minLeft = mLeft;
11698                         xLoc = 0;
11699                     }
11700                     invalidate(xLoc, 0, mRight - minLeft, mBottom - mTop);
11701                 }
11702             } else {
11703                 // Double-invalidation is necessary to capture view's old and new areas
11704                 invalidate(true);
11705             }
11706 
11707             int oldWidth = mRight - mLeft;
11708             int height = mBottom - mTop;
11709 
11710             mLeft = left;
11711             mRenderNode.setLeft(left);
11712 
11713             sizeChange(mRight - mLeft, height, oldWidth, height);
11714 
11715             if (!matrixIsIdentity) {
11716                 mPrivateFlags |= PFLAG_DRAWN; // force another invalidation with the new orientation
11717                 invalidate(true);
11718             }
11719             mBackgroundSizeChanged = true;
11720             if (mForegroundInfo != null) {
11721                 mForegroundInfo.mBoundsChanged = true;
11722             }
11723             invalidateParentIfNeeded();
11724             if ((mPrivateFlags2 & PFLAG2_VIEW_QUICK_REJECTED) == PFLAG2_VIEW_QUICK_REJECTED) {
11725                 // View was rejected last time it was drawn by its parent; this may have changed
11726                 invalidateParentIfNeeded();
11727             }
11728         }
11729     }
11730 
11731     /**
11732      * Right position of this view relative to its parent.
11733      *
11734      * @return The right edge of this view, in pixels.
11735      */
11736     @ViewDebug.CapturedViewProperty
11737     public final int getRight() {
11738         return mRight;
11739     }
11740 
11741     /**
11742      * Sets the right position of this view relative to its parent. This method is meant to be called
11743      * by the layout system and should not generally be called otherwise, because the property
11744      * may be changed at any time by the layout.
11745      *
11746      * @param right The right of this view, in pixels.
11747      */
11748     public final void setRight(int right) {
11749         if (right != mRight) {
11750             final boolean matrixIsIdentity = hasIdentityMatrix();
11751             if (matrixIsIdentity) {
11752                 if (mAttachInfo != null) {
11753                     int maxRight;
11754                     if (right < mRight) {
11755                         maxRight = mRight;
11756                     } else {
11757                         maxRight = right;
11758                     }
11759                     invalidate(0, 0, maxRight - mLeft, mBottom - mTop);
11760                 }
11761             } else {
11762                 // Double-invalidation is necessary to capture view's old and new areas
11763                 invalidate(true);
11764             }
11765 
11766             int oldWidth = mRight - mLeft;
11767             int height = mBottom - mTop;
11768 
11769             mRight = right;
11770             mRenderNode.setRight(mRight);
11771 
11772             sizeChange(mRight - mLeft, height, oldWidth, height);
11773 
11774             if (!matrixIsIdentity) {
11775                 mPrivateFlags |= PFLAG_DRAWN; // force another invalidation with the new orientation
11776                 invalidate(true);
11777             }
11778             mBackgroundSizeChanged = true;
11779             if (mForegroundInfo != null) {
11780                 mForegroundInfo.mBoundsChanged = true;
11781             }
11782             invalidateParentIfNeeded();
11783             if ((mPrivateFlags2 & PFLAG2_VIEW_QUICK_REJECTED) == PFLAG2_VIEW_QUICK_REJECTED) {
11784                 // View was rejected last time it was drawn by its parent; this may have changed
11785                 invalidateParentIfNeeded();
11786             }
11787         }
11788     }
11789 
11790     /**
11791      * The visual x position of this view, in pixels. This is equivalent to the
11792      * {@link #setTranslationX(float) translationX} property plus the current
11793      * {@link #getLeft() left} property.
11794      *
11795      * @return The visual x position of this view, in pixels.
11796      */
11797     @ViewDebug.ExportedProperty(category = "drawing")
11798     public float getX() {
11799         return mLeft + getTranslationX();
11800     }
11801 
11802     /**
11803      * Sets the visual x position of this view, in pixels. This is equivalent to setting the
11804      * {@link #setTranslationX(float) translationX} property to be the difference between
11805      * the x value passed in and the current {@link #getLeft() left} property.
11806      *
11807      * @param x The visual x position of this view, in pixels.
11808      */
11809     public void setX(float x) {
11810         setTranslationX(x - mLeft);
11811     }
11812 
11813     /**
11814      * The visual y position of this view, in pixels. This is equivalent to the
11815      * {@link #setTranslationY(float) translationY} property plus the current
11816      * {@link #getTop() top} property.
11817      *
11818      * @return The visual y position of this view, in pixels.
11819      */
11820     @ViewDebug.ExportedProperty(category = "drawing")
11821     public float getY() {
11822         return mTop + getTranslationY();
11823     }
11824 
11825     /**
11826      * Sets the visual y position of this view, in pixels. This is equivalent to setting the
11827      * {@link #setTranslationY(float) translationY} property to be the difference between
11828      * the y value passed in and the current {@link #getTop() top} property.
11829      *
11830      * @param y The visual y position of this view, in pixels.
11831      */
11832     public void setY(float y) {
11833         setTranslationY(y - mTop);
11834     }
11835 
11836     /**
11837      * The visual z position of this view, in pixels. This is equivalent to the
11838      * {@link #setTranslationZ(float) translationZ} property plus the current
11839      * {@link #getElevation() elevation} property.
11840      *
11841      * @return The visual z position of this view, in pixels.
11842      */
11843     @ViewDebug.ExportedProperty(category = "drawing")
11844     public float getZ() {
11845         return getElevation() + getTranslationZ();
11846     }
11847 
11848     /**
11849      * Sets the visual z position of this view, in pixels. This is equivalent to setting the
11850      * {@link #setTranslationZ(float) translationZ} property to be the difference between
11851      * the x value passed in and the current {@link #getElevation() elevation} property.
11852      *
11853      * @param z The visual z position of this view, in pixels.
11854      */
11855     public void setZ(float z) {
11856         setTranslationZ(z - getElevation());
11857     }
11858 
11859     /**
11860      * The base elevation of this view relative to its parent, in pixels.
11861      *
11862      * @return The base depth position of the view, in pixels.
11863      */
11864     @ViewDebug.ExportedProperty(category = "drawing")
11865     public float getElevation() {
11866         return mRenderNode.getElevation();
11867     }
11868 
11869     /**
11870      * Sets the base elevation of this view, in pixels.
11871      *
11872      * @attr ref android.R.styleable#View_elevation
11873      */
11874     public void setElevation(float elevation) {
11875         if (elevation != getElevation()) {
11876             invalidateViewProperty(true, false);
11877             mRenderNode.setElevation(elevation);
11878             invalidateViewProperty(false, true);
11879 
11880             invalidateParentIfNeededAndWasQuickRejected();
11881         }
11882     }
11883 
11884     /**
11885      * The horizontal location of this view relative to its {@link #getLeft() left} position.
11886      * This position is post-layout, in addition to wherever the object's
11887      * layout placed it.
11888      *
11889      * @return The horizontal position of this view relative to its left position, in pixels.
11890      */
11891     @ViewDebug.ExportedProperty(category = "drawing")
11892     public float getTranslationX() {
11893         return mRenderNode.getTranslationX();
11894     }
11895 
11896     /**
11897      * Sets the horizontal location of this view relative to its {@link #getLeft() left} position.
11898      * This effectively positions the object post-layout, in addition to wherever the object's
11899      * layout placed it.
11900      *
11901      * @param translationX The horizontal position of this view relative to its left position,
11902      * in pixels.
11903      *
11904      * @attr ref android.R.styleable#View_translationX
11905      */
11906     public void setTranslationX(float translationX) {
11907         if (translationX != getTranslationX()) {
11908             invalidateViewProperty(true, false);
11909             mRenderNode.setTranslationX(translationX);
11910             invalidateViewProperty(false, true);
11911 
11912             invalidateParentIfNeededAndWasQuickRejected();
11913             notifySubtreeAccessibilityStateChangedIfNeeded();
11914         }
11915     }
11916 
11917     /**
11918      * The vertical location of this view relative to its {@link #getTop() top} position.
11919      * This position is post-layout, in addition to wherever the object's
11920      * layout placed it.
11921      *
11922      * @return The vertical position of this view relative to its top position,
11923      * in pixels.
11924      */
11925     @ViewDebug.ExportedProperty(category = "drawing")
11926     public float getTranslationY() {
11927         return mRenderNode.getTranslationY();
11928     }
11929 
11930     /**
11931      * Sets the vertical location of this view relative to its {@link #getTop() top} position.
11932      * This effectively positions the object post-layout, in addition to wherever the object's
11933      * layout placed it.
11934      *
11935      * @param translationY The vertical position of this view relative to its top position,
11936      * in pixels.
11937      *
11938      * @attr ref android.R.styleable#View_translationY
11939      */
11940     public void setTranslationY(float translationY) {
11941         if (translationY != getTranslationY()) {
11942             invalidateViewProperty(true, false);
11943             mRenderNode.setTranslationY(translationY);
11944             invalidateViewProperty(false, true);
11945 
11946             invalidateParentIfNeededAndWasQuickRejected();
11947             notifySubtreeAccessibilityStateChangedIfNeeded();
11948         }
11949     }
11950 
11951     /**
11952      * The depth location of this view relative to its {@link #getElevation() elevation}.
11953      *
11954      * @return The depth of this view relative to its elevation.
11955      */
11956     @ViewDebug.ExportedProperty(category = "drawing")
11957     public float getTranslationZ() {
11958         return mRenderNode.getTranslationZ();
11959     }
11960 
11961     /**
11962      * Sets the depth location of this view relative to its {@link #getElevation() elevation}.
11963      *
11964      * @attr ref android.R.styleable#View_translationZ
11965      */
11966     public void setTranslationZ(float translationZ) {
11967         if (translationZ != getTranslationZ()) {
11968             invalidateViewProperty(true, false);
11969             mRenderNode.setTranslationZ(translationZ);
11970             invalidateViewProperty(false, true);
11971 
11972             invalidateParentIfNeededAndWasQuickRejected();
11973         }
11974     }
11975 
11976     /** @hide */
11977     public void setAnimationMatrix(Matrix matrix) {
11978         invalidateViewProperty(true, false);
11979         mRenderNode.setAnimationMatrix(matrix);
11980         invalidateViewProperty(false, true);
11981 
11982         invalidateParentIfNeededAndWasQuickRejected();
11983     }
11984 
11985     /**
11986      * Returns the current StateListAnimator if exists.
11987      *
11988      * @return StateListAnimator or null if it does not exists
11989      * @see    #setStateListAnimator(android.animation.StateListAnimator)
11990      */
11991     public StateListAnimator getStateListAnimator() {
11992         return mStateListAnimator;
11993     }
11994 
11995     /**
11996      * Attaches the provided StateListAnimator to this View.
11997      * <p>
11998      * Any previously attached StateListAnimator will be detached.
11999      *
12000      * @param stateListAnimator The StateListAnimator to update the view
12001      * @see {@link android.animation.StateListAnimator}
12002      */
12003     public void setStateListAnimator(StateListAnimator stateListAnimator) {
12004         if (mStateListAnimator == stateListAnimator) {
12005             return;
12006         }
12007         if (mStateListAnimator != null) {
12008             mStateListAnimator.setTarget(null);
12009         }
12010         mStateListAnimator = stateListAnimator;
12011         if (stateListAnimator != null) {
12012             stateListAnimator.setTarget(this);
12013             if (isAttachedToWindow()) {
12014                 stateListAnimator.setState(getDrawableState());
12015             }
12016         }
12017     }
12018 
12019     /**
12020      * Returns whether the Outline should be used to clip the contents of the View.
12021      * <p>
12022      * Note that this flag will only be respected if the View's Outline returns true from
12023      * {@link Outline#canClip()}.
12024      *
12025      * @see #setOutlineProvider(ViewOutlineProvider)
12026      * @see #setClipToOutline(boolean)
12027      */
12028     public final boolean getClipToOutline() {
12029         return mRenderNode.getClipToOutline();
12030     }
12031 
12032     /**
12033      * Sets whether the View's Outline should be used to clip the contents of the View.
12034      * <p>
12035      * Only a single non-rectangular clip can be applied on a View at any time.
12036      * Circular clips from a {@link ViewAnimationUtils#createCircularReveal(View, int, int, float, float)
12037      * circular reveal} animation take priority over Outline clipping, and
12038      * child Outline clipping takes priority over Outline clipping done by a
12039      * parent.
12040      * <p>
12041      * Note that this flag will only be respected if the View's Outline returns true from
12042      * {@link Outline#canClip()}.
12043      *
12044      * @see #setOutlineProvider(ViewOutlineProvider)
12045      * @see #getClipToOutline()
12046      */
12047     public void setClipToOutline(boolean clipToOutline) {
12048         damageInParent();
12049         if (getClipToOutline() != clipToOutline) {
12050             mRenderNode.setClipToOutline(clipToOutline);
12051         }
12052     }
12053 
12054     // correspond to the enum values of View_outlineProvider
12055     private static final int PROVIDER_BACKGROUND = 0;
12056     private static final int PROVIDER_NONE = 1;
12057     private static final int PROVIDER_BOUNDS = 2;
12058     private static final int PROVIDER_PADDED_BOUNDS = 3;
12059     private void setOutlineProviderFromAttribute(int providerInt) {
12060         switch (providerInt) {
12061             case PROVIDER_BACKGROUND:
12062                 setOutlineProvider(ViewOutlineProvider.BACKGROUND);
12063                 break;
12064             case PROVIDER_NONE:
12065                 setOutlineProvider(null);
12066                 break;
12067             case PROVIDER_BOUNDS:
12068                 setOutlineProvider(ViewOutlineProvider.BOUNDS);
12069                 break;
12070             case PROVIDER_PADDED_BOUNDS:
12071                 setOutlineProvider(ViewOutlineProvider.PADDED_BOUNDS);
12072                 break;
12073         }
12074     }
12075 
12076     /**
12077      * Sets the {@link ViewOutlineProvider} of the view, which generates the Outline that defines
12078      * the shape of the shadow it casts, and enables outline clipping.
12079      * <p>
12080      * The default ViewOutlineProvider, {@link ViewOutlineProvider#BACKGROUND}, queries the Outline
12081      * from the View's background drawable, via {@link Drawable#getOutline(Outline)}. Changing the
12082      * outline provider with this method allows this behavior to be overridden.
12083      * <p>
12084      * If the ViewOutlineProvider is null, if querying it for an outline returns false,
12085      * or if the produced Outline is {@link Outline#isEmpty()}, shadows will not be cast.
12086      * <p>
12087      * Only outlines that return true from {@link Outline#canClip()} may be used for clipping.
12088      *
12089      * @see #setClipToOutline(boolean)
12090      * @see #getClipToOutline()
12091      * @see #getOutlineProvider()
12092      */
12093     public void setOutlineProvider(ViewOutlineProvider provider) {
12094         mOutlineProvider = provider;
12095         invalidateOutline();
12096     }
12097 
12098     /**
12099      * Returns the current {@link ViewOutlineProvider} of the view, which generates the Outline
12100      * that defines the shape of the shadow it casts, and enables outline clipping.
12101      *
12102      * @see #setOutlineProvider(ViewOutlineProvider)
12103      */
12104     public ViewOutlineProvider getOutlineProvider() {
12105         return mOutlineProvider;
12106     }
12107 
12108     /**
12109      * Called to rebuild this View's Outline from its {@link ViewOutlineProvider outline provider}
12110      *
12111      * @see #setOutlineProvider(ViewOutlineProvider)
12112      */
12113     public void invalidateOutline() {
12114         rebuildOutline();
12115 
12116         notifySubtreeAccessibilityStateChangedIfNeeded();
12117         invalidateViewProperty(false, false);
12118     }
12119 
12120     /**
12121      * Internal version of {@link #invalidateOutline()} which invalidates the
12122      * outline without invalidating the view itself. This is intended to be called from
12123      * within methods in the View class itself which are the result of the view being
12124      * invalidated already. For example, when we are drawing the background of a View,
12125      * we invalidate the outline in case it changed in the meantime, but we do not
12126      * need to invalidate the view because we're already drawing the background as part
12127      * of drawing the view in response to an earlier invalidation of the view.
12128      */
12129     private void rebuildOutline() {
12130         // Unattached views ignore this signal, and outline is recomputed in onAttachedToWindow()
12131         if (mAttachInfo == null) return;
12132 
12133         if (mOutlineProvider == null) {
12134             // no provider, remove outline
12135             mRenderNode.setOutline(null);
12136         } else {
12137             final Outline outline = mAttachInfo.mTmpOutline;
12138             outline.setEmpty();
12139             outline.setAlpha(1.0f);
12140 
12141             mOutlineProvider.getOutline(this, outline);
12142             mRenderNode.setOutline(outline);
12143         }
12144     }
12145 
12146     /**
12147      * HierarchyViewer only
12148      *
12149      * @hide
12150      */
12151     @ViewDebug.ExportedProperty(category = "drawing")
12152     public boolean hasShadow() {
12153         return mRenderNode.hasShadow();
12154     }
12155 
12156 
12157     /** @hide */
12158     public void setRevealClip(boolean shouldClip, float x, float y, float radius) {
12159         mRenderNode.setRevealClip(shouldClip, x, y, radius);
12160         invalidateViewProperty(false, false);
12161     }
12162 
12163     /**
12164      * Hit rectangle in parent's coordinates
12165      *
12166      * @param outRect The hit rectangle of the view.
12167      */
12168     public void getHitRect(Rect outRect) {
12169         if (hasIdentityMatrix() || mAttachInfo == null) {
12170             outRect.set(mLeft, mTop, mRight, mBottom);
12171         } else {
12172             final RectF tmpRect = mAttachInfo.mTmpTransformRect;
12173             tmpRect.set(0, 0, getWidth(), getHeight());
12174             getMatrix().mapRect(tmpRect); // TODO: mRenderNode.mapRect(tmpRect)
12175             outRect.set((int) tmpRect.left + mLeft, (int) tmpRect.top + mTop,
12176                     (int) tmpRect.right + mLeft, (int) tmpRect.bottom + mTop);
12177         }
12178     }
12179 
12180     /**
12181      * Determines whether the given point, in local coordinates is inside the view.
12182      */
12183     /*package*/ final boolean pointInView(float localX, float localY) {
12184         return localX >= 0 && localX < (mRight - mLeft)
12185                 && localY >= 0 && localY < (mBottom - mTop);
12186     }
12187 
12188     /**
12189      * Utility method to determine whether the given point, in local coordinates,
12190      * is inside the view, where the area of the view is expanded by the slop factor.
12191      * This method is called while processing touch-move events to determine if the event
12192      * is still within the view.
12193      *
12194      * @hide
12195      */
12196     public boolean pointInView(float localX, float localY, float slop) {
12197         return localX >= -slop && localY >= -slop && localX < ((mRight - mLeft) + slop) &&
12198                 localY < ((mBottom - mTop) + slop);
12199     }
12200 
12201     /**
12202      * When a view has focus and the user navigates away from it, the next view is searched for
12203      * starting from the rectangle filled in by this method.
12204      *
12205      * By default, the rectangle is the {@link #getDrawingRect(android.graphics.Rect)})
12206      * of the view.  However, if your view maintains some idea of internal selection,
12207      * such as a cursor, or a selected row or column, you should override this method and
12208      * fill in a more specific rectangle.
12209      *
12210      * @param r The rectangle to fill in, in this view's coordinates.
12211      */
12212     public void getFocusedRect(Rect r) {
12213         getDrawingRect(r);
12214     }
12215 
12216     /**
12217      * If some part of this view is not clipped by any of its parents, then
12218      * return that area in r in global (root) coordinates. To convert r to local
12219      * coordinates (without taking possible View rotations into account), offset
12220      * it by -globalOffset (e.g. r.offset(-globalOffset.x, -globalOffset.y)).
12221      * If the view is completely clipped or translated out, return false.
12222      *
12223      * @param r If true is returned, r holds the global coordinates of the
12224      *        visible portion of this view.
12225      * @param globalOffset If true is returned, globalOffset holds the dx,dy
12226      *        between this view and its root. globalOffet may be null.
12227      * @return true if r is non-empty (i.e. part of the view is visible at the
12228      *         root level.
12229      */
12230     public boolean getGlobalVisibleRect(Rect r, Point globalOffset) {
12231         int width = mRight - mLeft;
12232         int height = mBottom - mTop;
12233         if (width > 0 && height > 0) {
12234             r.set(0, 0, width, height);
12235             if (globalOffset != null) {
12236                 globalOffset.set(-mScrollX, -mScrollY);
12237             }
12238             return mParent == null || mParent.getChildVisibleRect(this, r, globalOffset);
12239         }
12240         return false;
12241     }
12242 
12243     public final boolean getGlobalVisibleRect(Rect r) {
12244         return getGlobalVisibleRect(r, null);
12245     }
12246 
12247     public final boolean getLocalVisibleRect(Rect r) {
12248         final Point offset = mAttachInfo != null ? mAttachInfo.mPoint : new Point();
12249         if (getGlobalVisibleRect(r, offset)) {
12250             r.offset(-offset.x, -offset.y); // make r local
12251             return true;
12252         }
12253         return false;
12254     }
12255 
12256     /**
12257      * Offset this view's vertical location by the specified number of pixels.
12258      *
12259      * @param offset the number of pixels to offset the view by
12260      */
12261     public void offsetTopAndBottom(int offset) {
12262         if (offset != 0) {
12263             final boolean matrixIsIdentity = hasIdentityMatrix();
12264             if (matrixIsIdentity) {
12265                 if (isHardwareAccelerated()) {
12266                     invalidateViewProperty(false, false);
12267                 } else {
12268                     final ViewParent p = mParent;
12269                     if (p != null && mAttachInfo != null) {
12270                         final Rect r = mAttachInfo.mTmpInvalRect;
12271                         int minTop;
12272                         int maxBottom;
12273                         int yLoc;
12274                         if (offset < 0) {
12275                             minTop = mTop + offset;
12276                             maxBottom = mBottom;
12277                             yLoc = offset;
12278                         } else {
12279                             minTop = mTop;
12280                             maxBottom = mBottom + offset;
12281                             yLoc = 0;
12282                         }
12283                         r.set(0, yLoc, mRight - mLeft, maxBottom - minTop);
12284                         p.invalidateChild(this, r);
12285                     }
12286                 }
12287             } else {
12288                 invalidateViewProperty(false, false);
12289             }
12290 
12291             mTop += offset;
12292             mBottom += offset;
12293             mRenderNode.offsetTopAndBottom(offset);
12294             if (isHardwareAccelerated()) {
12295                 invalidateViewProperty(false, false);
12296                 invalidateParentIfNeededAndWasQuickRejected();
12297             } else {
12298                 if (!matrixIsIdentity) {
12299                     invalidateViewProperty(false, true);
12300                 }
12301                 invalidateParentIfNeeded();
12302             }
12303             notifySubtreeAccessibilityStateChangedIfNeeded();
12304         }
12305     }
12306 
12307     /**
12308      * Offset this view's horizontal location by the specified amount of pixels.
12309      *
12310      * @param offset the number of pixels to offset the view by
12311      */
12312     public void offsetLeftAndRight(int offset) {
12313         if (offset != 0) {
12314             final boolean matrixIsIdentity = hasIdentityMatrix();
12315             if (matrixIsIdentity) {
12316                 if (isHardwareAccelerated()) {
12317                     invalidateViewProperty(false, false);
12318                 } else {
12319                     final ViewParent p = mParent;
12320                     if (p != null && mAttachInfo != null) {
12321                         final Rect r = mAttachInfo.mTmpInvalRect;
12322                         int minLeft;
12323                         int maxRight;
12324                         if (offset < 0) {
12325                             minLeft = mLeft + offset;
12326                             maxRight = mRight;
12327                         } else {
12328                             minLeft = mLeft;
12329                             maxRight = mRight + offset;
12330                         }
12331                         r.set(0, 0, maxRight - minLeft, mBottom - mTop);
12332                         p.invalidateChild(this, r);
12333                     }
12334                 }
12335             } else {
12336                 invalidateViewProperty(false, false);
12337             }
12338 
12339             mLeft += offset;
12340             mRight += offset;
12341             mRenderNode.offsetLeftAndRight(offset);
12342             if (isHardwareAccelerated()) {
12343                 invalidateViewProperty(false, false);
12344                 invalidateParentIfNeededAndWasQuickRejected();
12345             } else {
12346                 if (!matrixIsIdentity) {
12347                     invalidateViewProperty(false, true);
12348                 }
12349                 invalidateParentIfNeeded();
12350             }
12351             notifySubtreeAccessibilityStateChangedIfNeeded();
12352         }
12353     }
12354 
12355     /**
12356      * Get the LayoutParams associated with this view. All views should have
12357      * layout parameters. These supply parameters to the <i>parent</i> of this
12358      * view specifying how it should be arranged. There are many subclasses of
12359      * ViewGroup.LayoutParams, and these correspond to the different subclasses
12360      * of ViewGroup that are responsible for arranging their children.
12361      *
12362      * This method may return null if this View is not attached to a parent
12363      * ViewGroup or {@link #setLayoutParams(android.view.ViewGroup.LayoutParams)}
12364      * was not invoked successfully. When a View is attached to a parent
12365      * ViewGroup, this method must not return null.
12366      *
12367      * @return The LayoutParams associated with this view, or null if no
12368      *         parameters have been set yet
12369      */
12370     @ViewDebug.ExportedProperty(deepExport = true, prefix = "layout_")
12371     public ViewGroup.LayoutParams getLayoutParams() {
12372         return mLayoutParams;
12373     }
12374 
12375     /**
12376      * Set the layout parameters associated with this view. These supply
12377      * parameters to the <i>parent</i> of this view specifying how it should be
12378      * arranged. There are many subclasses of ViewGroup.LayoutParams, and these
12379      * correspond to the different subclasses of ViewGroup that are responsible
12380      * for arranging their children.
12381      *
12382      * @param params The layout parameters for this view, cannot be null
12383      */
12384     public void setLayoutParams(ViewGroup.LayoutParams params) {
12385         if (params == null) {
12386             throw new NullPointerException("Layout parameters cannot be null");
12387         }
12388         mLayoutParams = params;
12389         resolveLayoutParams();
12390         if (mParent instanceof ViewGroup) {
12391             ((ViewGroup) mParent).onSetLayoutParams(this, params);
12392         }
12393         requestLayout();
12394     }
12395 
12396     /**
12397      * Resolve the layout parameters depending on the resolved layout direction
12398      *
12399      * @hide
12400      */
12401     public void resolveLayoutParams() {
12402         if (mLayoutParams != null) {
12403             mLayoutParams.resolveLayoutDirection(getLayoutDirection());
12404         }
12405     }
12406 
12407     /**
12408      * Set the scrolled position of your view. This will cause a call to
12409      * {@link #onScrollChanged(int, int, int, int)} and the view will be
12410      * invalidated.
12411      * @param x the x position to scroll to
12412      * @param y the y position to scroll to
12413      */
12414     public void scrollTo(int x, int y) {
12415         if (mScrollX != x || mScrollY != y) {
12416             int oldX = mScrollX;
12417             int oldY = mScrollY;
12418             mScrollX = x;
12419             mScrollY = y;
12420             invalidateParentCaches();
12421             onScrollChanged(mScrollX, mScrollY, oldX, oldY);
12422             if (!awakenScrollBars()) {
12423                 postInvalidateOnAnimation();
12424             }
12425         }
12426     }
12427 
12428     /**
12429      * Move the scrolled position of your view. This will cause a call to
12430      * {@link #onScrollChanged(int, int, int, int)} and the view will be
12431      * invalidated.
12432      * @param x the amount of pixels to scroll by horizontally
12433      * @param y the amount of pixels to scroll by vertically
12434      */
12435     public void scrollBy(int x, int y) {
12436         scrollTo(mScrollX + x, mScrollY + y);
12437     }
12438 
12439     /**
12440      * <p>Trigger the scrollbars to draw. When invoked this method starts an
12441      * animation to fade the scrollbars out after a default delay. If a subclass
12442      * provides animated scrolling, the start delay should equal the duration
12443      * of the scrolling animation.</p>
12444      *
12445      * <p>The animation starts only if at least one of the scrollbars is
12446      * enabled, as specified by {@link #isHorizontalScrollBarEnabled()} and
12447      * {@link #isVerticalScrollBarEnabled()}. When the animation is started,
12448      * this method returns true, and false otherwise. If the animation is
12449      * started, this method calls {@link #invalidate()}; in that case the
12450      * caller should not call {@link #invalidate()}.</p>
12451      *
12452      * <p>This method should be invoked every time a subclass directly updates
12453      * the scroll parameters.</p>
12454      *
12455      * <p>This method is automatically invoked by {@link #scrollBy(int, int)}
12456      * and {@link #scrollTo(int, int)}.</p>
12457      *
12458      * @return true if the animation is played, false otherwise
12459      *
12460      * @see #awakenScrollBars(int)
12461      * @see #scrollBy(int, int)
12462      * @see #scrollTo(int, int)
12463      * @see #isHorizontalScrollBarEnabled()
12464      * @see #isVerticalScrollBarEnabled()
12465      * @see #setHorizontalScrollBarEnabled(boolean)
12466      * @see #setVerticalScrollBarEnabled(boolean)
12467      */
12468     protected boolean awakenScrollBars() {
12469         return mScrollCache != null &&
12470                 awakenScrollBars(mScrollCache.scrollBarDefaultDelayBeforeFade, true);
12471     }
12472 
12473     /**
12474      * Trigger the scrollbars to draw.
12475      * This method differs from awakenScrollBars() only in its default duration.
12476      * initialAwakenScrollBars() will show the scroll bars for longer than
12477      * usual to give the user more of a chance to notice them.
12478      *
12479      * @return true if the animation is played, false otherwise.
12480      */
12481     private boolean initialAwakenScrollBars() {
12482         return mScrollCache != null &&
12483                 awakenScrollBars(mScrollCache.scrollBarDefaultDelayBeforeFade * 4, true);
12484     }
12485 
12486     /**
12487      * <p>
12488      * Trigger the scrollbars to draw. When invoked this method starts an
12489      * animation to fade the scrollbars out after a fixed delay. If a subclass
12490      * provides animated scrolling, the start delay should equal the duration of
12491      * the scrolling animation.
12492      * </p>
12493      *
12494      * <p>
12495      * The animation starts only if at least one of the scrollbars is enabled,
12496      * as specified by {@link #isHorizontalScrollBarEnabled()} and
12497      * {@link #isVerticalScrollBarEnabled()}. When the animation is started,
12498      * this method returns true, and false otherwise. If the animation is
12499      * started, this method calls {@link #invalidate()}; in that case the caller
12500      * should not call {@link #invalidate()}.
12501      * </p>
12502      *
12503      * <p>
12504      * This method should be invoked every time a subclass directly updates the
12505      * scroll parameters.
12506      * </p>
12507      *
12508      * @param startDelay the delay, in milliseconds, after which the animation
12509      *        should start; when the delay is 0, the animation starts
12510      *        immediately
12511      * @return true if the animation is played, false otherwise
12512      *
12513      * @see #scrollBy(int, int)
12514      * @see #scrollTo(int, int)
12515      * @see #isHorizontalScrollBarEnabled()
12516      * @see #isVerticalScrollBarEnabled()
12517      * @see #setHorizontalScrollBarEnabled(boolean)
12518      * @see #setVerticalScrollBarEnabled(boolean)
12519      */
12520     protected boolean awakenScrollBars(int startDelay) {
12521         return awakenScrollBars(startDelay, true);
12522     }
12523 
12524     /**
12525      * <p>
12526      * Trigger the scrollbars to draw. When invoked this method starts an
12527      * animation to fade the scrollbars out after a fixed delay. If a subclass
12528      * provides animated scrolling, the start delay should equal the duration of
12529      * the scrolling animation.
12530      * </p>
12531      *
12532      * <p>
12533      * The animation starts only if at least one of the scrollbars is enabled,
12534      * as specified by {@link #isHorizontalScrollBarEnabled()} and
12535      * {@link #isVerticalScrollBarEnabled()}. When the animation is started,
12536      * this method returns true, and false otherwise. If the animation is
12537      * started, this method calls {@link #invalidate()} if the invalidate parameter
12538      * is set to true; in that case the caller
12539      * should not call {@link #invalidate()}.
12540      * </p>
12541      *
12542      * <p>
12543      * This method should be invoked every time a subclass directly updates the
12544      * scroll parameters.
12545      * </p>
12546      *
12547      * @param startDelay the delay, in milliseconds, after which the animation
12548      *        should start; when the delay is 0, the animation starts
12549      *        immediately
12550      *
12551      * @param invalidate Whether this method should call invalidate
12552      *
12553      * @return true if the animation is played, false otherwise
12554      *
12555      * @see #scrollBy(int, int)
12556      * @see #scrollTo(int, int)
12557      * @see #isHorizontalScrollBarEnabled()
12558      * @see #isVerticalScrollBarEnabled()
12559      * @see #setHorizontalScrollBarEnabled(boolean)
12560      * @see #setVerticalScrollBarEnabled(boolean)
12561      */
12562     protected boolean awakenScrollBars(int startDelay, boolean invalidate) {
12563         final ScrollabilityCache scrollCache = mScrollCache;
12564 
12565         if (scrollCache == null || !scrollCache.fadeScrollBars) {
12566             return false;
12567         }
12568 
12569         if (scrollCache.scrollBar == null) {
12570             scrollCache.scrollBar = new ScrollBarDrawable();
12571             scrollCache.scrollBar.setCallback(this);
12572             scrollCache.scrollBar.setState(getDrawableState());
12573         }
12574 
12575         if (isHorizontalScrollBarEnabled() || isVerticalScrollBarEnabled()) {
12576 
12577             if (invalidate) {
12578                 // Invalidate to show the scrollbars
12579                 postInvalidateOnAnimation();
12580             }
12581 
12582             if (scrollCache.state == ScrollabilityCache.OFF) {
12583                 // FIXME: this is copied from WindowManagerService.
12584                 // We should get this value from the system when it
12585                 // is possible to do so.
12586                 final int KEY_REPEAT_FIRST_DELAY = 750;
12587                 startDelay = Math.max(KEY_REPEAT_FIRST_DELAY, startDelay);
12588             }
12589 
12590             // Tell mScrollCache when we should start fading. This may
12591             // extend the fade start time if one was already scheduled
12592             long fadeStartTime = AnimationUtils.currentAnimationTimeMillis() + startDelay;
12593             scrollCache.fadeStartTime = fadeStartTime;
12594             scrollCache.state = ScrollabilityCache.ON;
12595 
12596             // Schedule our fader to run, unscheduling any old ones first
12597             if (mAttachInfo != null) {
12598                 mAttachInfo.mHandler.removeCallbacks(scrollCache);
12599                 mAttachInfo.mHandler.postAtTime(scrollCache, fadeStartTime);
12600             }
12601 
12602             return true;
12603         }
12604 
12605         return false;
12606     }
12607 
12608     /**
12609      * Do not invalidate views which are not visible and which are not running an animation. They
12610      * will not get drawn and they should not set dirty flags as if they will be drawn
12611      */
12612     private boolean skipInvalidate() {
12613         return (mViewFlags & VISIBILITY_MASK) != VISIBLE && mCurrentAnimation == null &&
12614                 (!(mParent instanceof ViewGroup) ||
12615                         !((ViewGroup) mParent).isViewTransitioning(this));
12616     }
12617 
12618     /**
12619      * Mark the area defined by dirty as needing to be drawn. If the view is
12620      * visible, {@link #onDraw(android.graphics.Canvas)} will be called at some
12621      * point in the future.
12622      * <p>
12623      * This must be called from a UI thread. To call from a non-UI thread, call
12624      * {@link #postInvalidate()}.
12625      * <p>
12626      * <b>WARNING:</b> In API 19 and below, this method may be destructive to
12627      * {@code dirty}.
12628      *
12629      * @param dirty the rectangle representing the bounds of the dirty region
12630      */
12631     public void invalidate(Rect dirty) {
12632         final int scrollX = mScrollX;
12633         final int scrollY = mScrollY;
12634         invalidateInternal(dirty.left - scrollX, dirty.top - scrollY,
12635                 dirty.right - scrollX, dirty.bottom - scrollY, true, false);
12636     }
12637 
12638     /**
12639      * Mark the area defined by the rect (l,t,r,b) as needing to be drawn. The
12640      * coordinates of the dirty rect are relative to the view. If the view is
12641      * visible, {@link #onDraw(android.graphics.Canvas)} will be called at some
12642      * point in the future.
12643      * <p>
12644      * This must be called from a UI thread. To call from a non-UI thread, call
12645      * {@link #postInvalidate()}.
12646      *
12647      * @param l the left position of the dirty region
12648      * @param t the top position of the dirty region
12649      * @param r the right position of the dirty region
12650      * @param b the bottom position of the dirty region
12651      */
12652     public void invalidate(int l, int t, int r, int b) {
12653         final int scrollX = mScrollX;
12654         final int scrollY = mScrollY;
12655         invalidateInternal(l - scrollX, t - scrollY, r - scrollX, b - scrollY, true, false);
12656     }
12657 
12658     /**
12659      * Invalidate the whole view. If the view is visible,
12660      * {@link #onDraw(android.graphics.Canvas)} will be called at some point in
12661      * the future.
12662      * <p>
12663      * This must be called from a UI thread. To call from a non-UI thread, call
12664      * {@link #postInvalidate()}.
12665      */
12666     public void invalidate() {
12667         invalidate(true);
12668     }
12669 
12670     /**
12671      * This is where the invalidate() work actually happens. A full invalidate()
12672      * causes the drawing cache to be invalidated, but this function can be
12673      * called with invalidateCache set to false to skip that invalidation step
12674      * for cases that do not need it (for example, a component that remains at
12675      * the same dimensions with the same content).
12676      *
12677      * @param invalidateCache Whether the drawing cache for this view should be
12678      *            invalidated as well. This is usually true for a full
12679      *            invalidate, but may be set to false if the View's contents or
12680      *            dimensions have not changed.
12681      */
12682     void invalidate(boolean invalidateCache) {
12683         invalidateInternal(0, 0, mRight - mLeft, mBottom - mTop, invalidateCache, true);
12684     }
12685 
12686     void invalidateInternal(int l, int t, int r, int b, boolean invalidateCache,
12687             boolean fullInvalidate) {
12688         if (mGhostView != null) {
12689             mGhostView.invalidate(true);
12690             return;
12691         }
12692 
12693         if (skipInvalidate()) {
12694             return;
12695         }
12696 
12697         if ((mPrivateFlags & (PFLAG_DRAWN | PFLAG_HAS_BOUNDS)) == (PFLAG_DRAWN | PFLAG_HAS_BOUNDS)
12698                 || (invalidateCache && (mPrivateFlags & PFLAG_DRAWING_CACHE_VALID) == PFLAG_DRAWING_CACHE_VALID)
12699                 || (mPrivateFlags & PFLAG_INVALIDATED) != PFLAG_INVALIDATED
12700                 || (fullInvalidate && isOpaque() != mLastIsOpaque)) {
12701             if (fullInvalidate) {
12702                 mLastIsOpaque = isOpaque();
12703                 mPrivateFlags &= ~PFLAG_DRAWN;
12704             }
12705 
12706             mPrivateFlags |= PFLAG_DIRTY;
12707 
12708             if (invalidateCache) {
12709                 mPrivateFlags |= PFLAG_INVALIDATED;
12710                 mPrivateFlags &= ~PFLAG_DRAWING_CACHE_VALID;
12711             }
12712 
12713             // Propagate the damage rectangle to the parent view.
12714             final AttachInfo ai = mAttachInfo;
12715             final ViewParent p = mParent;
12716             if (p != null && ai != null && l < r && t < b) {
12717                 final Rect damage = ai.mTmpInvalRect;
12718                 damage.set(l, t, r, b);
12719                 p.invalidateChild(this, damage);
12720             }
12721 
12722             // Damage the entire projection receiver, if necessary.
12723             if (mBackground != null && mBackground.isProjected()) {
12724                 final View receiver = getProjectionReceiver();
12725                 if (receiver != null) {
12726                     receiver.damageInParent();
12727                 }
12728             }
12729 
12730             // Damage the entire IsolatedZVolume receiving this view's shadow.
12731             if (isHardwareAccelerated() && getZ() != 0) {
12732                 damageShadowReceiver();
12733             }
12734         }
12735     }
12736 
12737     /**
12738      * @return this view's projection receiver, or {@code null} if none exists
12739      */
12740     private View getProjectionReceiver() {
12741         ViewParent p = getParent();
12742         while (p != null && p instanceof View) {
12743             final View v = (View) p;
12744             if (v.isProjectionReceiver()) {
12745                 return v;
12746             }
12747             p = p.getParent();
12748         }
12749 
12750         return null;
12751     }
12752 
12753     /**
12754      * @return whether the view is a projection receiver
12755      */
12756     private boolean isProjectionReceiver() {
12757         return mBackground != null;
12758     }
12759 
12760     /**
12761      * Damage area of the screen that can be covered by this View's shadow.
12762      *
12763      * This method will guarantee that any changes to shadows cast by a View
12764      * are damaged on the screen for future redraw.
12765      */
12766     private void damageShadowReceiver() {
12767         final AttachInfo ai = mAttachInfo;
12768         if (ai != null) {
12769             ViewParent p = getParent();
12770             if (p != null && p instanceof ViewGroup) {
12771                 final ViewGroup vg = (ViewGroup) p;
12772                 vg.damageInParent();
12773             }
12774         }
12775     }
12776 
12777     /**
12778      * Quick invalidation for View property changes (alpha, translationXY, etc.). We don't want to
12779      * set any flags or handle all of the cases handled by the default invalidation methods.
12780      * Instead, we just want to schedule a traversal in ViewRootImpl with the appropriate
12781      * dirty rect. This method calls into fast invalidation methods in ViewGroup that
12782      * walk up the hierarchy, transforming the dirty rect as necessary.
12783      *
12784      * The method also handles normal invalidation logic if display list properties are not
12785      * being used in this view. The invalidateParent and forceRedraw flags are used by that
12786      * backup approach, to handle these cases used in the various property-setting methods.
12787      *
12788      * @param invalidateParent Force a call to invalidateParentCaches() if display list properties
12789      * are not being used in this view
12790      * @param forceRedraw Mark the view as DRAWN to force the invalidation to propagate, if display
12791      * list properties are not being used in this view
12792      */
12793     void invalidateViewProperty(boolean invalidateParent, boolean forceRedraw) {
12794         if (!isHardwareAccelerated()
12795                 || !mRenderNode.isValid()
12796                 || (mPrivateFlags & PFLAG_DRAW_ANIMATION) != 0) {
12797             if (invalidateParent) {
12798                 invalidateParentCaches();
12799             }
12800             if (forceRedraw) {
12801                 mPrivateFlags |= PFLAG_DRAWN; // force another invalidation with the new orientation
12802             }
12803             invalidate(false);
12804         } else {
12805             damageInParent();
12806         }
12807         if (isHardwareAccelerated() && invalidateParent && getZ() != 0) {
12808             damageShadowReceiver();
12809         }
12810     }
12811 
12812     /**
12813      * Tells the parent view to damage this view's bounds.
12814      *
12815      * @hide
12816      */
12817     protected void damageInParent() {
12818         final AttachInfo ai = mAttachInfo;
12819         final ViewParent p = mParent;
12820         if (p != null && ai != null) {
12821             final Rect r = ai.mTmpInvalRect;
12822             r.set(0, 0, mRight - mLeft, mBottom - mTop);
12823             if (mParent instanceof ViewGroup) {
12824                 ((ViewGroup) mParent).damageChild(this, r);
12825             } else {
12826                 mParent.invalidateChild(this, r);
12827             }
12828         }
12829     }
12830 
12831     /**
12832      * Utility method to transform a given Rect by the current matrix of this view.
12833      */
12834     void transformRect(final Rect rect) {
12835         if (!getMatrix().isIdentity()) {
12836             RectF boundingRect = mAttachInfo.mTmpTransformRect;
12837             boundingRect.set(rect);
12838             getMatrix().mapRect(boundingRect);
12839             rect.set((int) Math.floor(boundingRect.left),
12840                     (int) Math.floor(boundingRect.top),
12841                     (int) Math.ceil(boundingRect.right),
12842                     (int) Math.ceil(boundingRect.bottom));
12843         }
12844     }
12845 
12846     /**
12847      * Used to indicate that the parent of this view should clear its caches. This functionality
12848      * is used to force the parent to rebuild its display list (when hardware-accelerated),
12849      * which is necessary when various parent-managed properties of the view change, such as
12850      * alpha, translationX/Y, scrollX/Y, scaleX/Y, and rotation/X/Y. This method only
12851      * clears the parent caches and does not causes an invalidate event.
12852      *
12853      * @hide
12854      */
12855     protected void invalidateParentCaches() {
12856         if (mParent instanceof View) {
12857             ((View) mParent).mPrivateFlags |= PFLAG_INVALIDATED;
12858         }
12859     }
12860 
12861     /**
12862      * Used to indicate that the parent of this view should be invalidated. This functionality
12863      * is used to force the parent to rebuild its display list (when hardware-accelerated),
12864      * which is necessary when various parent-managed properties of the view change, such as
12865      * alpha, translationX/Y, scrollX/Y, scaleX/Y, and rotation/X/Y. This method will propagate
12866      * an invalidation event to the parent.
12867      *
12868      * @hide
12869      */
12870     protected void invalidateParentIfNeeded() {
12871         if (isHardwareAccelerated() && mParent instanceof View) {
12872             ((View) mParent).invalidate(true);
12873         }
12874     }
12875 
12876     /**
12877      * @hide
12878      */
12879     protected void invalidateParentIfNeededAndWasQuickRejected() {
12880         if ((mPrivateFlags2 & PFLAG2_VIEW_QUICK_REJECTED) != 0) {
12881             // View was rejected last time it was drawn by its parent; this may have changed
12882             invalidateParentIfNeeded();
12883         }
12884     }
12885 
12886     /**
12887      * Indicates whether this View is opaque. An opaque View guarantees that it will
12888      * draw all the pixels overlapping its bounds using a fully opaque color.
12889      *
12890      * Subclasses of View should override this method whenever possible to indicate
12891      * whether an instance is opaque. Opaque Views are treated in a special way by
12892      * the View hierarchy, possibly allowing it to perform optimizations during
12893      * invalidate/draw passes.
12894      *
12895      * @return True if this View is guaranteed to be fully opaque, false otherwise.
12896      */
12897     @ViewDebug.ExportedProperty(category = "drawing")
12898     public boolean isOpaque() {
12899         return (mPrivateFlags & PFLAG_OPAQUE_MASK) == PFLAG_OPAQUE_MASK &&
12900                 getFinalAlpha() >= 1.0f;
12901     }
12902 
12903     /**
12904      * @hide
12905      */
12906     protected void computeOpaqueFlags() {
12907         // Opaque if:
12908         //   - Has a background
12909         //   - Background is opaque
12910         //   - Doesn't have scrollbars or scrollbars overlay
12911 
12912         if (mBackground != null && mBackground.getOpacity() == PixelFormat.OPAQUE) {
12913             mPrivateFlags |= PFLAG_OPAQUE_BACKGROUND;
12914         } else {
12915             mPrivateFlags &= ~PFLAG_OPAQUE_BACKGROUND;
12916         }
12917 
12918         final int flags = mViewFlags;
12919         if (((flags & SCROLLBARS_VERTICAL) == 0 && (flags & SCROLLBARS_HORIZONTAL) == 0) ||
12920                 (flags & SCROLLBARS_STYLE_MASK) == SCROLLBARS_INSIDE_OVERLAY ||
12921                 (flags & SCROLLBARS_STYLE_MASK) == SCROLLBARS_OUTSIDE_OVERLAY) {
12922             mPrivateFlags |= PFLAG_OPAQUE_SCROLLBARS;
12923         } else {
12924             mPrivateFlags &= ~PFLAG_OPAQUE_SCROLLBARS;
12925         }
12926     }
12927 
12928     /**
12929      * @hide
12930      */
12931     protected boolean hasOpaqueScrollbars() {
12932         return (mPrivateFlags & PFLAG_OPAQUE_SCROLLBARS) == PFLAG_OPAQUE_SCROLLBARS;
12933     }
12934 
12935     /**
12936      * @return A handler associated with the thread running the View. This
12937      * handler can be used to pump events in the UI events queue.
12938      */
12939     public Handler getHandler() {
12940         final AttachInfo attachInfo = mAttachInfo;
12941         if (attachInfo != null) {
12942             return attachInfo.mHandler;
12943         }
12944         return null;
12945     }
12946 
12947     /**
12948      * Gets the view root associated with the View.
12949      * @return The view root, or null if none.
12950      * @hide
12951      */
12952     public ViewRootImpl getViewRootImpl() {
12953         if (mAttachInfo != null) {
12954             return mAttachInfo.mViewRootImpl;
12955         }
12956         return null;
12957     }
12958 
12959     /**
12960      * @hide
12961      */
12962     public HardwareRenderer getHardwareRenderer() {
12963         return mAttachInfo != null ? mAttachInfo.mHardwareRenderer : null;
12964     }
12965 
12966     /**
12967      * <p>Causes the Runnable to be added to the message queue.
12968      * The runnable will be run on the user interface thread.</p>
12969      *
12970      * @param action The Runnable that will be executed.
12971      *
12972      * @return Returns true if the Runnable was successfully placed in to the
12973      *         message queue.  Returns false on failure, usually because the
12974      *         looper processing the message queue is exiting.
12975      *
12976      * @see #postDelayed
12977      * @see #removeCallbacks
12978      */
12979     public boolean post(Runnable action) {
12980         final AttachInfo attachInfo = mAttachInfo;
12981         if (attachInfo != null) {
12982             return attachInfo.mHandler.post(action);
12983         }
12984         // Assume that post will succeed later
12985         ViewRootImpl.getRunQueue().post(action);
12986         return true;
12987     }
12988 
12989     /**
12990      * <p>Causes the Runnable to be added to the message queue, to be run
12991      * after the specified amount of time elapses.
12992      * The runnable will be run on the user interface thread.</p>
12993      *
12994      * @param action The Runnable that will be executed.
12995      * @param delayMillis The delay (in milliseconds) until the Runnable
12996      *        will be executed.
12997      *
12998      * @return true if the Runnable was successfully placed in to the
12999      *         message queue.  Returns false on failure, usually because the
13000      *         looper processing the message queue is exiting.  Note that a
13001      *         result of true does not mean the Runnable will be processed --
13002      *         if the looper is quit before the delivery time of the message
13003      *         occurs then the message will be dropped.
13004      *
13005      * @see #post
13006      * @see #removeCallbacks
13007      */
13008     public boolean postDelayed(Runnable action, long delayMillis) {
13009         final AttachInfo attachInfo = mAttachInfo;
13010         if (attachInfo != null) {
13011             return attachInfo.mHandler.postDelayed(action, delayMillis);
13012         }
13013         // Assume that post will succeed later
13014         ViewRootImpl.getRunQueue().postDelayed(action, delayMillis);
13015         return true;
13016     }
13017 
13018     /**
13019      * <p>Causes the Runnable to execute on the next animation time step.
13020      * The runnable will be run on the user interface thread.</p>
13021      *
13022      * @param action The Runnable that will be executed.
13023      *
13024      * @see #postOnAnimationDelayed
13025      * @see #removeCallbacks
13026      */
13027     public void postOnAnimation(Runnable action) {
13028         final AttachInfo attachInfo = mAttachInfo;
13029         if (attachInfo != null) {
13030             attachInfo.mViewRootImpl.mChoreographer.postCallback(
13031                     Choreographer.CALLBACK_ANIMATION, action, null);
13032         } else {
13033             // Assume that post will succeed later
13034             ViewRootImpl.getRunQueue().post(action);
13035         }
13036     }
13037 
13038     /**
13039      * <p>Causes the Runnable to execute on the next animation time step,
13040      * after the specified amount of time elapses.
13041      * The runnable will be run on the user interface thread.</p>
13042      *
13043      * @param action The Runnable that will be executed.
13044      * @param delayMillis The delay (in milliseconds) until the Runnable
13045      *        will be executed.
13046      *
13047      * @see #postOnAnimation
13048      * @see #removeCallbacks
13049      */
13050     public void postOnAnimationDelayed(Runnable action, long delayMillis) {
13051         final AttachInfo attachInfo = mAttachInfo;
13052         if (attachInfo != null) {
13053             attachInfo.mViewRootImpl.mChoreographer.postCallbackDelayed(
13054                     Choreographer.CALLBACK_ANIMATION, action, null, delayMillis);
13055         } else {
13056             // Assume that post will succeed later
13057             ViewRootImpl.getRunQueue().postDelayed(action, delayMillis);
13058         }
13059     }
13060 
13061     /**
13062      * <p>Removes the specified Runnable from the message queue.</p>
13063      *
13064      * @param action The Runnable to remove from the message handling queue
13065      *
13066      * @return true if this view could ask the Handler to remove the Runnable,
13067      *         false otherwise. When the returned value is true, the Runnable
13068      *         may or may not have been actually removed from the message queue
13069      *         (for instance, if the Runnable was not in the queue already.)
13070      *
13071      * @see #post
13072      * @see #postDelayed
13073      * @see #postOnAnimation
13074      * @see #postOnAnimationDelayed
13075      */
13076     public boolean removeCallbacks(Runnable action) {
13077         if (action != null) {
13078             final AttachInfo attachInfo = mAttachInfo;
13079             if (attachInfo != null) {
13080                 attachInfo.mHandler.removeCallbacks(action);
13081                 attachInfo.mViewRootImpl.mChoreographer.removeCallbacks(
13082                         Choreographer.CALLBACK_ANIMATION, action, null);
13083             }
13084             // Assume that post will succeed later
13085             ViewRootImpl.getRunQueue().removeCallbacks(action);
13086         }
13087         return true;
13088     }
13089 
13090     /**
13091      * <p>Cause an invalidate to happen on a subsequent cycle through the event loop.
13092      * Use this to invalidate the View from a non-UI thread.</p>
13093      *
13094      * <p>This method can be invoked from outside of the UI thread
13095      * only when this View is attached to a window.</p>
13096      *
13097      * @see #invalidate()
13098      * @see #postInvalidateDelayed(long)
13099      */
13100     public void postInvalidate() {
13101         postInvalidateDelayed(0);
13102     }
13103 
13104     /**
13105      * <p>Cause an invalidate of the specified area to happen on a subsequent cycle
13106      * through the event loop. Use this to invalidate the View from a non-UI thread.</p>
13107      *
13108      * <p>This method can be invoked from outside of the UI thread
13109      * only when this View is attached to a window.</p>
13110      *
13111      * @param left The left coordinate of the rectangle to invalidate.
13112      * @param top The top coordinate of the rectangle to invalidate.
13113      * @param right The right coordinate of the rectangle to invalidate.
13114      * @param bottom The bottom coordinate of the rectangle to invalidate.
13115      *
13116      * @see #invalidate(int, int, int, int)
13117      * @see #invalidate(Rect)
13118      * @see #postInvalidateDelayed(long, int, int, int, int)
13119      */
13120     public void postInvalidate(int left, int top, int right, int bottom) {
13121         postInvalidateDelayed(0, left, top, right, bottom);
13122     }
13123 
13124     /**
13125      * <p>Cause an invalidate to happen on a subsequent cycle through the event
13126      * loop. Waits for the specified amount of time.</p>
13127      *
13128      * <p>This method can be invoked from outside of the UI thread
13129      * only when this View is attached to a window.</p>
13130      *
13131      * @param delayMilliseconds the duration in milliseconds to delay the
13132      *         invalidation by
13133      *
13134      * @see #invalidate()
13135      * @see #postInvalidate()
13136      */
13137     public void postInvalidateDelayed(long delayMilliseconds) {
13138         // We try only with the AttachInfo because there's no point in invalidating
13139         // if we are not attached to our window
13140         final AttachInfo attachInfo = mAttachInfo;
13141         if (attachInfo != null) {
13142             attachInfo.mViewRootImpl.dispatchInvalidateDelayed(this, delayMilliseconds);
13143         }
13144     }
13145 
13146     /**
13147      * <p>Cause an invalidate of the specified area to happen on a subsequent cycle
13148      * through the event loop. Waits for the specified amount of time.</p>
13149      *
13150      * <p>This method can be invoked from outside of the UI thread
13151      * only when this View is attached to a window.</p>
13152      *
13153      * @param delayMilliseconds the duration in milliseconds to delay the
13154      *         invalidation by
13155      * @param left The left coordinate of the rectangle to invalidate.
13156      * @param top The top coordinate of the rectangle to invalidate.
13157      * @param right The right coordinate of the rectangle to invalidate.
13158      * @param bottom The bottom coordinate of the rectangle to invalidate.
13159      *
13160      * @see #invalidate(int, int, int, int)
13161      * @see #invalidate(Rect)
13162      * @see #postInvalidate(int, int, int, int)
13163      */
13164     public void postInvalidateDelayed(long delayMilliseconds, int left, int top,
13165             int right, int bottom) {
13166 
13167         // We try only with the AttachInfo because there's no point in invalidating
13168         // if we are not attached to our window
13169         final AttachInfo attachInfo = mAttachInfo;
13170         if (attachInfo != null) {
13171             final AttachInfo.InvalidateInfo info = AttachInfo.InvalidateInfo.obtain();
13172             info.target = this;
13173             info.left = left;
13174             info.top = top;
13175             info.right = right;
13176             info.bottom = bottom;
13177 
13178             attachInfo.mViewRootImpl.dispatchInvalidateRectDelayed(info, delayMilliseconds);
13179         }
13180     }
13181 
13182     /**
13183      * <p>Cause an invalidate to happen on the next animation time step, typically the
13184      * next display frame.</p>
13185      *
13186      * <p>This method can be invoked from outside of the UI thread
13187      * only when this View is attached to a window.</p>
13188      *
13189      * @see #invalidate()
13190      */
13191     public void postInvalidateOnAnimation() {
13192         // We try only with the AttachInfo because there's no point in invalidating
13193         // if we are not attached to our window
13194         final AttachInfo attachInfo = mAttachInfo;
13195         if (attachInfo != null) {
13196             attachInfo.mViewRootImpl.dispatchInvalidateOnAnimation(this);
13197         }
13198     }
13199 
13200     /**
13201      * <p>Cause an invalidate of the specified area to happen on the next animation
13202      * time step, typically the next display frame.</p>
13203      *
13204      * <p>This method can be invoked from outside of the UI thread
13205      * only when this View is attached to a window.</p>
13206      *
13207      * @param left The left coordinate of the rectangle to invalidate.
13208      * @param top The top coordinate of the rectangle to invalidate.
13209      * @param right The right coordinate of the rectangle to invalidate.
13210      * @param bottom The bottom coordinate of the rectangle to invalidate.
13211      *
13212      * @see #invalidate(int, int, int, int)
13213      * @see #invalidate(Rect)
13214      */
13215     public void postInvalidateOnAnimation(int left, int top, int right, int bottom) {
13216         // We try only with the AttachInfo because there's no point in invalidating
13217         // if we are not attached to our window
13218         final AttachInfo attachInfo = mAttachInfo;
13219         if (attachInfo != null) {
13220             final AttachInfo.InvalidateInfo info = AttachInfo.InvalidateInfo.obtain();
13221             info.target = this;
13222             info.left = left;
13223             info.top = top;
13224             info.right = right;
13225             info.bottom = bottom;
13226 
13227             attachInfo.mViewRootImpl.dispatchInvalidateRectOnAnimation(info);
13228         }
13229     }
13230 
13231     /**
13232      * Post a callback to send a {@link AccessibilityEvent#TYPE_VIEW_SCROLLED} event.
13233      * This event is sent at most once every
13234      * {@link ViewConfiguration#getSendRecurringAccessibilityEventsInterval()}.
13235      */
13236     private void postSendViewScrolledAccessibilityEventCallback() {
13237         if (mSendViewScrolledAccessibilityEvent == null) {
13238             mSendViewScrolledAccessibilityEvent = new SendViewScrolledAccessibilityEvent();
13239         }
13240         if (!mSendViewScrolledAccessibilityEvent.mIsPending) {
13241             mSendViewScrolledAccessibilityEvent.mIsPending = true;
13242             postDelayed(mSendViewScrolledAccessibilityEvent,
13243                     ViewConfiguration.getSendRecurringAccessibilityEventsInterval());
13244         }
13245     }
13246 
13247     /**
13248      * Called by a parent to request that a child update its values for mScrollX
13249      * and mScrollY if necessary. This will typically be done if the child is
13250      * animating a scroll using a {@link android.widget.Scroller Scroller}
13251      * object.
13252      */
13253     public void computeScroll() {
13254     }
13255 
13256     /**
13257      * <p>Indicate whether the horizontal edges are faded when the view is
13258      * scrolled horizontally.</p>
13259      *
13260      * @return true if the horizontal edges should are faded on scroll, false
13261      *         otherwise
13262      *
13263      * @see #setHorizontalFadingEdgeEnabled(boolean)
13264      *
13265      * @attr ref android.R.styleable#View_requiresFadingEdge
13266      */
13267     public boolean isHorizontalFadingEdgeEnabled() {
13268         return (mViewFlags & FADING_EDGE_HORIZONTAL) == FADING_EDGE_HORIZONTAL;
13269     }
13270 
13271     /**
13272      * <p>Define whether the horizontal edges should be faded when this view
13273      * is scrolled horizontally.</p>
13274      *
13275      * @param horizontalFadingEdgeEnabled true if the horizontal edges should
13276      *                                    be faded when the view is scrolled
13277      *                                    horizontally
13278      *
13279      * @see #isHorizontalFadingEdgeEnabled()
13280      *
13281      * @attr ref android.R.styleable#View_requiresFadingEdge
13282      */
13283     public void setHorizontalFadingEdgeEnabled(boolean horizontalFadingEdgeEnabled) {
13284         if (isHorizontalFadingEdgeEnabled() != horizontalFadingEdgeEnabled) {
13285             if (horizontalFadingEdgeEnabled) {
13286                 initScrollCache();
13287             }
13288 
13289             mViewFlags ^= FADING_EDGE_HORIZONTAL;
13290         }
13291     }
13292 
13293     /**
13294      * <p>Indicate whether the vertical edges are faded when the view is
13295      * scrolled horizontally.</p>
13296      *
13297      * @return true if the vertical edges should are faded on scroll, false
13298      *         otherwise
13299      *
13300      * @see #setVerticalFadingEdgeEnabled(boolean)
13301      *
13302      * @attr ref android.R.styleable#View_requiresFadingEdge
13303      */
13304     public boolean isVerticalFadingEdgeEnabled() {
13305         return (mViewFlags & FADING_EDGE_VERTICAL) == FADING_EDGE_VERTICAL;
13306     }
13307 
13308     /**
13309      * <p>Define whether the vertical edges should be faded when this view
13310      * is scrolled vertically.</p>
13311      *
13312      * @param verticalFadingEdgeEnabled true if the vertical edges should
13313      *                                  be faded when the view is scrolled
13314      *                                  vertically
13315      *
13316      * @see #isVerticalFadingEdgeEnabled()
13317      *
13318      * @attr ref android.R.styleable#View_requiresFadingEdge
13319      */
13320     public void setVerticalFadingEdgeEnabled(boolean verticalFadingEdgeEnabled) {
13321         if (isVerticalFadingEdgeEnabled() != verticalFadingEdgeEnabled) {
13322             if (verticalFadingEdgeEnabled) {
13323                 initScrollCache();
13324             }
13325 
13326             mViewFlags ^= FADING_EDGE_VERTICAL;
13327         }
13328     }
13329 
13330     /**
13331      * Returns the strength, or intensity, of the top faded edge. The strength is
13332      * a value between 0.0 (no fade) and 1.0 (full fade). The default implementation
13333      * returns 0.0 or 1.0 but no value in between.
13334      *
13335      * Subclasses should override this method to provide a smoother fade transition
13336      * when scrolling occurs.
13337      *
13338      * @return the intensity of the top fade as a float between 0.0f and 1.0f
13339      */
13340     protected float getTopFadingEdgeStrength() {
13341         return computeVerticalScrollOffset() > 0 ? 1.0f : 0.0f;
13342     }
13343 
13344     /**
13345      * Returns the strength, or intensity, of the bottom faded edge. The strength is
13346      * a value between 0.0 (no fade) and 1.0 (full fade). The default implementation
13347      * returns 0.0 or 1.0 but no value in between.
13348      *
13349      * Subclasses should override this method to provide a smoother fade transition
13350      * when scrolling occurs.
13351      *
13352      * @return the intensity of the bottom fade as a float between 0.0f and 1.0f
13353      */
13354     protected float getBottomFadingEdgeStrength() {
13355         return computeVerticalScrollOffset() + computeVerticalScrollExtent() <
13356                 computeVerticalScrollRange() ? 1.0f : 0.0f;
13357     }
13358 
13359     /**
13360      * Returns the strength, or intensity, of the left faded edge. The strength is
13361      * a value between 0.0 (no fade) and 1.0 (full fade). The default implementation
13362      * returns 0.0 or 1.0 but no value in between.
13363      *
13364      * Subclasses should override this method to provide a smoother fade transition
13365      * when scrolling occurs.
13366      *
13367      * @return the intensity of the left fade as a float between 0.0f and 1.0f
13368      */
13369     protected float getLeftFadingEdgeStrength() {
13370         return computeHorizontalScrollOffset() > 0 ? 1.0f : 0.0f;
13371     }
13372 
13373     /**
13374      * Returns the strength, or intensity, of the right faded edge. The strength is
13375      * a value between 0.0 (no fade) and 1.0 (full fade). The default implementation
13376      * returns 0.0 or 1.0 but no value in between.
13377      *
13378      * Subclasses should override this method to provide a smoother fade transition
13379      * when scrolling occurs.
13380      *
13381      * @return the intensity of the right fade as a float between 0.0f and 1.0f
13382      */
13383     protected float getRightFadingEdgeStrength() {
13384         return computeHorizontalScrollOffset() + computeHorizontalScrollExtent() <
13385                 computeHorizontalScrollRange() ? 1.0f : 0.0f;
13386     }
13387 
13388     /**
13389      * <p>Indicate whether the horizontal scrollbar should be drawn or not. The
13390      * scrollbar is not drawn by default.</p>
13391      *
13392      * @return true if the horizontal scrollbar should be painted, false
13393      *         otherwise
13394      *
13395      * @see #setHorizontalScrollBarEnabled(boolean)
13396      */
13397     public boolean isHorizontalScrollBarEnabled() {
13398         return (mViewFlags & SCROLLBARS_HORIZONTAL) == SCROLLBARS_HORIZONTAL;
13399     }
13400 
13401     /**
13402      * <p>Define whether the horizontal scrollbar should be drawn or not. The
13403      * scrollbar is not drawn by default.</p>
13404      *
13405      * @param horizontalScrollBarEnabled true if the horizontal scrollbar should
13406      *                                   be painted
13407      *
13408      * @see #isHorizontalScrollBarEnabled()
13409      */
13410     public void setHorizontalScrollBarEnabled(boolean horizontalScrollBarEnabled) {
13411         if (isHorizontalScrollBarEnabled() != horizontalScrollBarEnabled) {
13412             mViewFlags ^= SCROLLBARS_HORIZONTAL;
13413             computeOpaqueFlags();
13414             resolvePadding();
13415         }
13416     }
13417 
13418     /**
13419      * <p>Indicate whether the vertical scrollbar should be drawn or not. The
13420      * scrollbar is not drawn by default.</p>
13421      *
13422      * @return true if the vertical scrollbar should be painted, false
13423      *         otherwise
13424      *
13425      * @see #setVerticalScrollBarEnabled(boolean)
13426      */
13427     public boolean isVerticalScrollBarEnabled() {
13428         return (mViewFlags & SCROLLBARS_VERTICAL) == SCROLLBARS_VERTICAL;
13429     }
13430 
13431     /**
13432      * <p>Define whether the vertical scrollbar should be drawn or not. The
13433      * scrollbar is not drawn by default.</p>
13434      *
13435      * @param verticalScrollBarEnabled true if the vertical scrollbar should
13436      *                                 be painted
13437      *
13438      * @see #isVerticalScrollBarEnabled()
13439      */
13440     public void setVerticalScrollBarEnabled(boolean verticalScrollBarEnabled) {
13441         if (isVerticalScrollBarEnabled() != verticalScrollBarEnabled) {
13442             mViewFlags ^= SCROLLBARS_VERTICAL;
13443             computeOpaqueFlags();
13444             resolvePadding();
13445         }
13446     }
13447 
13448     /**
13449      * @hide
13450      */
13451     protected void recomputePadding() {
13452         internalSetPadding(mUserPaddingLeft, mPaddingTop, mUserPaddingRight, mUserPaddingBottom);
13453     }
13454 
13455     /**
13456      * Define whether scrollbars will fade when the view is not scrolling.
13457      *
13458      * @param fadeScrollbars whether to enable fading
13459      *
13460      * @attr ref android.R.styleable#View_fadeScrollbars
13461      */
13462     public void setScrollbarFadingEnabled(boolean fadeScrollbars) {
13463         initScrollCache();
13464         final ScrollabilityCache scrollabilityCache = mScrollCache;
13465         scrollabilityCache.fadeScrollBars = fadeScrollbars;
13466         if (fadeScrollbars) {
13467             scrollabilityCache.state = ScrollabilityCache.OFF;
13468         } else {
13469             scrollabilityCache.state = ScrollabilityCache.ON;
13470         }
13471     }
13472 
13473     /**
13474      *
13475      * Returns true if scrollbars will fade when this view is not scrolling
13476      *
13477      * @return true if scrollbar fading is enabled
13478      *
13479      * @attr ref android.R.styleable#View_fadeScrollbars
13480      */
13481     public boolean isScrollbarFadingEnabled() {
13482         return mScrollCache != null && mScrollCache.fadeScrollBars;
13483     }
13484 
13485     /**
13486      *
13487      * Returns the delay before scrollbars fade.
13488      *
13489      * @return the delay before scrollbars fade
13490      *
13491      * @attr ref android.R.styleable#View_scrollbarDefaultDelayBeforeFade
13492      */
13493     public int getScrollBarDefaultDelayBeforeFade() {
13494         return mScrollCache == null ? ViewConfiguration.getScrollDefaultDelay() :
13495                 mScrollCache.scrollBarDefaultDelayBeforeFade;
13496     }
13497 
13498     /**
13499      * Define the delay before scrollbars fade.
13500      *
13501      * @param scrollBarDefaultDelayBeforeFade - the delay before scrollbars fade
13502      *
13503      * @attr ref android.R.styleable#View_scrollbarDefaultDelayBeforeFade
13504      */
13505     public void setScrollBarDefaultDelayBeforeFade(int scrollBarDefaultDelayBeforeFade) {
13506         getScrollCache().scrollBarDefaultDelayBeforeFade = scrollBarDefaultDelayBeforeFade;
13507     }
13508 
13509     /**
13510      *
13511      * Returns the scrollbar fade duration.
13512      *
13513      * @return the scrollbar fade duration
13514      *
13515      * @attr ref android.R.styleable#View_scrollbarFadeDuration
13516      */
13517     public int getScrollBarFadeDuration() {
13518         return mScrollCache == null ? ViewConfiguration.getScrollBarFadeDuration() :
13519                 mScrollCache.scrollBarFadeDuration;
13520     }
13521 
13522     /**
13523      * Define the scrollbar fade duration.
13524      *
13525      * @param scrollBarFadeDuration - the scrollbar fade duration
13526      *
13527      * @attr ref android.R.styleable#View_scrollbarFadeDuration
13528      */
13529     public void setScrollBarFadeDuration(int scrollBarFadeDuration) {
13530         getScrollCache().scrollBarFadeDuration = scrollBarFadeDuration;
13531     }
13532 
13533     /**
13534      *
13535      * Returns the scrollbar size.
13536      *
13537      * @return the scrollbar size
13538      *
13539      * @attr ref android.R.styleable#View_scrollbarSize
13540      */
13541     public int getScrollBarSize() {
13542         return mScrollCache == null ? ViewConfiguration.get(mContext).getScaledScrollBarSize() :
13543                 mScrollCache.scrollBarSize;
13544     }
13545 
13546     /**
13547      * Define the scrollbar size.
13548      *
13549      * @param scrollBarSize - the scrollbar size
13550      *
13551      * @attr ref android.R.styleable#View_scrollbarSize
13552      */
13553     public void setScrollBarSize(int scrollBarSize) {
13554         getScrollCache().scrollBarSize = scrollBarSize;
13555     }
13556 
13557     /**
13558      * <p>Specify the style of the scrollbars. The scrollbars can be overlaid or
13559      * inset. When inset, they add to the padding of the view. And the scrollbars
13560      * can be drawn inside the padding area or on the edge of the view. For example,
13561      * if a view has a background drawable and you want to draw the scrollbars
13562      * inside the padding specified by the drawable, you can use
13563      * SCROLLBARS_INSIDE_OVERLAY or SCROLLBARS_INSIDE_INSET. If you want them to
13564      * appear at the edge of the view, ignoring the padding, then you can use
13565      * SCROLLBARS_OUTSIDE_OVERLAY or SCROLLBARS_OUTSIDE_INSET.</p>
13566      * @param style the style of the scrollbars. Should be one of
13567      * SCROLLBARS_INSIDE_OVERLAY, SCROLLBARS_INSIDE_INSET,
13568      * SCROLLBARS_OUTSIDE_OVERLAY or SCROLLBARS_OUTSIDE_INSET.
13569      * @see #SCROLLBARS_INSIDE_OVERLAY
13570      * @see #SCROLLBARS_INSIDE_INSET
13571      * @see #SCROLLBARS_OUTSIDE_OVERLAY
13572      * @see #SCROLLBARS_OUTSIDE_INSET
13573      *
13574      * @attr ref android.R.styleable#View_scrollbarStyle
13575      */
13576     public void setScrollBarStyle(@ScrollBarStyle int style) {
13577         if (style != (mViewFlags & SCROLLBARS_STYLE_MASK)) {
13578             mViewFlags = (mViewFlags & ~SCROLLBARS_STYLE_MASK) | (style & SCROLLBARS_STYLE_MASK);
13579             computeOpaqueFlags();
13580             resolvePadding();
13581         }
13582     }
13583 
13584     /**
13585      * <p>Returns the current scrollbar style.</p>
13586      * @return the current scrollbar style
13587      * @see #SCROLLBARS_INSIDE_OVERLAY
13588      * @see #SCROLLBARS_INSIDE_INSET
13589      * @see #SCROLLBARS_OUTSIDE_OVERLAY
13590      * @see #SCROLLBARS_OUTSIDE_INSET
13591      *
13592      * @attr ref android.R.styleable#View_scrollbarStyle
13593      */
13594     @ViewDebug.ExportedProperty(mapping = {
13595             @ViewDebug.IntToString(from = SCROLLBARS_INSIDE_OVERLAY, to = "INSIDE_OVERLAY"),
13596             @ViewDebug.IntToString(from = SCROLLBARS_INSIDE_INSET, to = "INSIDE_INSET"),
13597             @ViewDebug.IntToString(from = SCROLLBARS_OUTSIDE_OVERLAY, to = "OUTSIDE_OVERLAY"),
13598             @ViewDebug.IntToString(from = SCROLLBARS_OUTSIDE_INSET, to = "OUTSIDE_INSET")
13599     })
13600     @ScrollBarStyle
13601     public int getScrollBarStyle() {
13602         return mViewFlags & SCROLLBARS_STYLE_MASK;
13603     }
13604 
13605     /**
13606      * <p>Compute the horizontal range that the horizontal scrollbar
13607      * represents.</p>
13608      *
13609      * <p>The range is expressed in arbitrary units that must be the same as the
13610      * units used by {@link #computeHorizontalScrollExtent()} and
13611      * {@link #computeHorizontalScrollOffset()}.</p>
13612      *
13613      * <p>The default range is the drawing width of this view.</p>
13614      *
13615      * @return the total horizontal range represented by the horizontal
13616      *         scrollbar
13617      *
13618      * @see #computeHorizontalScrollExtent()
13619      * @see #computeHorizontalScrollOffset()
13620      * @see android.widget.ScrollBarDrawable
13621      */
13622     protected int computeHorizontalScrollRange() {
13623         return getWidth();
13624     }
13625 
13626     /**
13627      * <p>Compute the horizontal offset of the horizontal scrollbar's thumb
13628      * within the horizontal range. This value is used to compute the position
13629      * of the thumb within the scrollbar's track.</p>
13630      *
13631      * <p>The range is expressed in arbitrary units that must be the same as the
13632      * units used by {@link #computeHorizontalScrollRange()} and
13633      * {@link #computeHorizontalScrollExtent()}.</p>
13634      *
13635      * <p>The default offset is the scroll offset of this view.</p>
13636      *
13637      * @return the horizontal offset of the scrollbar's thumb
13638      *
13639      * @see #computeHorizontalScrollRange()
13640      * @see #computeHorizontalScrollExtent()
13641      * @see android.widget.ScrollBarDrawable
13642      */
13643     protected int computeHorizontalScrollOffset() {
13644         return mScrollX;
13645     }
13646 
13647     /**
13648      * <p>Compute the horizontal extent of the horizontal scrollbar's thumb
13649      * within the horizontal range. This value is used to compute the length
13650      * of the thumb within the scrollbar's track.</p>
13651      *
13652      * <p>The range is expressed in arbitrary units that must be the same as the
13653      * units used by {@link #computeHorizontalScrollRange()} and
13654      * {@link #computeHorizontalScrollOffset()}.</p>
13655      *
13656      * <p>The default extent is the drawing width of this view.</p>
13657      *
13658      * @return the horizontal extent of the scrollbar's thumb
13659      *
13660      * @see #computeHorizontalScrollRange()
13661      * @see #computeHorizontalScrollOffset()
13662      * @see android.widget.ScrollBarDrawable
13663      */
13664     protected int computeHorizontalScrollExtent() {
13665         return getWidth();
13666     }
13667 
13668     /**
13669      * <p>Compute the vertical range that the vertical scrollbar represents.</p>
13670      *
13671      * <p>The range is expressed in arbitrary units that must be the same as the
13672      * units used by {@link #computeVerticalScrollExtent()} and
13673      * {@link #computeVerticalScrollOffset()}.</p>
13674      *
13675      * @return the total vertical range represented by the vertical scrollbar
13676      *
13677      * <p>The default range is the drawing height of this view.</p>
13678      *
13679      * @see #computeVerticalScrollExtent()
13680      * @see #computeVerticalScrollOffset()
13681      * @see android.widget.ScrollBarDrawable
13682      */
13683     protected int computeVerticalScrollRange() {
13684         return getHeight();
13685     }
13686 
13687     /**
13688      * <p>Compute the vertical offset of the vertical scrollbar's thumb
13689      * within the horizontal range. This value is used to compute the position
13690      * of the thumb within the scrollbar's track.</p>
13691      *
13692      * <p>The range is expressed in arbitrary units that must be the same as the
13693      * units used by {@link #computeVerticalScrollRange()} and
13694      * {@link #computeVerticalScrollExtent()}.</p>
13695      *
13696      * <p>The default offset is the scroll offset of this view.</p>
13697      *
13698      * @return the vertical offset of the scrollbar's thumb
13699      *
13700      * @see #computeVerticalScrollRange()
13701      * @see #computeVerticalScrollExtent()
13702      * @see android.widget.ScrollBarDrawable
13703      */
13704     protected int computeVerticalScrollOffset() {
13705         return mScrollY;
13706     }
13707 
13708     /**
13709      * <p>Compute the vertical extent of the vertical scrollbar's thumb
13710      * within the vertical range. This value is used to compute the length
13711      * of the thumb within the scrollbar's track.</p>
13712      *
13713      * <p>The range is expressed in arbitrary units that must be the same as the
13714      * units used by {@link #computeVerticalScrollRange()} and
13715      * {@link #computeVerticalScrollOffset()}.</p>
13716      *
13717      * <p>The default extent is the drawing height of this view.</p>
13718      *
13719      * @return the vertical extent of the scrollbar's thumb
13720      *
13721      * @see #computeVerticalScrollRange()
13722      * @see #computeVerticalScrollOffset()
13723      * @see android.widget.ScrollBarDrawable
13724      */
13725     protected int computeVerticalScrollExtent() {
13726         return getHeight();
13727     }
13728 
13729     /**
13730      * Check if this view can be scrolled horizontally in a certain direction.
13731      *
13732      * @param direction Negative to check scrolling left, positive to check scrolling right.
13733      * @return true if this view can be scrolled in the specified direction, false otherwise.
13734      */
13735     public boolean canScrollHorizontally(int direction) {
13736         final int offset = computeHorizontalScrollOffset();
13737         final int range = computeHorizontalScrollRange() - computeHorizontalScrollExtent();
13738         if (range == 0) return false;
13739         if (direction < 0) {
13740             return offset > 0;
13741         } else {
13742             return offset < range - 1;
13743         }
13744     }
13745 
13746     /**
13747      * Check if this view can be scrolled vertically in a certain direction.
13748      *
13749      * @param direction Negative to check scrolling up, positive to check scrolling down.
13750      * @return true if this view can be scrolled in the specified direction, false otherwise.
13751      */
13752     public boolean canScrollVertically(int direction) {
13753         final int offset = computeVerticalScrollOffset();
13754         final int range = computeVerticalScrollRange() - computeVerticalScrollExtent();
13755         if (range == 0) return false;
13756         if (direction < 0) {
13757             return offset > 0;
13758         } else {
13759             return offset < range - 1;
13760         }
13761     }
13762 
13763     void getScrollIndicatorBounds(@NonNull Rect out) {
13764         out.left = mScrollX;
13765         out.right = mScrollX + mRight - mLeft;
13766         out.top = mScrollY;
13767         out.bottom = mScrollY + mBottom - mTop;
13768     }
13769 
13770     private void onDrawScrollIndicators(Canvas c) {
13771         if ((mPrivateFlags3 & SCROLL_INDICATORS_PFLAG3_MASK) == 0) {
13772             // No scroll indicators enabled.
13773             return;
13774         }
13775 
13776         final Drawable dr = mScrollIndicatorDrawable;
13777         if (dr == null) {
13778             // Scroll indicators aren't supported here.
13779             return;
13780         }
13781 
13782         final int h = dr.getIntrinsicHeight();
13783         final int w = dr.getIntrinsicWidth();
13784         final Rect rect = mAttachInfo.mTmpInvalRect;
13785         getScrollIndicatorBounds(rect);
13786 
13787         if ((mPrivateFlags3 & PFLAG3_SCROLL_INDICATOR_TOP) != 0) {
13788             final boolean canScrollUp = canScrollVertically(-1);
13789             if (canScrollUp) {
13790                 dr.setBounds(rect.left, rect.top, rect.right, rect.top + h);
13791                 dr.draw(c);
13792             }
13793         }
13794 
13795         if ((mPrivateFlags3 & PFLAG3_SCROLL_INDICATOR_BOTTOM) != 0) {
13796             final boolean canScrollDown = canScrollVertically(1);
13797             if (canScrollDown) {
13798                 dr.setBounds(rect.left, rect.bottom - h, rect.right, rect.bottom);
13799                 dr.draw(c);
13800             }
13801         }
13802 
13803         final int leftRtl;
13804         final int rightRtl;
13805         if (getLayoutDirection() == LAYOUT_DIRECTION_RTL) {
13806             leftRtl = PFLAG3_SCROLL_INDICATOR_END;
13807             rightRtl = PFLAG3_SCROLL_INDICATOR_START;
13808         } else {
13809             leftRtl = PFLAG3_SCROLL_INDICATOR_START;
13810             rightRtl = PFLAG3_SCROLL_INDICATOR_END;
13811         }
13812 
13813         final int leftMask = PFLAG3_SCROLL_INDICATOR_LEFT | leftRtl;
13814         if ((mPrivateFlags3 & leftMask) != 0) {
13815             final boolean canScrollLeft = canScrollHorizontally(-1);
13816             if (canScrollLeft) {
13817                 dr.setBounds(rect.left, rect.top, rect.left + w, rect.bottom);
13818                 dr.draw(c);
13819             }
13820         }
13821 
13822         final int rightMask = PFLAG3_SCROLL_INDICATOR_RIGHT | rightRtl;
13823         if ((mPrivateFlags3 & rightMask) != 0) {
13824             final boolean canScrollRight = canScrollHorizontally(1);
13825             if (canScrollRight) {
13826                 dr.setBounds(rect.right - w, rect.top, rect.right, rect.bottom);
13827                 dr.draw(c);
13828             }
13829         }
13830     }
13831 
13832     /**
13833      * <p>Request the drawing of the horizontal and the vertical scrollbar. The
13834      * scrollbars are painted only if they have been awakened first.</p>
13835      *
13836      * @param canvas the canvas on which to draw the scrollbars
13837      *
13838      * @see #awakenScrollBars(int)
13839      */
13840     protected final void onDrawScrollBars(Canvas canvas) {
13841         // scrollbars are drawn only when the animation is running
13842         final ScrollabilityCache cache = mScrollCache;
13843         if (cache != null) {
13844 
13845             int state = cache.state;
13846 
13847             if (state == ScrollabilityCache.OFF) {
13848                 return;
13849             }
13850 
13851             boolean invalidate = false;
13852 
13853             if (state == ScrollabilityCache.FADING) {
13854                 // We're fading -- get our fade interpolation
13855                 if (cache.interpolatorValues == null) {
13856                     cache.interpolatorValues = new float[1];
13857                 }
13858 
13859                 float[] values = cache.interpolatorValues;
13860 
13861                 // Stops the animation if we're done
13862                 if (cache.scrollBarInterpolator.timeToValues(values) ==
13863                         Interpolator.Result.FREEZE_END) {
13864                     cache.state = ScrollabilityCache.OFF;
13865                 } else {
13866                     cache.scrollBar.mutate().setAlpha(Math.round(values[0]));
13867                 }
13868 
13869                 // This will make the scroll bars inval themselves after
13870                 // drawing. We only want this when we're fading so that
13871                 // we prevent excessive redraws
13872                 invalidate = true;
13873             } else {
13874                 // We're just on -- but we may have been fading before so
13875                 // reset alpha
13876                 cache.scrollBar.mutate().setAlpha(255);
13877             }
13878 
13879 
13880             final int viewFlags = mViewFlags;
13881 
13882             final boolean drawHorizontalScrollBar =
13883                 (viewFlags & SCROLLBARS_HORIZONTAL) == SCROLLBARS_HORIZONTAL;
13884             final boolean drawVerticalScrollBar =
13885                 (viewFlags & SCROLLBARS_VERTICAL) == SCROLLBARS_VERTICAL
13886                 && !isVerticalScrollBarHidden();
13887 
13888             if (drawVerticalScrollBar || drawHorizontalScrollBar) {
13889                 final int width = mRight - mLeft;
13890                 final int height = mBottom - mTop;
13891 
13892                 final ScrollBarDrawable scrollBar = cache.scrollBar;
13893 
13894                 final int scrollX = mScrollX;
13895                 final int scrollY = mScrollY;
13896                 final int inside = (viewFlags & SCROLLBARS_OUTSIDE_MASK) == 0 ? ~0 : 0;
13897 
13898                 int left;
13899                 int top;
13900                 int right;
13901                 int bottom;
13902 
13903                 if (drawHorizontalScrollBar) {
13904                     int size = scrollBar.getSize(false);
13905                     if (size <= 0) {
13906                         size = cache.scrollBarSize;
13907                     }
13908 
13909                     scrollBar.setParameters(computeHorizontalScrollRange(),
13910                                             computeHorizontalScrollOffset(),
13911                                             computeHorizontalScrollExtent(), false);
13912                     final int verticalScrollBarGap = drawVerticalScrollBar ?
13913                             getVerticalScrollbarWidth() : 0;
13914                     top = scrollY + height - size - (mUserPaddingBottom & inside);
13915                     left = scrollX + (mPaddingLeft & inside);
13916                     right = scrollX + width - (mUserPaddingRight & inside) - verticalScrollBarGap;
13917                     bottom = top + size;
13918                     onDrawHorizontalScrollBar(canvas, scrollBar, left, top, right, bottom);
13919                     if (invalidate) {
13920                         invalidate(left, top, right, bottom);
13921                     }
13922                 }
13923 
13924                 if (drawVerticalScrollBar) {
13925                     int size = scrollBar.getSize(true);
13926                     if (size <= 0) {
13927                         size = cache.scrollBarSize;
13928                     }
13929 
13930                     scrollBar.setParameters(computeVerticalScrollRange(),
13931                                             computeVerticalScrollOffset(),
13932                                             computeVerticalScrollExtent(), true);
13933                     int verticalScrollbarPosition = mVerticalScrollbarPosition;
13934                     if (verticalScrollbarPosition == SCROLLBAR_POSITION_DEFAULT) {
13935                         verticalScrollbarPosition = isLayoutRtl() ?
13936                                 SCROLLBAR_POSITION_LEFT : SCROLLBAR_POSITION_RIGHT;
13937                     }
13938                     switch (verticalScrollbarPosition) {
13939                         default:
13940                         case SCROLLBAR_POSITION_RIGHT:
13941                             left = scrollX + width - size - (mUserPaddingRight & inside);
13942                             break;
13943                         case SCROLLBAR_POSITION_LEFT:
13944                             left = scrollX + (mUserPaddingLeft & inside);
13945                             break;
13946                     }
13947                     top = scrollY + (mPaddingTop & inside);
13948                     right = left + size;
13949                     bottom = scrollY + height - (mUserPaddingBottom & inside);
13950                     onDrawVerticalScrollBar(canvas, scrollBar, left, top, right, bottom);
13951                     if (invalidate) {
13952                         invalidate(left, top, right, bottom);
13953                     }
13954                 }
13955             }
13956         }
13957     }
13958 
13959     /**
13960      * Override this if the vertical scrollbar needs to be hidden in a subclass, like when
13961      * FastScroller is visible.
13962      * @return whether to temporarily hide the vertical scrollbar
13963      * @hide
13964      */
13965     protected boolean isVerticalScrollBarHidden() {
13966         return false;
13967     }
13968 
13969     /**
13970      * <p>Draw the horizontal scrollbar if
13971      * {@link #isHorizontalScrollBarEnabled()} returns true.</p>
13972      *
13973      * @param canvas the canvas on which to draw the scrollbar
13974      * @param scrollBar the scrollbar's drawable
13975      *
13976      * @see #isHorizontalScrollBarEnabled()
13977      * @see #computeHorizontalScrollRange()
13978      * @see #computeHorizontalScrollExtent()
13979      * @see #computeHorizontalScrollOffset()
13980      * @see android.widget.ScrollBarDrawable
13981      * @hide
13982      */
13983     protected void onDrawHorizontalScrollBar(Canvas canvas, Drawable scrollBar,
13984             int l, int t, int r, int b) {
13985         scrollBar.setBounds(l, t, r, b);
13986         scrollBar.draw(canvas);
13987     }
13988 
13989     /**
13990      * <p>Draw the vertical scrollbar if {@link #isVerticalScrollBarEnabled()}
13991      * returns true.</p>
13992      *
13993      * @param canvas the canvas on which to draw the scrollbar
13994      * @param scrollBar the scrollbar's drawable
13995      *
13996      * @see #isVerticalScrollBarEnabled()
13997      * @see #computeVerticalScrollRange()
13998      * @see #computeVerticalScrollExtent()
13999      * @see #computeVerticalScrollOffset()
14000      * @see android.widget.ScrollBarDrawable
14001      * @hide
14002      */
14003     protected void onDrawVerticalScrollBar(Canvas canvas, Drawable scrollBar,
14004             int l, int t, int r, int b) {
14005         scrollBar.setBounds(l, t, r, b);
14006         scrollBar.draw(canvas);
14007     }
14008 
14009     /**
14010      * Implement this to do your drawing.
14011      *
14012      * @param canvas the canvas on which the background will be drawn
14013      */
14014     protected void onDraw(Canvas canvas) {
14015     }
14016 
14017     /*
14018      * Caller is responsible for calling requestLayout if necessary.
14019      * (This allows addViewInLayout to not request a new layout.)
14020      */
14021     void assignParent(ViewParent parent) {
14022         if (mParent == null) {
14023             mParent = parent;
14024         } else if (parent == null) {
14025             mParent = null;
14026         } else {
14027             throw new RuntimeException("view " + this + " being added, but"
14028                     + " it already has a parent");
14029         }
14030     }
14031 
14032     /**
14033      * This is called when the view is attached to a window.  At this point it
14034      * has a Surface and will start drawing.  Note that this function is
14035      * guaranteed to be called before {@link #onDraw(android.graphics.Canvas)},
14036      * however it may be called any time before the first onDraw -- including
14037      * before or after {@link #onMeasure(int, int)}.
14038      *
14039      * @see #onDetachedFromWindow()
14040      */
14041     @CallSuper
14042     protected void onAttachedToWindow() {
14043         if ((mPrivateFlags & PFLAG_REQUEST_TRANSPARENT_REGIONS) != 0) {
14044             mParent.requestTransparentRegion(this);
14045         }
14046 
14047         mPrivateFlags3 &= ~PFLAG3_IS_LAID_OUT;
14048 
14049         jumpDrawablesToCurrentState();
14050 
14051         resetSubtreeAccessibilityStateChanged();
14052 
14053         // rebuild, since Outline not maintained while View is detached
14054         rebuildOutline();
14055 
14056         if (isFocused()) {
14057             InputMethodManager imm = InputMethodManager.peekInstance();
14058             if (imm != null) {
14059                 imm.focusIn(this);
14060             }
14061         }
14062     }
14063 
14064     /**
14065      * Resolve all RTL related properties.
14066      *
14067      * @return true if resolution of RTL properties has been done
14068      *
14069      * @hide
14070      */
14071     public boolean resolveRtlPropertiesIfNeeded() {
14072         if (!needRtlPropertiesResolution()) return false;
14073 
14074         // Order is important here: LayoutDirection MUST be resolved first
14075         if (!isLayoutDirectionResolved()) {
14076             resolveLayoutDirection();
14077             resolveLayoutParams();
14078         }
14079         // ... then we can resolve the others properties depending on the resolved LayoutDirection.
14080         if (!isTextDirectionResolved()) {
14081             resolveTextDirection();
14082         }
14083         if (!isTextAlignmentResolved()) {
14084             resolveTextAlignment();
14085         }
14086         // Should resolve Drawables before Padding because we need the layout direction of the
14087         // Drawable to correctly resolve Padding.
14088         if (!areDrawablesResolved()) {
14089             resolveDrawables();
14090         }
14091         if (!isPaddingResolved()) {
14092             resolvePadding();
14093         }
14094         onRtlPropertiesChanged(getLayoutDirection());
14095         return true;
14096     }
14097 
14098     /**
14099      * Reset resolution of all RTL related properties.
14100      *
14101      * @hide
14102      */
14103     public void resetRtlProperties() {
14104         resetResolvedLayoutDirection();
14105         resetResolvedTextDirection();
14106         resetResolvedTextAlignment();
14107         resetResolvedPadding();
14108         resetResolvedDrawables();
14109     }
14110 
14111     /**
14112      * @see #onScreenStateChanged(int)
14113      */
14114     void dispatchScreenStateChanged(int screenState) {
14115         onScreenStateChanged(screenState);
14116     }
14117 
14118     /**
14119      * This method is called whenever the state of the screen this view is
14120      * attached to changes. A state change will usually occurs when the screen
14121      * turns on or off (whether it happens automatically or the user does it
14122      * manually.)
14123      *
14124      * @param screenState The new state of the screen. Can be either
14125      *                    {@link #SCREEN_STATE_ON} or {@link #SCREEN_STATE_OFF}
14126      */
14127     public void onScreenStateChanged(int screenState) {
14128     }
14129 
14130     /**
14131      * Return true if the application tag in the AndroidManifest has set "supportRtl" to true
14132      */
14133     private boolean hasRtlSupport() {
14134         return mContext.getApplicationInfo().hasRtlSupport();
14135     }
14136 
14137     /**
14138      * Return true if we are in RTL compatibility mode (either before Jelly Bean MR1 or
14139      * RTL not supported)
14140      */
14141     private boolean isRtlCompatibilityMode() {
14142         final int targetSdkVersion = getContext().getApplicationInfo().targetSdkVersion;
14143         return targetSdkVersion < JELLY_BEAN_MR1 || !hasRtlSupport();
14144     }
14145 
14146     /**
14147      * @return true if RTL properties need resolution.
14148      *
14149      */
14150     private boolean needRtlPropertiesResolution() {
14151         return (mPrivateFlags2 & ALL_RTL_PROPERTIES_RESOLVED) != ALL_RTL_PROPERTIES_RESOLVED;
14152     }
14153 
14154     /**
14155      * Called when any RTL property (layout direction or text direction or text alignment) has
14156      * been changed.
14157      *
14158      * Subclasses need to override this method to take care of cached information that depends on the
14159      * resolved layout direction, or to inform child views that inherit their layout direction.
14160      *
14161      * The default implementation does nothing.
14162      *
14163      * @param layoutDirection the direction of the layout
14164      *
14165      * @see #LAYOUT_DIRECTION_LTR
14166      * @see #LAYOUT_DIRECTION_RTL
14167      */
14168     public void onRtlPropertiesChanged(@ResolvedLayoutDir int layoutDirection) {
14169     }
14170 
14171     /**
14172      * Resolve and cache the layout direction. LTR is set initially. This is implicitly supposing
14173      * that the parent directionality can and will be resolved before its children.
14174      *
14175      * @return true if resolution has been done, false otherwise.
14176      *
14177      * @hide
14178      */
14179     public boolean resolveLayoutDirection() {
14180         // Clear any previous layout direction resolution
14181         mPrivateFlags2 &= ~PFLAG2_LAYOUT_DIRECTION_RESOLVED_MASK;
14182 
14183         if (hasRtlSupport()) {
14184             // Set resolved depending on layout direction
14185             switch ((mPrivateFlags2 & PFLAG2_LAYOUT_DIRECTION_MASK) >>
14186                     PFLAG2_LAYOUT_DIRECTION_MASK_SHIFT) {
14187                 case LAYOUT_DIRECTION_INHERIT:
14188                     // We cannot resolve yet. LTR is by default and let the resolution happen again
14189                     // later to get the correct resolved value
14190                     if (!canResolveLayoutDirection()) return false;
14191 
14192                     // Parent has not yet resolved, LTR is still the default
14193                     try {
14194                         if (!mParent.isLayoutDirectionResolved()) return false;
14195 
14196                         if (mParent.getLayoutDirection() == LAYOUT_DIRECTION_RTL) {
14197                             mPrivateFlags2 |= PFLAG2_LAYOUT_DIRECTION_RESOLVED_RTL;
14198                         }
14199                     } catch (AbstractMethodError e) {
14200                         Log.e(VIEW_LOG_TAG, mParent.getClass().getSimpleName() +
14201                                 " does not fully implement ViewParent", e);
14202                     }
14203                     break;
14204                 case LAYOUT_DIRECTION_RTL:
14205                     mPrivateFlags2 |= PFLAG2_LAYOUT_DIRECTION_RESOLVED_RTL;
14206                     break;
14207                 case LAYOUT_DIRECTION_LOCALE:
14208                     if((LAYOUT_DIRECTION_RTL ==
14209                             TextUtils.getLayoutDirectionFromLocale(Locale.getDefault()))) {
14210                         mPrivateFlags2 |= PFLAG2_LAYOUT_DIRECTION_RESOLVED_RTL;
14211                     }
14212                     break;
14213                 default:
14214                     // Nothing to do, LTR by default
14215             }
14216         }
14217 
14218         // Set to resolved
14219         mPrivateFlags2 |= PFLAG2_LAYOUT_DIRECTION_RESOLVED;
14220         return true;
14221     }
14222 
14223     /**
14224      * Check if layout direction resolution can be done.
14225      *
14226      * @return true if layout direction resolution can be done otherwise return false.
14227      */
14228     public boolean canResolveLayoutDirection() {
14229         switch (getRawLayoutDirection()) {
14230             case LAYOUT_DIRECTION_INHERIT:
14231                 if (mParent != null) {
14232                     try {
14233                         return mParent.canResolveLayoutDirection();
14234                     } catch (AbstractMethodError e) {
14235                         Log.e(VIEW_LOG_TAG, mParent.getClass().getSimpleName() +
14236                                 " does not fully implement ViewParent", e);
14237                     }
14238                 }
14239                 return false;
14240 
14241             default:
14242                 return true;
14243         }
14244     }
14245 
14246     /**
14247      * Reset the resolved layout direction. Layout direction will be resolved during a call to
14248      * {@link #onMeasure(int, int)}.
14249      *
14250      * @hide
14251      */
14252     public void resetResolvedLayoutDirection() {
14253         // Reset the current resolved bits
14254         mPrivateFlags2 &= ~PFLAG2_LAYOUT_DIRECTION_RESOLVED_MASK;
14255     }
14256 
14257     /**
14258      * @return true if the layout direction is inherited.
14259      *
14260      * @hide
14261      */
14262     public boolean isLayoutDirectionInherited() {
14263         return (getRawLayoutDirection() == LAYOUT_DIRECTION_INHERIT);
14264     }
14265 
14266     /**
14267      * @return true if layout direction has been resolved.
14268      */
14269     public boolean isLayoutDirectionResolved() {
14270         return (mPrivateFlags2 & PFLAG2_LAYOUT_DIRECTION_RESOLVED) == PFLAG2_LAYOUT_DIRECTION_RESOLVED;
14271     }
14272 
14273     /**
14274      * Return if padding has been resolved
14275      *
14276      * @hide
14277      */
14278     boolean isPaddingResolved() {
14279         return (mPrivateFlags2 & PFLAG2_PADDING_RESOLVED) == PFLAG2_PADDING_RESOLVED;
14280     }
14281 
14282     /**
14283      * Resolves padding depending on layout direction, if applicable, and
14284      * recomputes internal padding values to adjust for scroll bars.
14285      *
14286      * @hide
14287      */
14288     public void resolvePadding() {
14289         final int resolvedLayoutDirection = getLayoutDirection();
14290 
14291         if (!isRtlCompatibilityMode()) {
14292             // Post Jelly Bean MR1 case: we need to take the resolved layout direction into account.
14293             // If start / end padding are defined, they will be resolved (hence overriding) to
14294             // left / right or right / left depending on the resolved layout direction.
14295             // If start / end padding are not defined, use the left / right ones.
14296             if (mBackground != null && (!mLeftPaddingDefined || !mRightPaddingDefined)) {
14297                 Rect padding = sThreadLocal.get();
14298                 if (padding == null) {
14299                     padding = new Rect();
14300                     sThreadLocal.set(padding);
14301                 }
14302                 mBackground.getPadding(padding);
14303                 if (!mLeftPaddingDefined) {
14304                     mUserPaddingLeftInitial = padding.left;
14305                 }
14306                 if (!mRightPaddingDefined) {
14307                     mUserPaddingRightInitial = padding.right;
14308                 }
14309             }
14310             switch (resolvedLayoutDirection) {
14311                 case LAYOUT_DIRECTION_RTL:
14312                     if (mUserPaddingStart != UNDEFINED_PADDING) {
14313                         mUserPaddingRight = mUserPaddingStart;
14314                     } else {
14315                         mUserPaddingRight = mUserPaddingRightInitial;
14316                     }
14317                     if (mUserPaddingEnd != UNDEFINED_PADDING) {
14318                         mUserPaddingLeft = mUserPaddingEnd;
14319                     } else {
14320                         mUserPaddingLeft = mUserPaddingLeftInitial;
14321                     }
14322                     break;
14323                 case LAYOUT_DIRECTION_LTR:
14324                 default:
14325                     if (mUserPaddingStart != UNDEFINED_PADDING) {
14326                         mUserPaddingLeft = mUserPaddingStart;
14327                     } else {
14328                         mUserPaddingLeft = mUserPaddingLeftInitial;
14329                     }
14330                     if (mUserPaddingEnd != UNDEFINED_PADDING) {
14331                         mUserPaddingRight = mUserPaddingEnd;
14332                     } else {
14333                         mUserPaddingRight = mUserPaddingRightInitial;
14334                     }
14335             }
14336 
14337             mUserPaddingBottom = (mUserPaddingBottom >= 0) ? mUserPaddingBottom : mPaddingBottom;
14338         }
14339 
14340         internalSetPadding(mUserPaddingLeft, mPaddingTop, mUserPaddingRight, mUserPaddingBottom);
14341         onRtlPropertiesChanged(resolvedLayoutDirection);
14342 
14343         mPrivateFlags2 |= PFLAG2_PADDING_RESOLVED;
14344     }
14345 
14346     /**
14347      * Reset the resolved layout direction.
14348      *
14349      * @hide
14350      */
14351     public void resetResolvedPadding() {
14352         resetResolvedPaddingInternal();
14353     }
14354 
14355     /**
14356      * Used when we only want to reset *this* view's padding and not trigger overrides
14357      * in ViewGroup that reset children too.
14358      */
14359     void resetResolvedPaddingInternal() {
14360         mPrivateFlags2 &= ~PFLAG2_PADDING_RESOLVED;
14361     }
14362 
14363     /**
14364      * This is called when the view is detached from a window.  At this point it
14365      * no longer has a surface for drawing.
14366      *
14367      * @see #onAttachedToWindow()
14368      */
14369     @CallSuper
14370     protected void onDetachedFromWindow() {
14371     }
14372 
14373     /**
14374      * This is a framework-internal mirror of onDetachedFromWindow() that's called
14375      * after onDetachedFromWindow().
14376      *
14377      * If you override this you *MUST* call super.onDetachedFromWindowInternal()!
14378      * The super method should be called at the end of the overridden method to ensure
14379      * subclasses are destroyed first
14380      *
14381      * @hide
14382      */
14383     @CallSuper
14384     protected void onDetachedFromWindowInternal() {
14385         mPrivateFlags &= ~PFLAG_CANCEL_NEXT_UP_EVENT;
14386         mPrivateFlags3 &= ~PFLAG3_IS_LAID_OUT;
14387 
14388         removeUnsetPressCallback();
14389         removeLongPressCallback();
14390         removePerformClickCallback();
14391         removeSendViewScrolledAccessibilityEventCallback();
14392         stopNestedScroll();
14393 
14394         // Anything that started animating right before detach should already
14395         // be in its final state when re-attached.
14396         jumpDrawablesToCurrentState();
14397 
14398         destroyDrawingCache();
14399 
14400         cleanupDraw();
14401         mCurrentAnimation = null;
14402     }
14403 
14404     private void cleanupDraw() {
14405         resetDisplayList();
14406         if (mAttachInfo != null) {
14407             mAttachInfo.mViewRootImpl.cancelInvalidate(this);
14408         }
14409     }
14410 
14411     void invalidateInheritedLayoutMode(int layoutModeOfRoot) {
14412     }
14413 
14414     /**
14415      * @return The number of times this view has been attached to a window
14416      */
14417     protected int getWindowAttachCount() {
14418         return mWindowAttachCount;
14419     }
14420 
14421     /**
14422      * Retrieve a unique token identifying the window this view is attached to.
14423      * @return Return the window's token for use in
14424      * {@link WindowManager.LayoutParams#token WindowManager.LayoutParams.token}.
14425      */
14426     public IBinder getWindowToken() {
14427         return mAttachInfo != null ? mAttachInfo.mWindowToken : null;
14428     }
14429 
14430     /**
14431      * Retrieve the {@link WindowId} for the window this view is
14432      * currently attached to.
14433      */
14434     public WindowId getWindowId() {
14435         if (mAttachInfo == null) {
14436             return null;
14437         }
14438         if (mAttachInfo.mWindowId == null) {
14439             try {
14440                 mAttachInfo.mIWindowId = mAttachInfo.mSession.getWindowId(
14441                         mAttachInfo.mWindowToken);
14442                 mAttachInfo.mWindowId = new WindowId(
14443                         mAttachInfo.mIWindowId);
14444             } catch (RemoteException e) {
14445             }
14446         }
14447         return mAttachInfo.mWindowId;
14448     }
14449 
14450     /**
14451      * Retrieve a unique token identifying the top-level "real" window of
14452      * the window that this view is attached to.  That is, this is like
14453      * {@link #getWindowToken}, except if the window this view in is a panel
14454      * window (attached to another containing window), then the token of
14455      * the containing window is returned instead.
14456      *
14457      * @return Returns the associated window token, either
14458      * {@link #getWindowToken()} or the containing window's token.
14459      */
14460     public IBinder getApplicationWindowToken() {
14461         AttachInfo ai = mAttachInfo;
14462         if (ai != null) {
14463             IBinder appWindowToken = ai.mPanelParentWindowToken;
14464             if (appWindowToken == null) {
14465                 appWindowToken = ai.mWindowToken;
14466             }
14467             return appWindowToken;
14468         }
14469         return null;
14470     }
14471 
14472     /**
14473      * Gets the logical display to which the view's window has been attached.
14474      *
14475      * @return The logical display, or null if the view is not currently attached to a window.
14476      */
14477     public Display getDisplay() {
14478         return mAttachInfo != null ? mAttachInfo.mDisplay : null;
14479     }
14480 
14481     /**
14482      * Retrieve private session object this view hierarchy is using to
14483      * communicate with the window manager.
14484      * @return the session object to communicate with the window manager
14485      */
14486     /*package*/ IWindowSession getWindowSession() {
14487         return mAttachInfo != null ? mAttachInfo.mSession : null;
14488     }
14489 
14490     /**
14491      * Return the visibility value of the least visible component passed.
14492      */
14493     int combineVisibility(int vis1, int vis2) {
14494         // This works because VISIBLE < INVISIBLE < GONE.
14495         return Math.max(vis1, vis2);
14496     }
14497 
14498     /**
14499      * @param info the {@link android.view.View.AttachInfo} to associated with
14500      *        this view
14501      */
14502     void dispatchAttachedToWindow(AttachInfo info, int visibility) {
14503         //System.out.println("Attached! " + this);
14504         mAttachInfo = info;
14505         if (mOverlay != null) {
14506             mOverlay.getOverlayView().dispatchAttachedToWindow(info, visibility);
14507         }
14508         mWindowAttachCount++;
14509         // We will need to evaluate the drawable state at least once.
14510         mPrivateFlags |= PFLAG_DRAWABLE_STATE_DIRTY;
14511         if (mFloatingTreeObserver != null) {
14512             info.mTreeObserver.merge(mFloatingTreeObserver);
14513             mFloatingTreeObserver = null;
14514         }
14515         if ((mPrivateFlags&PFLAG_SCROLL_CONTAINER) != 0) {
14516             mAttachInfo.mScrollContainers.add(this);
14517             mPrivateFlags |= PFLAG_SCROLL_CONTAINER_ADDED;
14518         }
14519         performCollectViewAttributes(mAttachInfo, visibility);
14520         onAttachedToWindow();
14521 
14522         ListenerInfo li = mListenerInfo;
14523         final CopyOnWriteArrayList<OnAttachStateChangeListener> listeners =
14524                 li != null ? li.mOnAttachStateChangeListeners : null;
14525         if (listeners != null && listeners.size() > 0) {
14526             // NOTE: because of the use of CopyOnWriteArrayList, we *must* use an iterator to
14527             // perform the dispatching. The iterator is a safe guard against listeners that
14528             // could mutate the list by calling the various add/remove methods. This prevents
14529             // the array from being modified while we iterate it.
14530             for (OnAttachStateChangeListener listener : listeners) {
14531                 listener.onViewAttachedToWindow(this);
14532             }
14533         }
14534 
14535         int vis = info.mWindowVisibility;
14536         if (vis != GONE) {
14537             onWindowVisibilityChanged(vis);
14538         }
14539 
14540         // Send onVisibilityChanged directly instead of dispatchVisibilityChanged.
14541         // As all views in the subtree will already receive dispatchAttachedToWindow
14542         // traversing the subtree again here is not desired.
14543         onVisibilityChanged(this, visibility);
14544 
14545         if ((mPrivateFlags&PFLAG_DRAWABLE_STATE_DIRTY) != 0) {
14546             // If nobody has evaluated the drawable state yet, then do it now.
14547             refreshDrawableState();
14548         }
14549         needGlobalAttributesUpdate(false);
14550     }
14551 
14552     void dispatchDetachedFromWindow() {
14553         AttachInfo info = mAttachInfo;
14554         if (info != null) {
14555             int vis = info.mWindowVisibility;
14556             if (vis != GONE) {
14557                 onWindowVisibilityChanged(GONE);
14558             }
14559         }
14560 
14561         onDetachedFromWindow();
14562         onDetachedFromWindowInternal();
14563 
14564         InputMethodManager imm = InputMethodManager.peekInstance();
14565         if (imm != null) {
14566             imm.onViewDetachedFromWindow(this);
14567         }
14568 
14569         ListenerInfo li = mListenerInfo;
14570         final CopyOnWriteArrayList<OnAttachStateChangeListener> listeners =
14571                 li != null ? li.mOnAttachStateChangeListeners : null;
14572         if (listeners != null && listeners.size() > 0) {
14573             // NOTE: because of the use of CopyOnWriteArrayList, we *must* use an iterator to
14574             // perform the dispatching. The iterator is a safe guard against listeners that
14575             // could mutate the list by calling the various add/remove methods. This prevents
14576             // the array from being modified while we iterate it.
14577             for (OnAttachStateChangeListener listener : listeners) {
14578                 listener.onViewDetachedFromWindow(this);
14579             }
14580         }
14581 
14582         if ((mPrivateFlags & PFLAG_SCROLL_CONTAINER_ADDED) != 0) {
14583             mAttachInfo.mScrollContainers.remove(this);
14584             mPrivateFlags &= ~PFLAG_SCROLL_CONTAINER_ADDED;
14585         }
14586 
14587         mAttachInfo = null;
14588         if (mOverlay != null) {
14589             mOverlay.getOverlayView().dispatchDetachedFromWindow();
14590         }
14591     }
14592 
14593     /**
14594      * Cancel any deferred high-level input events that were previously posted to the event queue.
14595      *
14596      * <p>Many views post high-level events such as click handlers to the event queue
14597      * to run deferred in order to preserve a desired user experience - clearing visible
14598      * pressed states before executing, etc. This method will abort any events of this nature
14599      * that are currently in flight.</p>
14600      *
14601      * <p>Custom views that generate their own high-level deferred input events should override
14602      * {@link #onCancelPendingInputEvents()} and remove those pending events from the queue.</p>
14603      *
14604      * <p>This will also cancel pending input events for any child views.</p>
14605      *
14606      * <p>Note that this may not be sufficient as a debouncing strategy for clicks in all cases.
14607      * This will not impact newer events posted after this call that may occur as a result of
14608      * lower-level input events still waiting in the queue. If you are trying to prevent
14609      * double-submitted  events for the duration of some sort of asynchronous transaction
14610      * you should also take other steps to protect against unexpected double inputs e.g. calling
14611      * {@link #setEnabled(boolean) setEnabled(false)} and re-enabling the view when
14612      * the transaction completes, tracking already submitted transaction IDs, etc.</p>
14613      */
14614     public final void cancelPendingInputEvents() {
14615         dispatchCancelPendingInputEvents();
14616     }
14617 
14618     /**
14619      * Called by {@link #cancelPendingInputEvents()} to cancel input events in flight.
14620      * Overridden by ViewGroup to dispatch. Package scoped to prevent app-side meddling.
14621      */
14622     void dispatchCancelPendingInputEvents() {
14623         mPrivateFlags3 &= ~PFLAG3_CALLED_SUPER;
14624         onCancelPendingInputEvents();
14625         if ((mPrivateFlags3 & PFLAG3_CALLED_SUPER) != PFLAG3_CALLED_SUPER) {
14626             throw new SuperNotCalledException("View " + getClass().getSimpleName() +
14627                     " did not call through to super.onCancelPendingInputEvents()");
14628         }
14629     }
14630 
14631     /**
14632      * Called as the result of a call to {@link #cancelPendingInputEvents()} on this view or
14633      * a parent view.
14634      *
14635      * <p>This method is responsible for removing any pending high-level input events that were
14636      * posted to the event queue to run later. Custom view classes that post their own deferred
14637      * high-level events via {@link #post(Runnable)}, {@link #postDelayed(Runnable, long)} or
14638      * {@link android.os.Handler} should override this method, call
14639      * <code>super.onCancelPendingInputEvents()</code> and remove those callbacks as appropriate.
14640      * </p>
14641      */
14642     public void onCancelPendingInputEvents() {
14643         removePerformClickCallback();
14644         cancelLongPress();
14645         mPrivateFlags3 |= PFLAG3_CALLED_SUPER;
14646     }
14647 
14648     /**
14649      * Store this view hierarchy's frozen state into the given container.
14650      *
14651      * @param container The SparseArray in which to save the view's state.
14652      *
14653      * @see #restoreHierarchyState(android.util.SparseArray)
14654      * @see #dispatchSaveInstanceState(android.util.SparseArray)
14655      * @see #onSaveInstanceState()
14656      */
14657     public void saveHierarchyState(SparseArray<Parcelable> container) {
14658         dispatchSaveInstanceState(container);
14659     }
14660 
14661     /**
14662      * Called by {@link #saveHierarchyState(android.util.SparseArray)} to store the state for
14663      * this view and its children. May be overridden to modify how freezing happens to a
14664      * view's children; for example, some views may want to not store state for their children.
14665      *
14666      * @param container The SparseArray in which to save the view's state.
14667      *
14668      * @see #dispatchRestoreInstanceState(android.util.SparseArray)
14669      * @see #saveHierarchyState(android.util.SparseArray)
14670      * @see #onSaveInstanceState()
14671      */
14672     protected void dispatchSaveInstanceState(SparseArray<Parcelable> container) {
14673         if (mID != NO_ID && (mViewFlags & SAVE_DISABLED_MASK) == 0) {
14674             mPrivateFlags &= ~PFLAG_SAVE_STATE_CALLED;
14675             Parcelable state = onSaveInstanceState();
14676             if ((mPrivateFlags & PFLAG_SAVE_STATE_CALLED) == 0) {
14677                 throw new IllegalStateException(
14678                         "Derived class did not call super.onSaveInstanceState()");
14679             }
14680             if (state != null) {
14681                 // Log.i("View", "Freezing #" + Integer.toHexString(mID)
14682                 // + ": " + state);
14683                 container.put(mID, state);
14684             }
14685         }
14686     }
14687 
14688     /**
14689      * Hook allowing a view to generate a representation of its internal state
14690      * that can later be used to create a new instance with that same state.
14691      * This state should only contain information that is not persistent or can
14692      * not be reconstructed later. For example, you will never store your
14693      * current position on screen because that will be computed again when a
14694      * new instance of the view is placed in its view hierarchy.
14695      * <p>
14696      * Some examples of things you may store here: the current cursor position
14697      * in a text view (but usually not the text itself since that is stored in a
14698      * content provider or other persistent storage), the currently selected
14699      * item in a list view.
14700      *
14701      * @return Returns a Parcelable object containing the view's current dynamic
14702      *         state, or null if there is nothing interesting to save. The
14703      *         default implementation returns null.
14704      * @see #onRestoreInstanceState(android.os.Parcelable)
14705      * @see #saveHierarchyState(android.util.SparseArray)
14706      * @see #dispatchSaveInstanceState(android.util.SparseArray)
14707      * @see #setSaveEnabled(boolean)
14708      */
14709     @CallSuper
14710     protected Parcelable onSaveInstanceState() {
14711         mPrivateFlags |= PFLAG_SAVE_STATE_CALLED;
14712         if (mStartActivityRequestWho != null) {
14713             BaseSavedState state = new BaseSavedState(AbsSavedState.EMPTY_STATE);
14714             state.mStartActivityRequestWhoSaved = mStartActivityRequestWho;
14715             return state;
14716         }
14717         return BaseSavedState.EMPTY_STATE;
14718     }
14719 
14720     /**
14721      * Restore this view hierarchy's frozen state from the given container.
14722      *
14723      * @param container The SparseArray which holds previously frozen states.
14724      *
14725      * @see #saveHierarchyState(android.util.SparseArray)
14726      * @see #dispatchRestoreInstanceState(android.util.SparseArray)
14727      * @see #onRestoreInstanceState(android.os.Parcelable)
14728      */
14729     public void restoreHierarchyState(SparseArray<Parcelable> container) {
14730         dispatchRestoreInstanceState(container);
14731     }
14732 
14733     /**
14734      * Called by {@link #restoreHierarchyState(android.util.SparseArray)} to retrieve the
14735      * state for this view and its children. May be overridden to modify how restoring
14736      * happens to a view's children; for example, some views may want to not store state
14737      * for their children.
14738      *
14739      * @param container The SparseArray which holds previously saved state.
14740      *
14741      * @see #dispatchSaveInstanceState(android.util.SparseArray)
14742      * @see #restoreHierarchyState(android.util.SparseArray)
14743      * @see #onRestoreInstanceState(android.os.Parcelable)
14744      */
14745     protected void dispatchRestoreInstanceState(SparseArray<Parcelable> container) {
14746         if (mID != NO_ID) {
14747             Parcelable state = container.get(mID);
14748             if (state != null) {
14749                 // Log.i("View", "Restoreing #" + Integer.toHexString(mID)
14750                 // + ": " + state);
14751                 mPrivateFlags &= ~PFLAG_SAVE_STATE_CALLED;
14752                 onRestoreInstanceState(state);
14753                 if ((mPrivateFlags & PFLAG_SAVE_STATE_CALLED) == 0) {
14754                     throw new IllegalStateException(
14755                             "Derived class did not call super.onRestoreInstanceState()");
14756                 }
14757             }
14758         }
14759     }
14760 
14761     /**
14762      * Hook allowing a view to re-apply a representation of its internal state that had previously
14763      * been generated by {@link #onSaveInstanceState}. This function will never be called with a
14764      * null state.
14765      *
14766      * @param state The frozen state that had previously been returned by
14767      *        {@link #onSaveInstanceState}.
14768      *
14769      * @see #onSaveInstanceState()
14770      * @see #restoreHierarchyState(android.util.SparseArray)
14771      * @see #dispatchRestoreInstanceState(android.util.SparseArray)
14772      */
14773     @CallSuper
14774     protected void onRestoreInstanceState(Parcelable state) {
14775         mPrivateFlags |= PFLAG_SAVE_STATE_CALLED;
14776         if (state != null && !(state instanceof AbsSavedState)) {
14777             throw new IllegalArgumentException("Wrong state class, expecting View State but "
14778                     + "received " + state.getClass().toString() + " instead. This usually happens "
14779                     + "when two views of different type have the same id in the same hierarchy. "
14780                     + "This view's id is " + ViewDebug.resolveId(mContext, getId()) + ". Make sure "
14781                     + "other views do not use the same id.");
14782         }
14783         if (state != null && state instanceof BaseSavedState) {
14784             mStartActivityRequestWho = ((BaseSavedState) state).mStartActivityRequestWhoSaved;
14785         }
14786     }
14787 
14788     /**
14789      * <p>Return the time at which the drawing of the view hierarchy started.</p>
14790      *
14791      * @return the drawing start time in milliseconds
14792      */
14793     public long getDrawingTime() {
14794         return mAttachInfo != null ? mAttachInfo.mDrawingTime : 0;
14795     }
14796 
14797     /**
14798      * <p>Enables or disables the duplication of the parent's state into this view. When
14799      * duplication is enabled, this view gets its drawable state from its parent rather
14800      * than from its own internal properties.</p>
14801      *
14802      * <p>Note: in the current implementation, setting this property to true after the
14803      * view was added to a ViewGroup might have no effect at all. This property should
14804      * always be used from XML or set to true before adding this view to a ViewGroup.</p>
14805      *
14806      * <p>Note: if this view's parent addStateFromChildren property is enabled and this
14807      * property is enabled, an exception will be thrown.</p>
14808      *
14809      * <p>Note: if the child view uses and updates additional states which are unknown to the
14810      * parent, these states should not be affected by this method.</p>
14811      *
14812      * @param enabled True to enable duplication of the parent's drawable state, false
14813      *                to disable it.
14814      *
14815      * @see #getDrawableState()
14816      * @see #isDuplicateParentStateEnabled()
14817      */
14818     public void setDuplicateParentStateEnabled(boolean enabled) {
14819         setFlags(enabled ? DUPLICATE_PARENT_STATE : 0, DUPLICATE_PARENT_STATE);
14820     }
14821 
14822     /**
14823      * <p>Indicates whether this duplicates its drawable state from its parent.</p>
14824      *
14825      * @return True if this view's drawable state is duplicated from the parent,
14826      *         false otherwise
14827      *
14828      * @see #getDrawableState()
14829      * @see #setDuplicateParentStateEnabled(boolean)
14830      */
14831     public boolean isDuplicateParentStateEnabled() {
14832         return (mViewFlags & DUPLICATE_PARENT_STATE) == DUPLICATE_PARENT_STATE;
14833     }
14834 
14835     /**
14836      * <p>Specifies the type of layer backing this view. The layer can be
14837      * {@link #LAYER_TYPE_NONE}, {@link #LAYER_TYPE_SOFTWARE} or
14838      * {@link #LAYER_TYPE_HARDWARE}.</p>
14839      *
14840      * <p>A layer is associated with an optional {@link android.graphics.Paint}
14841      * instance that controls how the layer is composed on screen. The following
14842      * properties of the paint are taken into account when composing the layer:</p>
14843      * <ul>
14844      * <li>{@link android.graphics.Paint#getAlpha() Translucency (alpha)}</li>
14845      * <li>{@link android.graphics.Paint#getXfermode() Blending mode}</li>
14846      * <li>{@link android.graphics.Paint#getColorFilter() Color filter}</li>
14847      * </ul>
14848      *
14849      * <p>If this view has an alpha value set to < 1.0 by calling
14850      * {@link #setAlpha(float)}, the alpha value of the layer's paint is superseded
14851      * by this view's alpha value.</p>
14852      *
14853      * <p>Refer to the documentation of {@link #LAYER_TYPE_NONE},
14854      * {@link #LAYER_TYPE_SOFTWARE} and {@link #LAYER_TYPE_HARDWARE}
14855      * for more information on when and how to use layers.</p>
14856      *
14857      * @param layerType The type of layer to use with this view, must be one of
14858      *        {@link #LAYER_TYPE_NONE}, {@link #LAYER_TYPE_SOFTWARE} or
14859      *        {@link #LAYER_TYPE_HARDWARE}
14860      * @param paint The paint used to compose the layer. This argument is optional
14861      *        and can be null. It is ignored when the layer type is
14862      *        {@link #LAYER_TYPE_NONE}
14863      *
14864      * @see #getLayerType()
14865      * @see #LAYER_TYPE_NONE
14866      * @see #LAYER_TYPE_SOFTWARE
14867      * @see #LAYER_TYPE_HARDWARE
14868      * @see #setAlpha(float)
14869      *
14870      * @attr ref android.R.styleable#View_layerType
14871      */
14872     public void setLayerType(int layerType, Paint paint) {
14873         if (layerType < LAYER_TYPE_NONE || layerType > LAYER_TYPE_HARDWARE) {
14874             throw new IllegalArgumentException("Layer type can only be one of: LAYER_TYPE_NONE, "
14875                     + "LAYER_TYPE_SOFTWARE or LAYER_TYPE_HARDWARE");
14876         }
14877 
14878         boolean typeChanged = mRenderNode.setLayerType(layerType);
14879 
14880         if (!typeChanged) {
14881             setLayerPaint(paint);
14882             return;
14883         }
14884 
14885         // Destroy any previous software drawing cache if needed
14886         if (mLayerType == LAYER_TYPE_SOFTWARE) {
14887             destroyDrawingCache();
14888         }
14889 
14890         mLayerType = layerType;
14891         final boolean layerDisabled = (mLayerType == LAYER_TYPE_NONE);
14892         mLayerPaint = layerDisabled ? null : (paint == null ? new Paint() : paint);
14893         mRenderNode.setLayerPaint(mLayerPaint);
14894 
14895         // draw() behaves differently if we are on a layer, so we need to
14896         // invalidate() here
14897         invalidateParentCaches();
14898         invalidate(true);
14899     }
14900 
14901     /**
14902      * Updates the {@link Paint} object used with the current layer (used only if the current
14903      * layer type is not set to {@link #LAYER_TYPE_NONE}). Changed properties of the Paint
14904      * provided to {@link #setLayerType(int, android.graphics.Paint)} will be used the next time
14905      * the View is redrawn, but {@link #setLayerPaint(android.graphics.Paint)} must be called to
14906      * ensure that the view gets redrawn immediately.
14907      *
14908      * <p>A layer is associated with an optional {@link android.graphics.Paint}
14909      * instance that controls how the layer is composed on screen. The following
14910      * properties of the paint are taken into account when composing the layer:</p>
14911      * <ul>
14912      * <li>{@link android.graphics.Paint#getAlpha() Translucency (alpha)}</li>
14913      * <li>{@link android.graphics.Paint#getXfermode() Blending mode}</li>
14914      * <li>{@link android.graphics.Paint#getColorFilter() Color filter}</li>
14915      * </ul>
14916      *
14917      * <p>If this view has an alpha value set to < 1.0 by calling {@link #setAlpha(float)}, the
14918      * alpha value of the layer's paint is superseded by this view's alpha value.</p>
14919      *
14920      * @param paint The paint used to compose the layer. This argument is optional
14921      *        and can be null. It is ignored when the layer type is
14922      *        {@link #LAYER_TYPE_NONE}
14923      *
14924      * @see #setLayerType(int, android.graphics.Paint)
14925      */
14926     public void setLayerPaint(Paint paint) {
14927         int layerType = getLayerType();
14928         if (layerType != LAYER_TYPE_NONE) {
14929             mLayerPaint = paint == null ? new Paint() : paint;
14930             if (layerType == LAYER_TYPE_HARDWARE) {
14931                 if (mRenderNode.setLayerPaint(mLayerPaint)) {
14932                     invalidateViewProperty(false, false);
14933                 }
14934             } else {
14935                 invalidate();
14936             }
14937         }
14938     }
14939 
14940     /**
14941      * Indicates what type of layer is currently associated with this view. By default
14942      * a view does not have a layer, and the layer type is {@link #LAYER_TYPE_NONE}.
14943      * Refer to the documentation of {@link #setLayerType(int, android.graphics.Paint)}
14944      * for more information on the different types of layers.
14945      *
14946      * @return {@link #LAYER_TYPE_NONE}, {@link #LAYER_TYPE_SOFTWARE} or
14947      *         {@link #LAYER_TYPE_HARDWARE}
14948      *
14949      * @see #setLayerType(int, android.graphics.Paint)
14950      * @see #buildLayer()
14951      * @see #LAYER_TYPE_NONE
14952      * @see #LAYER_TYPE_SOFTWARE
14953      * @see #LAYER_TYPE_HARDWARE
14954      */
14955     public int getLayerType() {
14956         return mLayerType;
14957     }
14958 
14959     /**
14960      * Forces this view's layer to be created and this view to be rendered
14961      * into its layer. If this view's layer type is set to {@link #LAYER_TYPE_NONE},
14962      * invoking this method will have no effect.
14963      *
14964      * This method can for instance be used to render a view into its layer before
14965      * starting an animation. If this view is complex, rendering into the layer
14966      * before starting the animation will avoid skipping frames.
14967      *
14968      * @throws IllegalStateException If this view is not attached to a window
14969      *
14970      * @see #setLayerType(int, android.graphics.Paint)
14971      */
14972     public void buildLayer() {
14973         if (mLayerType == LAYER_TYPE_NONE) return;
14974 
14975         final AttachInfo attachInfo = mAttachInfo;
14976         if (attachInfo == null) {
14977             throw new IllegalStateException("This view must be attached to a window first");
14978         }
14979 
14980         if (getWidth() == 0 || getHeight() == 0) {
14981             return;
14982         }
14983 
14984         switch (mLayerType) {
14985             case LAYER_TYPE_HARDWARE:
14986                 updateDisplayListIfDirty();
14987                 if (attachInfo.mHardwareRenderer != null && mRenderNode.isValid()) {
14988                     attachInfo.mHardwareRenderer.buildLayer(mRenderNode);
14989                 }
14990                 break;
14991             case LAYER_TYPE_SOFTWARE:
14992                 buildDrawingCache(true);
14993                 break;
14994         }
14995     }
14996 
14997     /**
14998      * If this View draws with a HardwareLayer, returns it.
14999      * Otherwise returns null
15000      *
15001      * TODO: Only TextureView uses this, can we eliminate it?
15002      */
15003     HardwareLayer getHardwareLayer() {
15004         return null;
15005     }
15006 
15007     /**
15008      * Destroys all hardware rendering resources. This method is invoked
15009      * when the system needs to reclaim resources. Upon execution of this
15010      * method, you should free any OpenGL resources created by the view.
15011      *
15012      * Note: you <strong>must</strong> call
15013      * <code>super.destroyHardwareResources()</code> when overriding
15014      * this method.
15015      *
15016      * @hide
15017      */
15018     @CallSuper
15019     protected void destroyHardwareResources() {
15020         // Although the Layer will be destroyed by RenderNode, we want to release
15021         // the staging display list, which is also a signal to RenderNode that it's
15022         // safe to free its copy of the display list as it knows that we will
15023         // push an updated DisplayList if we try to draw again
15024         resetDisplayList();
15025     }
15026 
15027     /**
15028      * <p>Enables or disables the drawing cache. When the drawing cache is enabled, the next call
15029      * to {@link #getDrawingCache()} or {@link #buildDrawingCache()} will draw the view in a
15030      * bitmap. Calling {@link #draw(android.graphics.Canvas)} will not draw from the cache when
15031      * the cache is enabled. To benefit from the cache, you must request the drawing cache by
15032      * calling {@link #getDrawingCache()} and draw it on screen if the returned bitmap is not
15033      * null.</p>
15034      *
15035      * <p>Enabling the drawing cache is similar to
15036      * {@link #setLayerType(int, android.graphics.Paint) setting a layer} when hardware
15037      * acceleration is turned off. When hardware acceleration is turned on, enabling the
15038      * drawing cache has no effect on rendering because the system uses a different mechanism
15039      * for acceleration which ignores the flag. If you want to use a Bitmap for the view, even
15040      * when hardware acceleration is enabled, see {@link #setLayerType(int, android.graphics.Paint)}
15041      * for information on how to enable software and hardware layers.</p>
15042      *
15043      * <p>This API can be used to manually generate
15044      * a bitmap copy of this view, by setting the flag to <code>true</code> and calling
15045      * {@link #getDrawingCache()}.</p>
15046      *
15047      * @param enabled true to enable the drawing cache, false otherwise
15048      *
15049      * @see #isDrawingCacheEnabled()
15050      * @see #getDrawingCache()
15051      * @see #buildDrawingCache()
15052      * @see #setLayerType(int, android.graphics.Paint)
15053      */
15054     public void setDrawingCacheEnabled(boolean enabled) {
15055         mCachingFailed = false;
15056         setFlags(enabled ? DRAWING_CACHE_ENABLED : 0, DRAWING_CACHE_ENABLED);
15057     }
15058 
15059     /**
15060      * <p>Indicates whether the drawing cache is enabled for this view.</p>
15061      *
15062      * @return true if the drawing cache is enabled
15063      *
15064      * @see #setDrawingCacheEnabled(boolean)
15065      * @see #getDrawingCache()
15066      */
15067     @ViewDebug.ExportedProperty(category = "drawing")
15068     public boolean isDrawingCacheEnabled() {
15069         return (mViewFlags & DRAWING_CACHE_ENABLED) == DRAWING_CACHE_ENABLED;
15070     }
15071 
15072     /**
15073      * Debugging utility which recursively outputs the dirty state of a view and its
15074      * descendants.
15075      *
15076      * @hide
15077      */
15078     @SuppressWarnings({"UnusedDeclaration"})
15079     public void outputDirtyFlags(String indent, boolean clear, int clearMask) {
15080         Log.d("View", indent + this + "             DIRTY(" + (mPrivateFlags & View.PFLAG_DIRTY_MASK) +
15081                 ") DRAWN(" + (mPrivateFlags & PFLAG_DRAWN) + ")" + " CACHE_VALID(" +
15082                 (mPrivateFlags & View.PFLAG_DRAWING_CACHE_VALID) +
15083                 ") INVALIDATED(" + (mPrivateFlags & PFLAG_INVALIDATED) + ")");
15084         if (clear) {
15085             mPrivateFlags &= clearMask;
15086         }
15087         if (this instanceof ViewGroup) {
15088             ViewGroup parent = (ViewGroup) this;
15089             final int count = parent.getChildCount();
15090             for (int i = 0; i < count; i++) {
15091                 final View child = parent.getChildAt(i);
15092                 child.outputDirtyFlags(indent + "  ", clear, clearMask);
15093             }
15094         }
15095     }
15096 
15097     /**
15098      * This method is used by ViewGroup to cause its children to restore or recreate their
15099      * display lists. It is called by getDisplayList() when the parent ViewGroup does not need
15100      * to recreate its own display list, which would happen if it went through the normal
15101      * draw/dispatchDraw mechanisms.
15102      *
15103      * @hide
15104      */
15105     protected void dispatchGetDisplayList() {}
15106 
15107     /**
15108      * A view that is not attached or hardware accelerated cannot create a display list.
15109      * This method checks these conditions and returns the appropriate result.
15110      *
15111      * @return true if view has the ability to create a display list, false otherwise.
15112      *
15113      * @hide
15114      */
15115     public boolean canHaveDisplayList() {
15116         return !(mAttachInfo == null || mAttachInfo.mHardwareRenderer == null);
15117     }
15118 
15119     /**
15120      * Gets the RenderNode for the view, and updates its DisplayList (if needed and supported)
15121      * @hide
15122      */
15123     @NonNull
15124     public RenderNode updateDisplayListIfDirty() {
15125         final RenderNode renderNode = mRenderNode;
15126         if (!canHaveDisplayList()) {
15127             // can't populate RenderNode, don't try
15128             return renderNode;
15129         }
15130 
15131         if ((mPrivateFlags & PFLAG_DRAWING_CACHE_VALID) == 0
15132                 || !renderNode.isValid()
15133                 || (mRecreateDisplayList)) {
15134             // Don't need to recreate the display list, just need to tell our
15135             // children to restore/recreate theirs
15136             if (renderNode.isValid()
15137                     && !mRecreateDisplayList) {
15138                 mPrivateFlags |= PFLAG_DRAWN | PFLAG_DRAWING_CACHE_VALID;
15139                 mPrivateFlags &= ~PFLAG_DIRTY_MASK;
15140                 dispatchGetDisplayList();
15141 
15142                 return renderNode; // no work needed
15143             }
15144 
15145             // If we got here, we're recreating it. Mark it as such to ensure that
15146             // we copy in child display lists into ours in drawChild()
15147             mRecreateDisplayList = true;
15148 
15149             int width = mRight - mLeft;
15150             int height = mBottom - mTop;
15151             int layerType = getLayerType();
15152 
15153             final DisplayListCanvas canvas = renderNode.start(width, height);
15154             canvas.setHighContrastText(mAttachInfo.mHighContrastText);
15155 
15156             try {
15157                 final HardwareLayer layer = getHardwareLayer();
15158                 if (layer != null && layer.isValid()) {
15159                     canvas.drawHardwareLayer(layer, 0, 0, mLayerPaint);
15160                 } else if (layerType == LAYER_TYPE_SOFTWARE) {
15161                     buildDrawingCache(true);
15162                     Bitmap cache = getDrawingCache(true);
15163                     if (cache != null) {
15164                         canvas.drawBitmap(cache, 0, 0, mLayerPaint);
15165                     }
15166                 } else {
15167                     computeScroll();
15168 
15169                     canvas.translate(-mScrollX, -mScrollY);
15170                     mPrivateFlags |= PFLAG_DRAWN | PFLAG_DRAWING_CACHE_VALID;
15171                     mPrivateFlags &= ~PFLAG_DIRTY_MASK;
15172 
15173                     // Fast path for layouts with no backgrounds
15174                     if ((mPrivateFlags & PFLAG_SKIP_DRAW) == PFLAG_SKIP_DRAW) {
15175                         dispatchDraw(canvas);
15176                         if (mOverlay != null && !mOverlay.isEmpty()) {
15177                             mOverlay.getOverlayView().draw(canvas);
15178                         }
15179                     } else {
15180                         draw(canvas);
15181                     }
15182                 }
15183             } finally {
15184                 renderNode.end(canvas);
15185                 setDisplayListProperties(renderNode);
15186             }
15187         } else {
15188             mPrivateFlags |= PFLAG_DRAWN | PFLAG_DRAWING_CACHE_VALID;
15189             mPrivateFlags &= ~PFLAG_DIRTY_MASK;
15190         }
15191         return renderNode;
15192     }
15193 
15194     private void resetDisplayList() {
15195         if (mRenderNode.isValid()) {
15196             mRenderNode.destroyDisplayListData();
15197         }
15198 
15199         if (mBackgroundRenderNode != null && mBackgroundRenderNode.isValid()) {
15200             mBackgroundRenderNode.destroyDisplayListData();
15201         }
15202     }
15203 
15204     /**
15205      * <p>Calling this method is equivalent to calling <code>getDrawingCache(false)</code>.</p>
15206      *
15207      * @return A non-scaled bitmap representing this view or null if cache is disabled.
15208      *
15209      * @see #getDrawingCache(boolean)
15210      */
15211     public Bitmap getDrawingCache() {
15212         return getDrawingCache(false);
15213     }
15214 
15215     /**
15216      * <p>Returns the bitmap in which this view drawing is cached. The returned bitmap
15217      * is null when caching is disabled. If caching is enabled and the cache is not ready,
15218      * this method will create it. Calling {@link #draw(android.graphics.Canvas)} will not
15219      * draw from the cache when the cache is enabled. To benefit from the cache, you must
15220      * request the drawing cache by calling this method and draw it on screen if the
15221      * returned bitmap is not null.</p>
15222      *
15223      * <p>Note about auto scaling in compatibility mode: When auto scaling is not enabled,
15224      * this method will create a bitmap of the same size as this view. Because this bitmap
15225      * will be drawn scaled by the parent ViewGroup, the result on screen might show
15226      * scaling artifacts. To avoid such artifacts, you should call this method by setting
15227      * the auto scaling to true. Doing so, however, will generate a bitmap of a different
15228      * size than the view. This implies that your application must be able to handle this
15229      * size.</p>
15230      *
15231      * @param autoScale Indicates whether the generated bitmap should be scaled based on
15232      *        the current density of the screen when the application is in compatibility
15233      *        mode.
15234      *
15235      * @return A bitmap representing this view or null if cache is disabled.
15236      *
15237      * @see #setDrawingCacheEnabled(boolean)
15238      * @see #isDrawingCacheEnabled()
15239      * @see #buildDrawingCache(boolean)
15240      * @see #destroyDrawingCache()
15241      */
15242     public Bitmap getDrawingCache(boolean autoScale) {
15243         if ((mViewFlags & WILL_NOT_CACHE_DRAWING) == WILL_NOT_CACHE_DRAWING) {
15244             return null;
15245         }
15246         if ((mViewFlags & DRAWING_CACHE_ENABLED) == DRAWING_CACHE_ENABLED) {
15247             buildDrawingCache(autoScale);
15248         }
15249         return autoScale ? mDrawingCache : mUnscaledDrawingCache;
15250     }
15251 
15252     /**
15253      * <p>Frees the resources used by the drawing cache. If you call
15254      * {@link #buildDrawingCache()} manually without calling
15255      * {@link #setDrawingCacheEnabled(boolean) setDrawingCacheEnabled(true)}, you
15256      * should cleanup the cache with this method afterwards.</p>
15257      *
15258      * @see #setDrawingCacheEnabled(boolean)
15259      * @see #buildDrawingCache()
15260      * @see #getDrawingCache()
15261      */
15262     public void destroyDrawingCache() {
15263         if (mDrawingCache != null) {
15264             mDrawingCache.recycle();
15265             mDrawingCache = null;
15266         }
15267         if (mUnscaledDrawingCache != null) {
15268             mUnscaledDrawingCache.recycle();
15269             mUnscaledDrawingCache = null;
15270         }
15271     }
15272 
15273     /**
15274      * Setting a solid background color for the drawing cache's bitmaps will improve
15275      * performance and memory usage. Note, though that this should only be used if this
15276      * view will always be drawn on top of a solid color.
15277      *
15278      * @param color The background color to use for the drawing cache's bitmap
15279      *
15280      * @see #setDrawingCacheEnabled(boolean)
15281      * @see #buildDrawingCache()
15282      * @see #getDrawingCache()
15283      */
15284     public void setDrawingCacheBackgroundColor(@ColorInt int color) {
15285         if (color != mDrawingCacheBackgroundColor) {
15286             mDrawingCacheBackgroundColor = color;
15287             mPrivateFlags &= ~PFLAG_DRAWING_CACHE_VALID;
15288         }
15289     }
15290 
15291     /**
15292      * @see #setDrawingCacheBackgroundColor(int)
15293      *
15294      * @return The background color to used for the drawing cache's bitmap
15295      */
15296     @ColorInt
15297     public int getDrawingCacheBackgroundColor() {
15298         return mDrawingCacheBackgroundColor;
15299     }
15300 
15301     /**
15302      * <p>Calling this method is equivalent to calling <code>buildDrawingCache(false)</code>.</p>
15303      *
15304      * @see #buildDrawingCache(boolean)
15305      */
15306     public void buildDrawingCache() {
15307         buildDrawingCache(false);
15308     }
15309 
15310     /**
15311      * <p>Forces the drawing cache to be built if the drawing cache is invalid.</p>
15312      *
15313      * <p>If you call {@link #buildDrawingCache()} manually without calling
15314      * {@link #setDrawingCacheEnabled(boolean) setDrawingCacheEnabled(true)}, you
15315      * should cleanup the cache by calling {@link #destroyDrawingCache()} afterwards.</p>
15316      *
15317      * <p>Note about auto scaling in compatibility mode: When auto scaling is not enabled,
15318      * this method will create a bitmap of the same size as this view. Because this bitmap
15319      * will be drawn scaled by the parent ViewGroup, the result on screen might show
15320      * scaling artifacts. To avoid such artifacts, you should call this method by setting
15321      * the auto scaling to true. Doing so, however, will generate a bitmap of a different
15322      * size than the view. This implies that your application must be able to handle this
15323      * size.</p>
15324      *
15325      * <p>You should avoid calling this method when hardware acceleration is enabled. If
15326      * you do not need the drawing cache bitmap, calling this method will increase memory
15327      * usage and cause the view to be rendered in software once, thus negatively impacting
15328      * performance.</p>
15329      *
15330      * @see #getDrawingCache()
15331      * @see #destroyDrawingCache()
15332      */
15333     public void buildDrawingCache(boolean autoScale) {
15334         if ((mPrivateFlags & PFLAG_DRAWING_CACHE_VALID) == 0 || (autoScale ?
15335                 mDrawingCache == null : mUnscaledDrawingCache == null)) {
15336             if (Trace.isTagEnabled(Trace.TRACE_TAG_VIEW)) {
15337                 Trace.traceBegin(Trace.TRACE_TAG_VIEW,
15338                         "buildDrawingCache/SW Layer for " + getClass().getSimpleName());
15339             }
15340             try {
15341                 buildDrawingCacheImpl(autoScale);
15342             } finally {
15343                 Trace.traceEnd(Trace.TRACE_TAG_VIEW);
15344             }
15345         }
15346     }
15347 
15348     /**
15349      * private, internal implementation of buildDrawingCache, used to enable tracing
15350      */
15351     private void buildDrawingCacheImpl(boolean autoScale) {
15352         mCachingFailed = false;
15353 
15354         int width = mRight - mLeft;
15355         int height = mBottom - mTop;
15356 
15357         final AttachInfo attachInfo = mAttachInfo;
15358         final boolean scalingRequired = attachInfo != null && attachInfo.mScalingRequired;
15359 
15360         if (autoScale && scalingRequired) {
15361             width = (int) ((width * attachInfo.mApplicationScale) + 0.5f);
15362             height = (int) ((height * attachInfo.mApplicationScale) + 0.5f);
15363         }
15364 
15365         final int drawingCacheBackgroundColor = mDrawingCacheBackgroundColor;
15366         final boolean opaque = drawingCacheBackgroundColor != 0 || isOpaque();
15367         final boolean use32BitCache = attachInfo != null && attachInfo.mUse32BitDrawingCache;
15368 
15369         final long projectedBitmapSize = width * height * (opaque && !use32BitCache ? 2 : 4);
15370         final long drawingCacheSize =
15371                 ViewConfiguration.get(mContext).getScaledMaximumDrawingCacheSize();
15372         if (width <= 0 || height <= 0 || projectedBitmapSize > drawingCacheSize) {
15373             if (width > 0 && height > 0) {
15374                 Log.w(VIEW_LOG_TAG, getClass().getSimpleName() + " not displayed because it is"
15375                         + " too large to fit into a software layer (or drawing cache), needs "
15376                         + projectedBitmapSize + " bytes, only "
15377                         + drawingCacheSize + " available");
15378             }
15379             destroyDrawingCache();
15380             mCachingFailed = true;
15381             return;
15382         }
15383 
15384         boolean clear = true;
15385         Bitmap bitmap = autoScale ? mDrawingCache : mUnscaledDrawingCache;
15386 
15387         if (bitmap == null || bitmap.getWidth() != width || bitmap.getHeight() != height) {
15388             Bitmap.Config quality;
15389             if (!opaque) {
15390                 // Never pick ARGB_4444 because it looks awful
15391                 // Keep the DRAWING_CACHE_QUALITY_LOW flag just in case
15392                 switch (mViewFlags & DRAWING_CACHE_QUALITY_MASK) {
15393                     case DRAWING_CACHE_QUALITY_AUTO:
15394                     case DRAWING_CACHE_QUALITY_LOW:
15395                     case DRAWING_CACHE_QUALITY_HIGH:
15396                     default:
15397                         quality = Bitmap.Config.ARGB_8888;
15398                         break;
15399                 }
15400             } else {
15401                 // Optimization for translucent windows
15402                 // If the window is translucent, use a 32 bits bitmap to benefit from memcpy()
15403                 quality = use32BitCache ? Bitmap.Config.ARGB_8888 : Bitmap.Config.RGB_565;
15404             }
15405 
15406             // Try to cleanup memory
15407             if (bitmap != null) bitmap.recycle();
15408 
15409             try {
15410                 bitmap = Bitmap.createBitmap(mResources.getDisplayMetrics(),
15411                         width, height, quality);
15412                 bitmap.setDensity(getResources().getDisplayMetrics().densityDpi);
15413                 if (autoScale) {
15414                     mDrawingCache = bitmap;
15415                 } else {
15416                     mUnscaledDrawingCache = bitmap;
15417                 }
15418                 if (opaque && use32BitCache) bitmap.setHasAlpha(false);
15419             } catch (OutOfMemoryError e) {
15420                 // If there is not enough memory to create the bitmap cache, just
15421                 // ignore the issue as bitmap caches are not required to draw the
15422                 // view hierarchy
15423                 if (autoScale) {
15424                     mDrawingCache = null;
15425                 } else {
15426                     mUnscaledDrawingCache = null;
15427                 }
15428                 mCachingFailed = true;
15429                 return;
15430             }
15431 
15432             clear = drawingCacheBackgroundColor != 0;
15433         }
15434 
15435         Canvas canvas;
15436         if (attachInfo != null) {
15437             canvas = attachInfo.mCanvas;
15438             if (canvas == null) {
15439                 canvas = new Canvas();
15440             }
15441             canvas.setBitmap(bitmap);
15442             // Temporarily clobber the cached Canvas in case one of our children
15443             // is also using a drawing cache. Without this, the children would
15444             // steal the canvas by attaching their own bitmap to it and bad, bad
15445             // thing would happen (invisible views, corrupted drawings, etc.)
15446             attachInfo.mCanvas = null;
15447         } else {
15448             // This case should hopefully never or seldom happen
15449             canvas = new Canvas(bitmap);
15450         }
15451 
15452         if (clear) {
15453             bitmap.eraseColor(drawingCacheBackgroundColor);
15454         }
15455 
15456         computeScroll();
15457         final int restoreCount = canvas.save();
15458 
15459         if (autoScale && scalingRequired) {
15460             final float scale = attachInfo.mApplicationScale;
15461             canvas.scale(scale, scale);
15462         }
15463 
15464         canvas.translate(-mScrollX, -mScrollY);
15465 
15466         mPrivateFlags |= PFLAG_DRAWN;
15467         if (mAttachInfo == null || !mAttachInfo.mHardwareAccelerated ||
15468                 mLayerType != LAYER_TYPE_NONE) {
15469             mPrivateFlags |= PFLAG_DRAWING_CACHE_VALID;
15470         }
15471 
15472         // Fast path for layouts with no backgrounds
15473         if ((mPrivateFlags & PFLAG_SKIP_DRAW) == PFLAG_SKIP_DRAW) {
15474             mPrivateFlags &= ~PFLAG_DIRTY_MASK;
15475             dispatchDraw(canvas);
15476             if (mOverlay != null && !mOverlay.isEmpty()) {
15477                 mOverlay.getOverlayView().draw(canvas);
15478             }
15479         } else {
15480             draw(canvas);
15481         }
15482 
15483         canvas.restoreToCount(restoreCount);
15484         canvas.setBitmap(null);
15485 
15486         if (attachInfo != null) {
15487             // Restore the cached Canvas for our siblings
15488             attachInfo.mCanvas = canvas;
15489         }
15490     }
15491 
15492     /**
15493      * Create a snapshot of the view into a bitmap.  We should probably make
15494      * some form of this public, but should think about the API.
15495      */
15496     Bitmap createSnapshot(Bitmap.Config quality, int backgroundColor, boolean skipChildren) {
15497         int width = mRight - mLeft;
15498         int height = mBottom - mTop;
15499 
15500         final AttachInfo attachInfo = mAttachInfo;
15501         final float scale = attachInfo != null ? attachInfo.mApplicationScale : 1.0f;
15502         width = (int) ((width * scale) + 0.5f);
15503         height = (int) ((height * scale) + 0.5f);
15504 
15505         Bitmap bitmap = Bitmap.createBitmap(mResources.getDisplayMetrics(),
15506                 width > 0 ? width : 1, height > 0 ? height : 1, quality);
15507         if (bitmap == null) {
15508             throw new OutOfMemoryError();
15509         }
15510 
15511         Resources resources = getResources();
15512         if (resources != null) {
15513             bitmap.setDensity(resources.getDisplayMetrics().densityDpi);
15514         }
15515 
15516         Canvas canvas;
15517         if (attachInfo != null) {
15518             canvas = attachInfo.mCanvas;
15519             if (canvas == null) {
15520                 canvas = new Canvas();
15521             }
15522             canvas.setBitmap(bitmap);
15523             // Temporarily clobber the cached Canvas in case one of our children
15524             // is also using a drawing cache. Without this, the children would
15525             // steal the canvas by attaching their own bitmap to it and bad, bad
15526             // things would happen (invisible views, corrupted drawings, etc.)
15527             attachInfo.mCanvas = null;
15528         } else {
15529             // This case should hopefully never or seldom happen
15530             canvas = new Canvas(bitmap);
15531         }
15532 
15533         if ((backgroundColor & 0xff000000) != 0) {
15534             bitmap.eraseColor(backgroundColor);
15535         }
15536 
15537         computeScroll();
15538         final int restoreCount = canvas.save();
15539         canvas.scale(scale, scale);
15540         canvas.translate(-mScrollX, -mScrollY);
15541 
15542         // Temporarily remove the dirty mask
15543         int flags = mPrivateFlags;
15544         mPrivateFlags &= ~PFLAG_DIRTY_MASK;
15545 
15546         // Fast path for layouts with no backgrounds
15547         if ((mPrivateFlags & PFLAG_SKIP_DRAW) == PFLAG_SKIP_DRAW) {
15548             dispatchDraw(canvas);
15549             if (mOverlay != null && !mOverlay.isEmpty()) {
15550                 mOverlay.getOverlayView().draw(canvas);
15551             }
15552         } else {
15553             draw(canvas);
15554         }
15555 
15556         mPrivateFlags = flags;
15557 
15558         canvas.restoreToCount(restoreCount);
15559         canvas.setBitmap(null);
15560 
15561         if (attachInfo != null) {
15562             // Restore the cached Canvas for our siblings
15563             attachInfo.mCanvas = canvas;
15564         }
15565 
15566         return bitmap;
15567     }
15568 
15569     /**
15570      * Indicates whether this View is currently in edit mode. A View is usually
15571      * in edit mode when displayed within a developer tool. For instance, if
15572      * this View is being drawn by a visual user interface builder, this method
15573      * should return true.
15574      *
15575      * Subclasses should check the return value of this method to provide
15576      * different behaviors if their normal behavior might interfere with the
15577      * host environment. For instance: the class spawns a thread in its
15578      * constructor, the drawing code relies on device-specific features, etc.
15579      *
15580      * This method is usually checked in the drawing code of custom widgets.
15581      *
15582      * @return True if this View is in edit mode, false otherwise.
15583      */
15584     public boolean isInEditMode() {
15585         return false;
15586     }
15587 
15588     /**
15589      * If the View draws content inside its padding and enables fading edges,
15590      * it needs to support padding offsets. Padding offsets are added to the
15591      * fading edges to extend the length of the fade so that it covers pixels
15592      * drawn inside the padding.
15593      *
15594      * Subclasses of this class should override this method if they need
15595      * to draw content inside the padding.
15596      *
15597      * @return True if padding offset must be applied, false otherwise.
15598      *
15599      * @see #getLeftPaddingOffset()
15600      * @see #getRightPaddingOffset()
15601      * @see #getTopPaddingOffset()
15602      * @see #getBottomPaddingOffset()
15603      *
15604      * @since CURRENT
15605      */
15606     protected boolean isPaddingOffsetRequired() {
15607         return false;
15608     }
15609 
15610     /**
15611      * Amount by which to extend the left fading region. Called only when
15612      * {@link #isPaddingOffsetRequired()} returns true.
15613      *
15614      * @return The left padding offset in pixels.
15615      *
15616      * @see #isPaddingOffsetRequired()
15617      *
15618      * @since CURRENT
15619      */
15620     protected int getLeftPaddingOffset() {
15621         return 0;
15622     }
15623 
15624     /**
15625      * Amount by which to extend the right fading region. Called only when
15626      * {@link #isPaddingOffsetRequired()} returns true.
15627      *
15628      * @return The right padding offset in pixels.
15629      *
15630      * @see #isPaddingOffsetRequired()
15631      *
15632      * @since CURRENT
15633      */
15634     protected int getRightPaddingOffset() {
15635         return 0;
15636     }
15637 
15638     /**
15639      * Amount by which to extend the top fading region. Called only when
15640      * {@link #isPaddingOffsetRequired()} returns true.
15641      *
15642      * @return The top padding offset in pixels.
15643      *
15644      * @see #isPaddingOffsetRequired()
15645      *
15646      * @since CURRENT
15647      */
15648     protected int getTopPaddingOffset() {
15649         return 0;
15650     }
15651 
15652     /**
15653      * Amount by which to extend the bottom fading region. Called only when
15654      * {@link #isPaddingOffsetRequired()} returns true.
15655      *
15656      * @return The bottom padding offset in pixels.
15657      *
15658      * @see #isPaddingOffsetRequired()
15659      *
15660      * @since CURRENT
15661      */
15662     protected int getBottomPaddingOffset() {
15663         return 0;
15664     }
15665 
15666     /**
15667      * @hide
15668      * @param offsetRequired
15669      */
15670     protected int getFadeTop(boolean offsetRequired) {
15671         int top = mPaddingTop;
15672         if (offsetRequired) top += getTopPaddingOffset();
15673         return top;
15674     }
15675 
15676     /**
15677      * @hide
15678      * @param offsetRequired
15679      */
15680     protected int getFadeHeight(boolean offsetRequired) {
15681         int padding = mPaddingTop;
15682         if (offsetRequired) padding += getTopPaddingOffset();
15683         return mBottom - mTop - mPaddingBottom - padding;
15684     }
15685 
15686     /**
15687      * <p>Indicates whether this view is attached to a hardware accelerated
15688      * window or not.</p>
15689      *
15690      * <p>Even if this method returns true, it does not mean that every call
15691      * to {@link #draw(android.graphics.Canvas)} will be made with an hardware
15692      * accelerated {@link android.graphics.Canvas}. For instance, if this view
15693      * is drawn onto an offscreen {@link android.graphics.Bitmap} and its
15694      * window is hardware accelerated,
15695      * {@link android.graphics.Canvas#isHardwareAccelerated()} will likely
15696      * return false, and this method will return true.</p>
15697      *
15698      * @return True if the view is attached to a window and the window is
15699      *         hardware accelerated; false in any other case.
15700      */
15701     @ViewDebug.ExportedProperty(category = "drawing")
15702     public boolean isHardwareAccelerated() {
15703         return mAttachInfo != null && mAttachInfo.mHardwareAccelerated;
15704     }
15705 
15706     /**
15707      * Sets a rectangular area on this view to which the view will be clipped
15708      * when it is drawn. Setting the value to null will remove the clip bounds
15709      * and the view will draw normally, using its full bounds.
15710      *
15711      * @param clipBounds The rectangular area, in the local coordinates of
15712      * this view, to which future drawing operations will be clipped.
15713      */
15714     public void setClipBounds(Rect clipBounds) {
15715         if (clipBounds == mClipBounds
15716                 || (clipBounds != null && clipBounds.equals(mClipBounds))) {
15717             return;
15718         }
15719         if (clipBounds != null) {
15720             if (mClipBounds == null) {
15721                 mClipBounds = new Rect(clipBounds);
15722             } else {
15723                 mClipBounds.set(clipBounds);
15724             }
15725         } else {
15726             mClipBounds = null;
15727         }
15728         mRenderNode.setClipBounds(mClipBounds);
15729         invalidateViewProperty(false, false);
15730     }
15731 
15732     /**
15733      * Returns a copy of the current {@link #setClipBounds(Rect) clipBounds}.
15734      *
15735      * @return A copy of the current clip bounds if clip bounds are set,
15736      * otherwise null.
15737      */
15738     public Rect getClipBounds() {
15739         return (mClipBounds != null) ? new Rect(mClipBounds) : null;
15740     }
15741 
15742 
15743     /**
15744      * Populates an output rectangle with the clip bounds of the view,
15745      * returning {@code true} if successful or {@code false} if the view's
15746      * clip bounds are {@code null}.
15747      *
15748      * @param outRect rectangle in which to place the clip bounds of the view
15749      * @return {@code true} if successful or {@code false} if the view's
15750      *         clip bounds are {@code null}
15751      */
15752     public boolean getClipBounds(Rect outRect) {
15753         if (mClipBounds != null) {
15754             outRect.set(mClipBounds);
15755             return true;
15756         }
15757         return false;
15758     }
15759 
15760     /**
15761      * Utility function, called by draw(canvas, parent, drawingTime) to handle the less common
15762      * case of an active Animation being run on the view.
15763      */
15764     private boolean applyLegacyAnimation(ViewGroup parent, long drawingTime,
15765             Animation a, boolean scalingRequired) {
15766         Transformation invalidationTransform;
15767         final int flags = parent.mGroupFlags;
15768         final boolean initialized = a.isInitialized();
15769         if (!initialized) {
15770             a.initialize(mRight - mLeft, mBottom - mTop, parent.getWidth(), parent.getHeight());
15771             a.initializeInvalidateRegion(0, 0, mRight - mLeft, mBottom - mTop);
15772             if (mAttachInfo != null) a.setListenerHandler(mAttachInfo.mHandler);
15773             onAnimationStart();
15774         }
15775 
15776         final Transformation t = parent.getChildTransformation();
15777         boolean more = a.getTransformation(drawingTime, t, 1f);
15778         if (scalingRequired && mAttachInfo.mApplicationScale != 1f) {
15779             if (parent.mInvalidationTransformation == null) {
15780                 parent.mInvalidationTransformation = new Transformation();
15781             }
15782             invalidationTransform = parent.mInvalidationTransformation;
15783             a.getTransformation(drawingTime, invalidationTransform, 1f);
15784         } else {
15785             invalidationTransform = t;
15786         }
15787 
15788         if (more) {
15789             if (!a.willChangeBounds()) {
15790                 if ((flags & (ViewGroup.FLAG_OPTIMIZE_INVALIDATE | ViewGroup.FLAG_ANIMATION_DONE)) ==
15791                         ViewGroup.FLAG_OPTIMIZE_INVALIDATE) {
15792                     parent.mGroupFlags |= ViewGroup.FLAG_INVALIDATE_REQUIRED;
15793                 } else if ((flags & ViewGroup.FLAG_INVALIDATE_REQUIRED) == 0) {
15794                     // The child need to draw an animation, potentially offscreen, so
15795                     // make sure we do not cancel invalidate requests
15796                     parent.mPrivateFlags |= PFLAG_DRAW_ANIMATION;
15797                     parent.invalidate(mLeft, mTop, mRight, mBottom);
15798                 }
15799             } else {
15800                 if (parent.mInvalidateRegion == null) {
15801                     parent.mInvalidateRegion = new RectF();
15802                 }
15803                 final RectF region = parent.mInvalidateRegion;
15804                 a.getInvalidateRegion(0, 0, mRight - mLeft, mBottom - mTop, region,
15805                         invalidationTransform);
15806 
15807                 // The child need to draw an animation, potentially offscreen, so
15808                 // make sure we do not cancel invalidate requests
15809                 parent.mPrivateFlags |= PFLAG_DRAW_ANIMATION;
15810 
15811                 final int left = mLeft + (int) region.left;
15812                 final int top = mTop + (int) region.top;
15813                 parent.invalidate(left, top, left + (int) (region.width() + .5f),
15814                         top + (int) (region.height() + .5f));
15815             }
15816         }
15817         return more;
15818     }
15819 
15820     /**
15821      * This method is called by getDisplayList() when a display list is recorded for a View.
15822      * It pushes any properties to the RenderNode that aren't managed by the RenderNode.
15823      */
15824     void setDisplayListProperties(RenderNode renderNode) {
15825         if (renderNode != null) {
15826             renderNode.setHasOverlappingRendering(hasOverlappingRendering());
15827             renderNode.setClipToBounds(mParent instanceof ViewGroup
15828                     && ((ViewGroup) mParent).getClipChildren());
15829 
15830             float alpha = 1;
15831             if (mParent instanceof ViewGroup && (((ViewGroup) mParent).mGroupFlags &
15832                     ViewGroup.FLAG_SUPPORT_STATIC_TRANSFORMATIONS) != 0) {
15833                 ViewGroup parentVG = (ViewGroup) mParent;
15834                 final Transformation t = parentVG.getChildTransformation();
15835                 if (parentVG.getChildStaticTransformation(this, t)) {
15836                     final int transformType = t.getTransformationType();
15837                     if (transformType != Transformation.TYPE_IDENTITY) {
15838                         if ((transformType & Transformation.TYPE_ALPHA) != 0) {
15839                             alpha = t.getAlpha();
15840                         }
15841                         if ((transformType & Transformation.TYPE_MATRIX) != 0) {
15842                             renderNode.setStaticMatrix(t.getMatrix());
15843                         }
15844                     }
15845                 }
15846             }
15847             if (mTransformationInfo != null) {
15848                 alpha *= getFinalAlpha();
15849                 if (alpha < 1) {
15850                     final int multipliedAlpha = (int) (255 * alpha);
15851                     if (onSetAlpha(multipliedAlpha)) {
15852                         alpha = 1;
15853                     }
15854                 }
15855                 renderNode.setAlpha(alpha);
15856             } else if (alpha < 1) {
15857                 renderNode.setAlpha(alpha);
15858             }
15859         }
15860     }
15861 
15862     /**
15863      * This method is called by ViewGroup.drawChild() to have each child view draw itself.
15864      *
15865      * This is where the View specializes rendering behavior based on layer type,
15866      * and hardware acceleration.
15867      */
15868     boolean draw(Canvas canvas, ViewGroup parent, long drawingTime) {
15869         final boolean hardwareAcceleratedCanvas = canvas.isHardwareAccelerated();
15870         /* If an attached view draws to a HW canvas, it may use its RenderNode + DisplayList.
15871          *
15872          * If a view is dettached, its DisplayList shouldn't exist. If the canvas isn't
15873          * HW accelerated, it can't handle drawing RenderNodes.
15874          */
15875         boolean drawingWithRenderNode = mAttachInfo != null
15876                 && mAttachInfo.mHardwareAccelerated
15877                 && hardwareAcceleratedCanvas;
15878 
15879         boolean more = false;
15880         final boolean childHasIdentityMatrix = hasIdentityMatrix();
15881         final int parentFlags = parent.mGroupFlags;
15882 
15883         if ((parentFlags & ViewGroup.FLAG_CLEAR_TRANSFORMATION) != 0) {
15884             parent.getChildTransformation().clear();
15885             parent.mGroupFlags &= ~ViewGroup.FLAG_CLEAR_TRANSFORMATION;
15886         }
15887 
15888         Transformation transformToApply = null;
15889         boolean concatMatrix = false;
15890         final boolean scalingRequired = mAttachInfo != null && mAttachInfo.mScalingRequired;
15891         final Animation a = getAnimation();
15892         if (a != null) {
15893             more = applyLegacyAnimation(parent, drawingTime, a, scalingRequired);
15894             concatMatrix = a.willChangeTransformationMatrix();
15895             if (concatMatrix) {
15896                 mPrivateFlags3 |= PFLAG3_VIEW_IS_ANIMATING_TRANSFORM;
15897             }
15898             transformToApply = parent.getChildTransformation();
15899         } else {
15900             if ((mPrivateFlags3 & PFLAG3_VIEW_IS_ANIMATING_TRANSFORM) != 0) {
15901                 // No longer animating: clear out old animation matrix
15902                 mRenderNode.setAnimationMatrix(null);
15903                 mPrivateFlags3 &= ~PFLAG3_VIEW_IS_ANIMATING_TRANSFORM;
15904             }
15905             if (!drawingWithRenderNode
15906                     && (parentFlags & ViewGroup.FLAG_SUPPORT_STATIC_TRANSFORMATIONS) != 0) {
15907                 final Transformation t = parent.getChildTransformation();
15908                 final boolean hasTransform = parent.getChildStaticTransformation(this, t);
15909                 if (hasTransform) {
15910                     final int transformType = t.getTransformationType();
15911                     transformToApply = transformType != Transformation.TYPE_IDENTITY ? t : null;
15912                     concatMatrix = (transformType & Transformation.TYPE_MATRIX) != 0;
15913                 }
15914             }
15915         }
15916 
15917         concatMatrix |= !childHasIdentityMatrix;
15918 
15919         // Sets the flag as early as possible to allow draw() implementations
15920         // to call invalidate() successfully when doing animations
15921         mPrivateFlags |= PFLAG_DRAWN;
15922 
15923         if (!concatMatrix &&
15924                 (parentFlags & (ViewGroup.FLAG_SUPPORT_STATIC_TRANSFORMATIONS |
15925                         ViewGroup.FLAG_CLIP_CHILDREN)) == ViewGroup.FLAG_CLIP_CHILDREN &&
15926                 canvas.quickReject(mLeft, mTop, mRight, mBottom, Canvas.EdgeType.BW) &&
15927                 (mPrivateFlags & PFLAG_DRAW_ANIMATION) == 0) {
15928             mPrivateFlags2 |= PFLAG2_VIEW_QUICK_REJECTED;
15929             return more;
15930         }
15931         mPrivateFlags2 &= ~PFLAG2_VIEW_QUICK_REJECTED;
15932 
15933         if (hardwareAcceleratedCanvas) {
15934             // Clear INVALIDATED flag to allow invalidation to occur during rendering, but
15935             // retain the flag's value temporarily in the mRecreateDisplayList flag
15936             mRecreateDisplayList = (mPrivateFlags & PFLAG_INVALIDATED) != 0;
15937             mPrivateFlags &= ~PFLAG_INVALIDATED;
15938         }
15939 
15940         RenderNode renderNode = null;
15941         Bitmap cache = null;
15942         int layerType = getLayerType(); // TODO: signify cache state with just 'cache' local
15943         if (layerType == LAYER_TYPE_SOFTWARE
15944                 || (!drawingWithRenderNode && layerType != LAYER_TYPE_NONE)) {
15945             // If not drawing with RenderNode, treat HW layers as SW
15946             layerType = LAYER_TYPE_SOFTWARE;
15947             buildDrawingCache(true);
15948             cache = getDrawingCache(true);
15949         }
15950 
15951         if (drawingWithRenderNode) {
15952             // Delay getting the display list until animation-driven alpha values are
15953             // set up and possibly passed on to the view
15954             renderNode = updateDisplayListIfDirty();
15955             if (!renderNode.isValid()) {
15956                 // Uncommon, but possible. If a view is removed from the hierarchy during the call
15957                 // to getDisplayList(), the display list will be marked invalid and we should not
15958                 // try to use it again.
15959                 renderNode = null;
15960                 drawingWithRenderNode = false;
15961             }
15962         }
15963 
15964         int sx = 0;
15965         int sy = 0;
15966         if (!drawingWithRenderNode) {
15967             computeScroll();
15968             sx = mScrollX;
15969             sy = mScrollY;
15970         }
15971 
15972         final boolean drawingWithDrawingCache = cache != null && !drawingWithRenderNode;
15973         final boolean offsetForScroll = cache == null && !drawingWithRenderNode;
15974 
15975         int restoreTo = -1;
15976         if (!drawingWithRenderNode || transformToApply != null) {
15977             restoreTo = canvas.save();
15978         }
15979         if (offsetForScroll) {
15980             canvas.translate(mLeft - sx, mTop - sy);
15981         } else {
15982             if (!drawingWithRenderNode) {
15983                 canvas.translate(mLeft, mTop);
15984             }
15985             if (scalingRequired) {
15986                 if (drawingWithRenderNode) {
15987                     // TODO: Might not need this if we put everything inside the DL
15988                     restoreTo = canvas.save();
15989                 }
15990                 // mAttachInfo cannot be null, otherwise scalingRequired == false
15991                 final float scale = 1.0f / mAttachInfo.mApplicationScale;
15992                 canvas.scale(scale, scale);
15993             }
15994         }
15995 
15996         float alpha = drawingWithRenderNode ? 1 : (getAlpha() * getTransitionAlpha());
15997         if (transformToApply != null
15998                 || alpha < 1
15999                 || !hasIdentityMatrix()
16000                 || (mPrivateFlags3 & PFLAG3_VIEW_IS_ANIMATING_ALPHA) != 0) {
16001             if (transformToApply != null || !childHasIdentityMatrix) {
16002                 int transX = 0;
16003                 int transY = 0;
16004 
16005                 if (offsetForScroll) {
16006                     transX = -sx;
16007                     transY = -sy;
16008                 }
16009 
16010                 if (transformToApply != null) {
16011                     if (concatMatrix) {
16012                         if (drawingWithRenderNode) {
16013                             renderNode.setAnimationMatrix(transformToApply.getMatrix());
16014                         } else {
16015                             // Undo the scroll translation, apply the transformation matrix,
16016                             // then redo the scroll translate to get the correct result.
16017                             canvas.translate(-transX, -transY);
16018                             canvas.concat(transformToApply.getMatrix());
16019                             canvas.translate(transX, transY);
16020                         }
16021                         parent.mGroupFlags |= ViewGroup.FLAG_CLEAR_TRANSFORMATION;
16022                     }
16023 
16024                     float transformAlpha = transformToApply.getAlpha();
16025                     if (transformAlpha < 1) {
16026                         alpha *= transformAlpha;
16027                         parent.mGroupFlags |= ViewGroup.FLAG_CLEAR_TRANSFORMATION;
16028                     }
16029                 }
16030 
16031                 if (!childHasIdentityMatrix && !drawingWithRenderNode) {
16032                     canvas.translate(-transX, -transY);
16033                     canvas.concat(getMatrix());
16034                     canvas.translate(transX, transY);
16035                 }
16036             }
16037 
16038             // Deal with alpha if it is or used to be <1
16039             if (alpha < 1 || (mPrivateFlags3 & PFLAG3_VIEW_IS_ANIMATING_ALPHA) != 0) {
16040                 if (alpha < 1) {
16041                     mPrivateFlags3 |= PFLAG3_VIEW_IS_ANIMATING_ALPHA;
16042                 } else {
16043                     mPrivateFlags3 &= ~PFLAG3_VIEW_IS_ANIMATING_ALPHA;
16044                 }
16045                 parent.mGroupFlags |= ViewGroup.FLAG_CLEAR_TRANSFORMATION;
16046                 if (!drawingWithDrawingCache) {
16047                     final int multipliedAlpha = (int) (255 * alpha);
16048                     if (!onSetAlpha(multipliedAlpha)) {
16049                         if (drawingWithRenderNode) {
16050                             renderNode.setAlpha(alpha * getAlpha() * getTransitionAlpha());
16051                         } else if (layerType == LAYER_TYPE_NONE) {
16052                             canvas.saveLayerAlpha(sx, sy, sx + getWidth(), sy + getHeight(),
16053                                     multipliedAlpha);
16054                         }
16055                     } else {
16056                         // Alpha is handled by the child directly, clobber the layer's alpha
16057                         mPrivateFlags |= PFLAG_ALPHA_SET;
16058                     }
16059                 }
16060             }
16061         } else if ((mPrivateFlags & PFLAG_ALPHA_SET) == PFLAG_ALPHA_SET) {
16062             onSetAlpha(255);
16063             mPrivateFlags &= ~PFLAG_ALPHA_SET;
16064         }
16065 
16066         if (!drawingWithRenderNode) {
16067             // apply clips directly, since RenderNode won't do it for this draw
16068             if ((parentFlags & ViewGroup.FLAG_CLIP_CHILDREN) != 0 && cache == null) {
16069                 if (offsetForScroll) {
16070                     canvas.clipRect(sx, sy, sx + getWidth(), sy + getHeight());
16071                 } else {
16072                     if (!scalingRequired || cache == null) {
16073                         canvas.clipRect(0, 0, getWidth(), getHeight());
16074                     } else {
16075                         canvas.clipRect(0, 0, cache.getWidth(), cache.getHeight());
16076                     }
16077                 }
16078             }
16079 
16080             if (mClipBounds != null) {
16081                 // clip bounds ignore scroll
16082                 canvas.clipRect(mClipBounds);
16083             }
16084         }
16085 
16086         if (!drawingWithDrawingCache) {
16087             if (drawingWithRenderNode) {
16088                 mPrivateFlags &= ~PFLAG_DIRTY_MASK;
16089                 ((DisplayListCanvas) canvas).drawRenderNode(renderNode);
16090             } else {
16091                 // Fast path for layouts with no backgrounds
16092                 if ((mPrivateFlags & PFLAG_SKIP_DRAW) == PFLAG_SKIP_DRAW) {
16093                     mPrivateFlags &= ~PFLAG_DIRTY_MASK;
16094                     dispatchDraw(canvas);
16095                 } else {
16096                     draw(canvas);
16097                 }
16098             }
16099         } else if (cache != null) {
16100             mPrivateFlags &= ~PFLAG_DIRTY_MASK;
16101             if (layerType == LAYER_TYPE_NONE) {
16102                 // no layer paint, use temporary paint to draw bitmap
16103                 Paint cachePaint = parent.mCachePaint;
16104                 if (cachePaint == null) {
16105                     cachePaint = new Paint();
16106                     cachePaint.setDither(false);
16107                     parent.mCachePaint = cachePaint;
16108                 }
16109                 cachePaint.setAlpha((int) (alpha * 255));
16110                 canvas.drawBitmap(cache, 0.0f, 0.0f, cachePaint);
16111             } else {
16112                 // use layer paint to draw the bitmap, merging the two alphas, but also restore
16113                 int layerPaintAlpha = mLayerPaint.getAlpha();
16114                 mLayerPaint.setAlpha((int) (alpha * layerPaintAlpha));
16115                 canvas.drawBitmap(cache, 0.0f, 0.0f, mLayerPaint);
16116                 mLayerPaint.setAlpha(layerPaintAlpha);
16117             }
16118         }
16119 
16120         if (restoreTo >= 0) {
16121             canvas.restoreToCount(restoreTo);
16122         }
16123 
16124         if (a != null && !more) {
16125             if (!hardwareAcceleratedCanvas && !a.getFillAfter()) {
16126                 onSetAlpha(255);
16127             }
16128             parent.finishAnimatingView(this, a);
16129         }
16130 
16131         if (more && hardwareAcceleratedCanvas) {
16132             if (a.hasAlpha() && (mPrivateFlags & PFLAG_ALPHA_SET) == PFLAG_ALPHA_SET) {
16133                 // alpha animations should cause the child to recreate its display list
16134                 invalidate(true);
16135             }
16136         }
16137 
16138         mRecreateDisplayList = false;
16139 
16140         return more;
16141     }
16142 
16143     /**
16144      * Manually render this view (and all of its children) to the given Canvas.
16145      * The view must have already done a full layout before this function is
16146      * called.  When implementing a view, implement
16147      * {@link #onDraw(android.graphics.Canvas)} instead of overriding this method.
16148      * If you do need to override this method, call the superclass version.
16149      *
16150      * @param canvas The Canvas to which the View is rendered.
16151      */
16152     @CallSuper
16153     public void draw(Canvas canvas) {
16154         final int privateFlags = mPrivateFlags;
16155         final boolean dirtyOpaque = (privateFlags & PFLAG_DIRTY_MASK) == PFLAG_DIRTY_OPAQUE &&
16156                 (mAttachInfo == null || !mAttachInfo.mIgnoreDirtyState);
16157         mPrivateFlags = (privateFlags & ~PFLAG_DIRTY_MASK) | PFLAG_DRAWN;
16158 
16159         /*
16160          * Draw traversal performs several drawing steps which must be executed
16161          * in the appropriate order:
16162          *
16163          *      1. Draw the background
16164          *      2. If necessary, save the canvas' layers to prepare for fading
16165          *      3. Draw view's content
16166          *      4. Draw children
16167          *      5. If necessary, draw the fading edges and restore layers
16168          *      6. Draw decorations (scrollbars for instance)
16169          */
16170 
16171         // Step 1, draw the background, if needed
16172         int saveCount;
16173 
16174         if (!dirtyOpaque) {
16175             drawBackground(canvas);
16176         }
16177 
16178         // skip step 2 & 5 if possible (common case)
16179         final int viewFlags = mViewFlags;
16180         boolean horizontalEdges = (viewFlags & FADING_EDGE_HORIZONTAL) != 0;
16181         boolean verticalEdges = (viewFlags & FADING_EDGE_VERTICAL) != 0;
16182         if (!verticalEdges && !horizontalEdges) {
16183             // Step 3, draw the content
16184             if (!dirtyOpaque) onDraw(canvas);
16185 
16186             // Step 4, draw the children
16187             dispatchDraw(canvas);
16188 
16189             // Overlay is part of the content and draws beneath Foreground
16190             if (mOverlay != null && !mOverlay.isEmpty()) {
16191                 mOverlay.getOverlayView().dispatchDraw(canvas);
16192             }
16193 
16194             // Step 6, draw decorations (foreground, scrollbars)
16195             onDrawForeground(canvas);
16196 
16197             // we're done...
16198             return;
16199         }
16200 
16201         /*
16202          * Here we do the full fledged routine...
16203          * (this is an uncommon case where speed matters less,
16204          * this is why we repeat some of the tests that have been
16205          * done above)
16206          */
16207 
16208         boolean drawTop = false;
16209         boolean drawBottom = false;
16210         boolean drawLeft = false;
16211         boolean drawRight = false;
16212 
16213         float topFadeStrength = 0.0f;
16214         float bottomFadeStrength = 0.0f;
16215         float leftFadeStrength = 0.0f;
16216         float rightFadeStrength = 0.0f;
16217 
16218         // Step 2, save the canvas' layers
16219         int paddingLeft = mPaddingLeft;
16220 
16221         final boolean offsetRequired = isPaddingOffsetRequired();
16222         if (offsetRequired) {
16223             paddingLeft += getLeftPaddingOffset();
16224         }
16225 
16226         int left = mScrollX + paddingLeft;
16227         int right = left + mRight - mLeft - mPaddingRight - paddingLeft;
16228         int top = mScrollY + getFadeTop(offsetRequired);
16229         int bottom = top + getFadeHeight(offsetRequired);
16230 
16231         if (offsetRequired) {
16232             right += getRightPaddingOffset();
16233             bottom += getBottomPaddingOffset();
16234         }
16235 
16236         final ScrollabilityCache scrollabilityCache = mScrollCache;
16237         final float fadeHeight = scrollabilityCache.fadingEdgeLength;
16238         int length = (int) fadeHeight;
16239 
16240         // clip the fade length if top and bottom fades overlap
16241         // overlapping fades produce odd-looking artifacts
16242         if (verticalEdges && (top + length > bottom - length)) {
16243             length = (bottom - top) / 2;
16244         }
16245 
16246         // also clip horizontal fades if necessary
16247         if (horizontalEdges && (left + length > right - length)) {
16248             length = (right - left) / 2;
16249         }
16250 
16251         if (verticalEdges) {
16252             topFadeStrength = Math.max(0.0f, Math.min(1.0f, getTopFadingEdgeStrength()));
16253             drawTop = topFadeStrength * fadeHeight > 1.0f;
16254             bottomFadeStrength = Math.max(0.0f, Math.min(1.0f, getBottomFadingEdgeStrength()));
16255             drawBottom = bottomFadeStrength * fadeHeight > 1.0f;
16256         }
16257 
16258         if (horizontalEdges) {
16259             leftFadeStrength = Math.max(0.0f, Math.min(1.0f, getLeftFadingEdgeStrength()));
16260             drawLeft = leftFadeStrength * fadeHeight > 1.0f;
16261             rightFadeStrength = Math.max(0.0f, Math.min(1.0f, getRightFadingEdgeStrength()));
16262             drawRight = rightFadeStrength * fadeHeight > 1.0f;
16263         }
16264 
16265         saveCount = canvas.getSaveCount();
16266 
16267         int solidColor = getSolidColor();
16268         if (solidColor == 0) {
16269             final int flags = Canvas.HAS_ALPHA_LAYER_SAVE_FLAG;
16270 
16271             if (drawTop) {
16272                 canvas.saveLayer(left, top, right, top + length, null, flags);
16273             }
16274 
16275             if (drawBottom) {
16276                 canvas.saveLayer(left, bottom - length, right, bottom, null, flags);
16277             }
16278 
16279             if (drawLeft) {
16280                 canvas.saveLayer(left, top, left + length, bottom, null, flags);
16281             }
16282 
16283             if (drawRight) {
16284                 canvas.saveLayer(right - length, top, right, bottom, null, flags);
16285             }
16286         } else {
16287             scrollabilityCache.setFadeColor(solidColor);
16288         }
16289 
16290         // Step 3, draw the content
16291         if (!dirtyOpaque) onDraw(canvas);
16292 
16293         // Step 4, draw the children
16294         dispatchDraw(canvas);
16295 
16296         // Step 5, draw the fade effect and restore layers
16297         final Paint p = scrollabilityCache.paint;
16298         final Matrix matrix = scrollabilityCache.matrix;
16299         final Shader fade = scrollabilityCache.shader;
16300 
16301         if (drawTop) {
16302             matrix.setScale(1, fadeHeight * topFadeStrength);
16303             matrix.postTranslate(left, top);
16304             fade.setLocalMatrix(matrix);
16305             p.setShader(fade);
16306             canvas.drawRect(left, top, right, top + length, p);
16307         }
16308 
16309         if (drawBottom) {
16310             matrix.setScale(1, fadeHeight * bottomFadeStrength);
16311             matrix.postRotate(180);
16312             matrix.postTranslate(left, bottom);
16313             fade.setLocalMatrix(matrix);
16314             p.setShader(fade);
16315             canvas.drawRect(left, bottom - length, right, bottom, p);
16316         }
16317 
16318         if (drawLeft) {
16319             matrix.setScale(1, fadeHeight * leftFadeStrength);
16320             matrix.postRotate(-90);
16321             matrix.postTranslate(left, top);
16322             fade.setLocalMatrix(matrix);
16323             p.setShader(fade);
16324             canvas.drawRect(left, top, left + length, bottom, p);
16325         }
16326 
16327         if (drawRight) {
16328             matrix.setScale(1, fadeHeight * rightFadeStrength);
16329             matrix.postRotate(90);
16330             matrix.postTranslate(right, top);
16331             fade.setLocalMatrix(matrix);
16332             p.setShader(fade);
16333             canvas.drawRect(right - length, top, right, bottom, p);
16334         }
16335 
16336         canvas.restoreToCount(saveCount);
16337 
16338         // Overlay is part of the content and draws beneath Foreground
16339         if (mOverlay != null && !mOverlay.isEmpty()) {
16340             mOverlay.getOverlayView().dispatchDraw(canvas);
16341         }
16342 
16343         // Step 6, draw decorations (foreground, scrollbars)
16344         onDrawForeground(canvas);
16345     }
16346 
16347     /**
16348      * Draws the background onto the specified canvas.
16349      *
16350      * @param canvas Canvas on which to draw the background
16351      */
16352     private void drawBackground(Canvas canvas) {
16353         final Drawable background = mBackground;
16354         if (background == null) {
16355             return;
16356         }
16357 
16358         setBackgroundBounds();
16359 
16360         // Attempt to use a display list if requested.
16361         if (canvas.isHardwareAccelerated() && mAttachInfo != null
16362                 && mAttachInfo.mHardwareRenderer != null) {
16363             mBackgroundRenderNode = getDrawableRenderNode(background, mBackgroundRenderNode);
16364 
16365             final RenderNode renderNode = mBackgroundRenderNode;
16366             if (renderNode != null && renderNode.isValid()) {
16367                 setBackgroundRenderNodeProperties(renderNode);
16368                 ((DisplayListCanvas) canvas).drawRenderNode(renderNode);
16369                 return;
16370             }
16371         }
16372 
16373         final int scrollX = mScrollX;
16374         final int scrollY = mScrollY;
16375         if ((scrollX | scrollY) == 0) {
16376             background.draw(canvas);
16377         } else {
16378             canvas.translate(scrollX, scrollY);
16379             background.draw(canvas);
16380             canvas.translate(-scrollX, -scrollY);
16381         }
16382     }
16383 
16384     /**
16385      * Sets the correct background bounds and rebuilds the outline, if needed.
16386      * <p/>
16387      * This is called by LayoutLib.
16388      */
16389     void setBackgroundBounds() {
16390         if (mBackgroundSizeChanged && mBackground != null) {
16391             mBackground.setBounds(0, 0,  mRight - mLeft, mBottom - mTop);
16392             mBackgroundSizeChanged = false;
16393             rebuildOutline();
16394         }
16395     }
16396 
16397     private void setBackgroundRenderNodeProperties(RenderNode renderNode) {
16398         renderNode.setTranslationX(mScrollX);
16399         renderNode.setTranslationY(mScrollY);
16400     }
16401 
16402     /**
16403      * Creates a new display list or updates the existing display list for the
16404      * specified Drawable.
16405      *
16406      * @param drawable Drawable for which to create a display list
16407      * @param renderNode Existing RenderNode, or {@code null}
16408      * @return A valid display list for the specified drawable
16409      */
16410     private RenderNode getDrawableRenderNode(Drawable drawable, RenderNode renderNode) {
16411         if (renderNode == null) {
16412             renderNode = RenderNode.create(drawable.getClass().getName(), this);
16413         }
16414 
16415         final Rect bounds = drawable.getBounds();
16416         final int width = bounds.width();
16417         final int height = bounds.height();
16418         final DisplayListCanvas canvas = renderNode.start(width, height);
16419 
16420         // Reverse left/top translation done by drawable canvas, which will
16421         // instead be applied by rendernode's LTRB bounds below. This way, the
16422         // drawable's bounds match with its rendernode bounds and its content
16423         // will lie within those bounds in the rendernode tree.
16424         canvas.translate(-bounds.left, -bounds.top);
16425 
16426         try {
16427             drawable.draw(canvas);
16428         } finally {
16429             renderNode.end(canvas);
16430         }
16431 
16432         // Set up drawable properties that are view-independent.
16433         renderNode.setLeftTopRightBottom(bounds.left, bounds.top, bounds.right, bounds.bottom);
16434         renderNode.setProjectBackwards(drawable.isProjected());
16435         renderNode.setProjectionReceiver(true);
16436         renderNode.setClipToBounds(false);
16437         return renderNode;
16438     }
16439 
16440     /**
16441      * Returns the overlay for this view, creating it if it does not yet exist.
16442      * Adding drawables to the overlay will cause them to be displayed whenever
16443      * the view itself is redrawn. Objects in the overlay should be actively
16444      * managed: remove them when they should not be displayed anymore. The
16445      * overlay will always have the same size as its host view.
16446      *
16447      * <p>Note: Overlays do not currently work correctly with {@link
16448      * SurfaceView} or {@link TextureView}; contents in overlays for these
16449      * types of views may not display correctly.</p>
16450      *
16451      * @return The ViewOverlay object for this view.
16452      * @see ViewOverlay
16453      */
16454     public ViewOverlay getOverlay() {
16455         if (mOverlay == null) {
16456             mOverlay = new ViewOverlay(mContext, this);
16457         }
16458         return mOverlay;
16459     }
16460 
16461     /**
16462      * Override this if your view is known to always be drawn on top of a solid color background,
16463      * and needs to draw fading edges. Returning a non-zero color enables the view system to
16464      * optimize the drawing of the fading edges. If you do return a non-zero color, the alpha
16465      * should be set to 0xFF.
16466      *
16467      * @see #setVerticalFadingEdgeEnabled(boolean)
16468      * @see #setHorizontalFadingEdgeEnabled(boolean)
16469      *
16470      * @return The known solid color background for this view, or 0 if the color may vary
16471      */
16472     @ViewDebug.ExportedProperty(category = "drawing")
16473     @ColorInt
16474     public int getSolidColor() {
16475         return 0;
16476     }
16477 
16478     /**
16479      * Build a human readable string representation of the specified view flags.
16480      *
16481      * @param flags the view flags to convert to a string
16482      * @return a String representing the supplied flags
16483      */
16484     private static String printFlags(int flags) {
16485         String output = "";
16486         int numFlags = 0;
16487         if ((flags & FOCUSABLE_MASK) == FOCUSABLE) {
16488             output += "TAKES_FOCUS";
16489             numFlags++;
16490         }
16491 
16492         switch (flags & VISIBILITY_MASK) {
16493         case INVISIBLE:
16494             if (numFlags > 0) {
16495                 output += " ";
16496             }
16497             output += "INVISIBLE";
16498             // USELESS HERE numFlags++;
16499             break;
16500         case GONE:
16501             if (numFlags > 0) {
16502                 output += " ";
16503             }
16504             output += "GONE";
16505             // USELESS HERE numFlags++;
16506             break;
16507         default:
16508             break;
16509         }
16510         return output;
16511     }
16512 
16513     /**
16514      * Build a human readable string representation of the specified private
16515      * view flags.
16516      *
16517      * @param privateFlags the private view flags to convert to a string
16518      * @return a String representing the supplied flags
16519      */
16520     private static String printPrivateFlags(int privateFlags) {
16521         String output = "";
16522         int numFlags = 0;
16523 
16524         if ((privateFlags & PFLAG_WANTS_FOCUS) == PFLAG_WANTS_FOCUS) {
16525             output += "WANTS_FOCUS";
16526             numFlags++;
16527         }
16528 
16529         if ((privateFlags & PFLAG_FOCUSED) == PFLAG_FOCUSED) {
16530             if (numFlags > 0) {
16531                 output += " ";
16532             }
16533             output += "FOCUSED";
16534             numFlags++;
16535         }
16536 
16537         if ((privateFlags & PFLAG_SELECTED) == PFLAG_SELECTED) {
16538             if (numFlags > 0) {
16539                 output += " ";
16540             }
16541             output += "SELECTED";
16542             numFlags++;
16543         }
16544 
16545         if ((privateFlags & PFLAG_IS_ROOT_NAMESPACE) == PFLAG_IS_ROOT_NAMESPACE) {
16546             if (numFlags > 0) {
16547                 output += " ";
16548             }
16549             output += "IS_ROOT_NAMESPACE";
16550             numFlags++;
16551         }
16552 
16553         if ((privateFlags & PFLAG_HAS_BOUNDS) == PFLAG_HAS_BOUNDS) {
16554             if (numFlags > 0) {
16555                 output += " ";
16556             }
16557             output += "HAS_BOUNDS";
16558             numFlags++;
16559         }
16560 
16561         if ((privateFlags & PFLAG_DRAWN) == PFLAG_DRAWN) {
16562             if (numFlags > 0) {
16563                 output += " ";
16564             }
16565             output += "DRAWN";
16566             // USELESS HERE numFlags++;
16567         }
16568         return output;
16569     }
16570 
16571     /**
16572      * <p>Indicates whether or not this view's layout will be requested during
16573      * the next hierarchy layout pass.</p>
16574      *
16575      * @return true if the layout will be forced during next layout pass
16576      */
16577     public boolean isLayoutRequested() {
16578         return (mPrivateFlags & PFLAG_FORCE_LAYOUT) == PFLAG_FORCE_LAYOUT;
16579     }
16580 
16581     /**
16582      * Return true if o is a ViewGroup that is laying out using optical bounds.
16583      * @hide
16584      */
16585     public static boolean isLayoutModeOptical(Object o) {
16586         return o instanceof ViewGroup && ((ViewGroup) o).isLayoutModeOptical();
16587     }
16588 
16589     private boolean setOpticalFrame(int left, int top, int right, int bottom) {
16590         Insets parentInsets = mParent instanceof View ?
16591                 ((View) mParent).getOpticalInsets() : Insets.NONE;
16592         Insets childInsets = getOpticalInsets();
16593         return setFrame(
16594                 left   + parentInsets.left - childInsets.left,
16595                 top    + parentInsets.top  - childInsets.top,
16596                 right  + parentInsets.left + childInsets.right,
16597                 bottom + parentInsets.top  + childInsets.bottom);
16598     }
16599 
16600     /**
16601      * Assign a size and position to a view and all of its
16602      * descendants
16603      *
16604      * <p>This is the second phase of the layout mechanism.
16605      * (The first is measuring). In this phase, each parent calls
16606      * layout on all of its children to position them.
16607      * This is typically done using the child measurements
16608      * that were stored in the measure pass().</p>
16609      *
16610      * <p>Derived classes should not override this method.
16611      * Derived classes with children should override
16612      * onLayout. In that method, they should
16613      * call layout on each of their children.</p>
16614      *
16615      * @param l Left position, relative to parent
16616      * @param t Top position, relative to parent
16617      * @param r Right position, relative to parent
16618      * @param b Bottom position, relative to parent
16619      */
16620     @SuppressWarnings({"unchecked"})
16621     public void layout(int l, int t, int r, int b) {
16622         if ((mPrivateFlags3 & PFLAG3_MEASURE_NEEDED_BEFORE_LAYOUT) != 0) {
16623             onMeasure(mOldWidthMeasureSpec, mOldHeightMeasureSpec);
16624             mPrivateFlags3 &= ~PFLAG3_MEASURE_NEEDED_BEFORE_LAYOUT;
16625         }
16626 
16627         int oldL = mLeft;
16628         int oldT = mTop;
16629         int oldB = mBottom;
16630         int oldR = mRight;
16631 
16632         boolean changed = isLayoutModeOptical(mParent) ?
16633                 setOpticalFrame(l, t, r, b) : setFrame(l, t, r, b);
16634 
16635         if (changed || (mPrivateFlags & PFLAG_LAYOUT_REQUIRED) == PFLAG_LAYOUT_REQUIRED) {
16636             onLayout(changed, l, t, r, b);
16637             mPrivateFlags &= ~PFLAG_LAYOUT_REQUIRED;
16638 
16639             ListenerInfo li = mListenerInfo;
16640             if (li != null && li.mOnLayoutChangeListeners != null) {
16641                 ArrayList<OnLayoutChangeListener> listenersCopy =
16642                         (ArrayList<OnLayoutChangeListener>)li.mOnLayoutChangeListeners.clone();
16643                 int numListeners = listenersCopy.size();
16644                 for (int i = 0; i < numListeners; ++i) {
16645                     listenersCopy.get(i).onLayoutChange(this, l, t, r, b, oldL, oldT, oldR, oldB);
16646                 }
16647             }
16648         }
16649 
16650         mPrivateFlags &= ~PFLAG_FORCE_LAYOUT;
16651         mPrivateFlags3 |= PFLAG3_IS_LAID_OUT;
16652     }
16653 
16654     /**
16655      * Called from layout when this view should
16656      * assign a size and position to each of its children.
16657      *
16658      * Derived classes with children should override
16659      * this method and call layout on each of
16660      * their children.
16661      * @param changed This is a new size or position for this view
16662      * @param left Left position, relative to parent
16663      * @param top Top position, relative to parent
16664      * @param right Right position, relative to parent
16665      * @param bottom Bottom position, relative to parent
16666      */
16667     protected void onLayout(boolean changed, int left, int top, int right, int bottom) {
16668     }
16669 
16670     /**
16671      * Assign a size and position to this view.
16672      *
16673      * This is called from layout.
16674      *
16675      * @param left Left position, relative to parent
16676      * @param top Top position, relative to parent
16677      * @param right Right position, relative to parent
16678      * @param bottom Bottom position, relative to parent
16679      * @return true if the new size and position are different than the
16680      *         previous ones
16681      * {@hide}
16682      */
16683     protected boolean setFrame(int left, int top, int right, int bottom) {
16684         boolean changed = false;
16685 
16686         if (DBG) {
16687             Log.d("View", this + " View.setFrame(" + left + "," + top + ","
16688                     + right + "," + bottom + ")");
16689         }
16690 
16691         if (mLeft != left || mRight != right || mTop != top || mBottom != bottom) {
16692             changed = true;
16693 
16694             // Remember our drawn bit
16695             int drawn = mPrivateFlags & PFLAG_DRAWN;
16696 
16697             int oldWidth = mRight - mLeft;
16698             int oldHeight = mBottom - mTop;
16699             int newWidth = right - left;
16700             int newHeight = bottom - top;
16701             boolean sizeChanged = (newWidth != oldWidth) || (newHeight != oldHeight);
16702 
16703             // Invalidate our old position
16704             invalidate(sizeChanged);
16705 
16706             mLeft = left;
16707             mTop = top;
16708             mRight = right;
16709             mBottom = bottom;
16710             mRenderNode.setLeftTopRightBottom(mLeft, mTop, mRight, mBottom);
16711 
16712             mPrivateFlags |= PFLAG_HAS_BOUNDS;
16713 
16714 
16715             if (sizeChanged) {
16716                 sizeChange(newWidth, newHeight, oldWidth, oldHeight);
16717             }
16718 
16719             if ((mViewFlags & VISIBILITY_MASK) == VISIBLE || mGhostView != null) {
16720                 // If we are visible, force the DRAWN bit to on so that
16721                 // this invalidate will go through (at least to our parent).
16722                 // This is because someone may have invalidated this view
16723                 // before this call to setFrame came in, thereby clearing
16724                 // the DRAWN bit.
16725                 mPrivateFlags |= PFLAG_DRAWN;
16726                 invalidate(sizeChanged);
16727                 // parent display list may need to be recreated based on a change in the bounds
16728                 // of any child
16729                 invalidateParentCaches();
16730             }
16731 
16732             // Reset drawn bit to original value (invalidate turns it off)
16733             mPrivateFlags |= drawn;
16734 
16735             mBackgroundSizeChanged = true;
16736             if (mForegroundInfo != null) {
16737                 mForegroundInfo.mBoundsChanged = true;
16738             }
16739 
16740             notifySubtreeAccessibilityStateChangedIfNeeded();
16741         }
16742         return changed;
16743     }
16744 
16745     /**
16746      * Same as setFrame, but public and hidden. For use in {@link android.transition.ChangeBounds}.
16747      * @hide
16748      */
16749     public void setLeftTopRightBottom(int left, int top, int right, int bottom) {
16750         setFrame(left, top, right, bottom);
16751     }
16752 
16753     private void sizeChange(int newWidth, int newHeight, int oldWidth, int oldHeight) {
16754         onSizeChanged(newWidth, newHeight, oldWidth, oldHeight);
16755         if (mOverlay != null) {
16756             mOverlay.getOverlayView().setRight(newWidth);
16757             mOverlay.getOverlayView().setBottom(newHeight);
16758         }
16759         rebuildOutline();
16760     }
16761 
16762     /**
16763      * Finalize inflating a view from XML.  This is called as the last phase
16764      * of inflation, after all child views have been added.
16765      *
16766      * <p>Even if the subclass overrides onFinishInflate, they should always be
16767      * sure to call the super method, so that we get called.
16768      */
16769     @CallSuper
16770     protected void onFinishInflate() {
16771     }
16772 
16773     /**
16774      * Returns the resources associated with this view.
16775      *
16776      * @return Resources object.
16777      */
16778     public Resources getResources() {
16779         return mResources;
16780     }
16781 
16782     /**
16783      * Invalidates the specified Drawable.
16784      *
16785      * @param drawable the drawable to invalidate
16786      */
16787     @Override
16788     public void invalidateDrawable(@NonNull Drawable drawable) {
16789         if (verifyDrawable(drawable)) {
16790             final Rect dirty = drawable.getDirtyBounds();
16791             final int scrollX = mScrollX;
16792             final int scrollY = mScrollY;
16793 
16794             invalidate(dirty.left + scrollX, dirty.top + scrollY,
16795                     dirty.right + scrollX, dirty.bottom + scrollY);
16796             rebuildOutline();
16797         }
16798     }
16799 
16800     /**
16801      * Schedules an action on a drawable to occur at a specified time.
16802      *
16803      * @param who the recipient of the action
16804      * @param what the action to run on the drawable
16805      * @param when the time at which the action must occur. Uses the
16806      *        {@link SystemClock#uptimeMillis} timebase.
16807      */
16808     @Override
16809     public void scheduleDrawable(Drawable who, Runnable what, long when) {
16810         if (verifyDrawable(who) && what != null) {
16811             final long delay = when - SystemClock.uptimeMillis();
16812             if (mAttachInfo != null) {
16813                 mAttachInfo.mViewRootImpl.mChoreographer.postCallbackDelayed(
16814                         Choreographer.CALLBACK_ANIMATION, what, who,
16815                         Choreographer.subtractFrameDelay(delay));
16816             } else {
16817                 ViewRootImpl.getRunQueue().postDelayed(what, delay);
16818             }
16819         }
16820     }
16821 
16822     /**
16823      * Cancels a scheduled action on a drawable.
16824      *
16825      * @param who the recipient of the action
16826      * @param what the action to cancel
16827      */
16828     @Override
16829     public void unscheduleDrawable(Drawable who, Runnable what) {
16830         if (verifyDrawable(who) && what != null) {
16831             if (mAttachInfo != null) {
16832                 mAttachInfo.mViewRootImpl.mChoreographer.removeCallbacks(
16833                         Choreographer.CALLBACK_ANIMATION, what, who);
16834             }
16835             ViewRootImpl.getRunQueue().removeCallbacks(what);
16836         }
16837     }
16838 
16839     /**
16840      * Unschedule any events associated with the given Drawable.  This can be
16841      * used when selecting a new Drawable into a view, so that the previous
16842      * one is completely unscheduled.
16843      *
16844      * @param who The Drawable to unschedule.
16845      *
16846      * @see #drawableStateChanged
16847      */
16848     public void unscheduleDrawable(Drawable who) {
16849         if (mAttachInfo != null && who != null) {
16850             mAttachInfo.mViewRootImpl.mChoreographer.removeCallbacks(
16851                     Choreographer.CALLBACK_ANIMATION, null, who);
16852         }
16853     }
16854 
16855     /**
16856      * Resolve the Drawables depending on the layout direction. This is implicitly supposing
16857      * that the View directionality can and will be resolved before its Drawables.
16858      *
16859      * Will call {@link View#onResolveDrawables} when resolution is done.
16860      *
16861      * @hide
16862      */
16863     protected void resolveDrawables() {
16864         // Drawables resolution may need to happen before resolving the layout direction (which is
16865         // done only during the measure() call).
16866         // If the layout direction is not resolved yet, we cannot resolve the Drawables except in
16867         // one case: when the raw layout direction has not been defined as LAYOUT_DIRECTION_INHERIT.
16868         // So, if the raw layout direction is LAYOUT_DIRECTION_LTR or LAYOUT_DIRECTION_RTL or
16869         // LAYOUT_DIRECTION_LOCALE, we can "cheat" and we don't need to wait for the layout
16870         // direction to be resolved as its resolved value will be the same as its raw value.
16871         if (!isLayoutDirectionResolved() &&
16872                 getRawLayoutDirection() == View.LAYOUT_DIRECTION_INHERIT) {
16873             return;
16874         }
16875 
16876         final int layoutDirection = isLayoutDirectionResolved() ?
16877                 getLayoutDirection() : getRawLayoutDirection();
16878 
16879         if (mBackground != null) {
16880             mBackground.setLayoutDirection(layoutDirection);
16881         }
16882         if (mForegroundInfo != null && mForegroundInfo.mDrawable != null) {
16883             mForegroundInfo.mDrawable.setLayoutDirection(layoutDirection);
16884         }
16885         mPrivateFlags2 |= PFLAG2_DRAWABLE_RESOLVED;
16886         onResolveDrawables(layoutDirection);
16887     }
16888 
16889     boolean areDrawablesResolved() {
16890         return (mPrivateFlags2 & PFLAG2_DRAWABLE_RESOLVED) == PFLAG2_DRAWABLE_RESOLVED;
16891     }
16892 
16893     /**
16894      * Called when layout direction has been resolved.
16895      *
16896      * The default implementation does nothing.
16897      *
16898      * @param layoutDirection The resolved layout direction.
16899      *
16900      * @see #LAYOUT_DIRECTION_LTR
16901      * @see #LAYOUT_DIRECTION_RTL
16902      *
16903      * @hide
16904      */
16905     public void onResolveDrawables(@ResolvedLayoutDir int layoutDirection) {
16906     }
16907 
16908     /**
16909      * @hide
16910      */
16911     protected void resetResolvedDrawables() {
16912         resetResolvedDrawablesInternal();
16913     }
16914 
16915     void resetResolvedDrawablesInternal() {
16916         mPrivateFlags2 &= ~PFLAG2_DRAWABLE_RESOLVED;
16917     }
16918 
16919     /**
16920      * If your view subclass is displaying its own Drawable objects, it should
16921      * override this function and return true for any Drawable it is
16922      * displaying.  This allows animations for those drawables to be
16923      * scheduled.
16924      *
16925      * <p>Be sure to call through to the super class when overriding this
16926      * function.
16927      *
16928      * @param who The Drawable to verify.  Return true if it is one you are
16929      *            displaying, else return the result of calling through to the
16930      *            super class.
16931      *
16932      * @return boolean If true than the Drawable is being displayed in the
16933      *         view; else false and it is not allowed to animate.
16934      *
16935      * @see #unscheduleDrawable(android.graphics.drawable.Drawable)
16936      * @see #drawableStateChanged()
16937      */
16938     @CallSuper
16939     protected boolean verifyDrawable(Drawable who) {
16940         return who == mBackground || (mScrollCache != null && mScrollCache.scrollBar == who)
16941                 || (mForegroundInfo != null && mForegroundInfo.mDrawable == who);
16942     }
16943 
16944     /**
16945      * This function is called whenever the state of the view changes in such
16946      * a way that it impacts the state of drawables being shown.
16947      * <p>
16948      * If the View has a StateListAnimator, it will also be called to run necessary state
16949      * change animations.
16950      * <p>
16951      * Be sure to call through to the superclass when overriding this function.
16952      *
16953      * @see Drawable#setState(int[])
16954      */
16955     @CallSuper
16956     protected void drawableStateChanged() {
16957         final int[] state = getDrawableState();
16958 
16959         final Drawable bg = mBackground;
16960         if (bg != null && bg.isStateful()) {
16961             bg.setState(state);
16962         }
16963 
16964         final Drawable fg = mForegroundInfo != null ? mForegroundInfo.mDrawable : null;
16965         if (fg != null && fg.isStateful()) {
16966             fg.setState(state);
16967         }
16968 
16969         if (mScrollCache != null) {
16970             final Drawable scrollBar = mScrollCache.scrollBar;
16971             if (scrollBar != null && scrollBar.isStateful()) {
16972                 scrollBar.setState(state);
16973             }
16974         }
16975 
16976         if (mStateListAnimator != null) {
16977             mStateListAnimator.setState(state);
16978         }
16979     }
16980 
16981     /**
16982      * This function is called whenever the view hotspot changes and needs to
16983      * be propagated to drawables or child views managed by the view.
16984      * <p>
16985      * Dispatching to child views is handled by
16986      * {@link #dispatchDrawableHotspotChanged(float, float)}.
16987      * <p>
16988      * Be sure to call through to the superclass when overriding this function.
16989      *
16990      * @param x hotspot x coordinate
16991      * @param y hotspot y coordinate
16992      */
16993     @CallSuper
16994     public void drawableHotspotChanged(float x, float y) {
16995         if (mBackground != null) {
16996             mBackground.setHotspot(x, y);
16997         }
16998         if (mForegroundInfo != null && mForegroundInfo.mDrawable != null) {
16999             mForegroundInfo.mDrawable.setHotspot(x, y);
17000         }
17001 
17002         dispatchDrawableHotspotChanged(x, y);
17003     }
17004 
17005     /**
17006      * Dispatches drawableHotspotChanged to all of this View's children.
17007      *
17008      * @param x hotspot x coordinate
17009      * @param y hotspot y coordinate
17010      * @see #drawableHotspotChanged(float, float)
17011      */
17012     public void dispatchDrawableHotspotChanged(float x, float y) {
17013     }
17014 
17015     /**
17016      * Call this to force a view to update its drawable state. This will cause
17017      * drawableStateChanged to be called on this view. Views that are interested
17018      * in the new state should call getDrawableState.
17019      *
17020      * @see #drawableStateChanged
17021      * @see #getDrawableState
17022      */
17023     public void refreshDrawableState() {
17024         mPrivateFlags |= PFLAG_DRAWABLE_STATE_DIRTY;
17025         drawableStateChanged();
17026 
17027         ViewParent parent = mParent;
17028         if (parent != null) {
17029             parent.childDrawableStateChanged(this);
17030         }
17031     }
17032 
17033     /**
17034      * Return an array of resource IDs of the drawable states representing the
17035      * current state of the view.
17036      *
17037      * @return The current drawable state
17038      *
17039      * @see Drawable#setState(int[])
17040      * @see #drawableStateChanged()
17041      * @see #onCreateDrawableState(int)
17042      */
17043     public final int[] getDrawableState() {
17044         if ((mDrawableState != null) && ((mPrivateFlags & PFLAG_DRAWABLE_STATE_DIRTY) == 0)) {
17045             return mDrawableState;
17046         } else {
17047             mDrawableState = onCreateDrawableState(0);
17048             mPrivateFlags &= ~PFLAG_DRAWABLE_STATE_DIRTY;
17049             return mDrawableState;
17050         }
17051     }
17052 
17053     /**
17054      * Generate the new {@link android.graphics.drawable.Drawable} state for
17055      * this view. This is called by the view
17056      * system when the cached Drawable state is determined to be invalid.  To
17057      * retrieve the current state, you should use {@link #getDrawableState}.
17058      *
17059      * @param extraSpace if non-zero, this is the number of extra entries you
17060      * would like in the returned array in which you can place your own
17061      * states.
17062      *
17063      * @return Returns an array holding the current {@link Drawable} state of
17064      * the view.
17065      *
17066      * @see #mergeDrawableStates(int[], int[])
17067      */
17068     protected int[] onCreateDrawableState(int extraSpace) {
17069         if ((mViewFlags & DUPLICATE_PARENT_STATE) == DUPLICATE_PARENT_STATE &&
17070                 mParent instanceof View) {
17071             return ((View) mParent).onCreateDrawableState(extraSpace);
17072         }
17073 
17074         int[] drawableState;
17075 
17076         int privateFlags = mPrivateFlags;
17077 
17078         int viewStateIndex = 0;
17079         if ((privateFlags & PFLAG_PRESSED) != 0) viewStateIndex |= StateSet.VIEW_STATE_PRESSED;
17080         if ((mViewFlags & ENABLED_MASK) == ENABLED) viewStateIndex |= StateSet.VIEW_STATE_ENABLED;
17081         if (isFocused()) viewStateIndex |= StateSet.VIEW_STATE_FOCUSED;
17082         if ((privateFlags & PFLAG_SELECTED) != 0) viewStateIndex |= StateSet.VIEW_STATE_SELECTED;
17083         if (hasWindowFocus()) viewStateIndex |= StateSet.VIEW_STATE_WINDOW_FOCUSED;
17084         if ((privateFlags & PFLAG_ACTIVATED) != 0) viewStateIndex |= StateSet.VIEW_STATE_ACTIVATED;
17085         if (mAttachInfo != null && mAttachInfo.mHardwareAccelerationRequested &&
17086                 HardwareRenderer.isAvailable()) {
17087             // This is set if HW acceleration is requested, even if the current
17088             // process doesn't allow it.  This is just to allow app preview
17089             // windows to better match their app.
17090             viewStateIndex |= StateSet.VIEW_STATE_ACCELERATED;
17091         }
17092         if ((privateFlags & PFLAG_HOVERED) != 0) viewStateIndex |= StateSet.VIEW_STATE_HOVERED;
17093 
17094         final int privateFlags2 = mPrivateFlags2;
17095         if ((privateFlags2 & PFLAG2_DRAG_CAN_ACCEPT) != 0) {
17096             viewStateIndex |= StateSet.VIEW_STATE_DRAG_CAN_ACCEPT;
17097         }
17098         if ((privateFlags2 & PFLAG2_DRAG_HOVERED) != 0) {
17099             viewStateIndex |= StateSet.VIEW_STATE_DRAG_HOVERED;
17100         }
17101 
17102         drawableState = StateSet.get(viewStateIndex);
17103 
17104         //noinspection ConstantIfStatement
17105         if (false) {
17106             Log.i("View", "drawableStateIndex=" + viewStateIndex);
17107             Log.i("View", toString()
17108                     + " pressed=" + ((privateFlags & PFLAG_PRESSED) != 0)
17109                     + " en=" + ((mViewFlags & ENABLED_MASK) == ENABLED)
17110                     + " fo=" + hasFocus()
17111                     + " sl=" + ((privateFlags & PFLAG_SELECTED) != 0)
17112                     + " wf=" + hasWindowFocus()
17113                     + ": " + Arrays.toString(drawableState));
17114         }
17115 
17116         if (extraSpace == 0) {
17117             return drawableState;
17118         }
17119 
17120         final int[] fullState;
17121         if (drawableState != null) {
17122             fullState = new int[drawableState.length + extraSpace];
17123             System.arraycopy(drawableState, 0, fullState, 0, drawableState.length);
17124         } else {
17125             fullState = new int[extraSpace];
17126         }
17127 
17128         return fullState;
17129     }
17130 
17131     /**
17132      * Merge your own state values in <var>additionalState</var> into the base
17133      * state values <var>baseState</var> that were returned by
17134      * {@link #onCreateDrawableState(int)}.
17135      *
17136      * @param baseState The base state values returned by
17137      * {@link #onCreateDrawableState(int)}, which will be modified to also hold your
17138      * own additional state values.
17139      *
17140      * @param additionalState The additional state values you would like
17141      * added to <var>baseState</var>; this array is not modified.
17142      *
17143      * @return As a convenience, the <var>baseState</var> array you originally
17144      * passed into the function is returned.
17145      *
17146      * @see #onCreateDrawableState(int)
17147      */
17148     protected static int[] mergeDrawableStates(int[] baseState, int[] additionalState) {
17149         final int N = baseState.length;
17150         int i = N - 1;
17151         while (i >= 0 && baseState[i] == 0) {
17152             i--;
17153         }
17154         System.arraycopy(additionalState, 0, baseState, i + 1, additionalState.length);
17155         return baseState;
17156     }
17157 
17158     /**
17159      * Call {@link Drawable#jumpToCurrentState() Drawable.jumpToCurrentState()}
17160      * on all Drawable objects associated with this view.
17161      * <p>
17162      * Also calls {@link StateListAnimator#jumpToCurrentState()} if there is a StateListAnimator
17163      * attached to this view.
17164      */
17165     @CallSuper
17166     public void jumpDrawablesToCurrentState() {
17167         if (mBackground != null) {
17168             mBackground.jumpToCurrentState();
17169         }
17170         if (mStateListAnimator != null) {
17171             mStateListAnimator.jumpToCurrentState();
17172         }
17173         if (mForegroundInfo != null && mForegroundInfo.mDrawable != null) {
17174             mForegroundInfo.mDrawable.jumpToCurrentState();
17175         }
17176     }
17177 
17178     /**
17179      * Sets the background color for this view.
17180      * @param color the color of the background
17181      */
17182     @RemotableViewMethod
17183     public void setBackgroundColor(@ColorInt int color) {
17184         if (mBackground instanceof ColorDrawable) {
17185             ((ColorDrawable) mBackground.mutate()).setColor(color);
17186             computeOpaqueFlags();
17187             mBackgroundResource = 0;
17188         } else {
17189             setBackground(new ColorDrawable(color));
17190         }
17191     }
17192 
17193     /**
17194      * Set the background to a given resource. The resource should refer to
17195      * a Drawable object or 0 to remove the background.
17196      * @param resid The identifier of the resource.
17197      *
17198      * @attr ref android.R.styleable#View_background
17199      */
17200     @RemotableViewMethod
17201     public void setBackgroundResource(@DrawableRes int resid) {
17202         if (resid != 0 && resid == mBackgroundResource) {
17203             return;
17204         }
17205 
17206         Drawable d = null;
17207         if (resid != 0) {
17208             d = mContext.getDrawable(resid);
17209         }
17210         setBackground(d);
17211 
17212         mBackgroundResource = resid;
17213     }
17214 
17215     /**
17216      * Set the background to a given Drawable, or remove the background. If the
17217      * background has padding, this View's padding is set to the background's
17218      * padding. However, when a background is removed, this View's padding isn't
17219      * touched. If setting the padding is desired, please use
17220      * {@link #setPadding(int, int, int, int)}.
17221      *
17222      * @param background The Drawable to use as the background, or null to remove the
17223      *        background
17224      */
17225     public void setBackground(Drawable background) {
17226         //noinspection deprecation
17227         setBackgroundDrawable(background);
17228     }
17229 
17230     /**
17231      * @deprecated use {@link #setBackground(Drawable)} instead
17232      */
17233     @Deprecated
17234     public void setBackgroundDrawable(Drawable background) {
17235         computeOpaqueFlags();
17236 
17237         if (background == mBackground) {
17238             return;
17239         }
17240 
17241         boolean requestLayout = false;
17242 
17243         mBackgroundResource = 0;
17244 
17245         /*
17246          * Regardless of whether we're setting a new background or not, we want
17247          * to clear the previous drawable.
17248          */
17249         if (mBackground != null) {
17250             mBackground.setCallback(null);
17251             unscheduleDrawable(mBackground);
17252         }
17253 
17254         if (background != null) {
17255             Rect padding = sThreadLocal.get();
17256             if (padding == null) {
17257                 padding = new Rect();
17258                 sThreadLocal.set(padding);
17259             }
17260             resetResolvedDrawablesInternal();
17261             background.setLayoutDirection(getLayoutDirection());
17262             if (background.getPadding(padding)) {
17263                 resetResolvedPaddingInternal();
17264                 switch (background.getLayoutDirection()) {
17265                     case LAYOUT_DIRECTION_RTL:
17266                         mUserPaddingLeftInitial = padding.right;
17267                         mUserPaddingRightInitial = padding.left;
17268                         internalSetPadding(padding.right, padding.top, padding.left, padding.bottom);
17269                         break;
17270                     case LAYOUT_DIRECTION_LTR:
17271                     default:
17272                         mUserPaddingLeftInitial = padding.left;
17273                         mUserPaddingRightInitial = padding.right;
17274                         internalSetPadding(padding.left, padding.top, padding.right, padding.bottom);
17275                 }
17276                 mLeftPaddingDefined = false;
17277                 mRightPaddingDefined = false;
17278             }
17279 
17280             // Compare the minimum sizes of the old Drawable and the new.  If there isn't an old or
17281             // if it has a different minimum size, we should layout again
17282             if (mBackground == null
17283                     || mBackground.getMinimumHeight() != background.getMinimumHeight()
17284                     || mBackground.getMinimumWidth() != background.getMinimumWidth()) {
17285                 requestLayout = true;
17286             }
17287 
17288             background.setCallback(this);
17289             if (background.isStateful()) {
17290                 background.setState(getDrawableState());
17291             }
17292             background.setVisible(getVisibility() == VISIBLE, false);
17293             mBackground = background;
17294 
17295             applyBackgroundTint();
17296 
17297             if ((mPrivateFlags & PFLAG_SKIP_DRAW) != 0) {
17298                 mPrivateFlags &= ~PFLAG_SKIP_DRAW;
17299                 requestLayout = true;
17300             }
17301         } else {
17302             /* Remove the background */
17303             mBackground = null;
17304             if ((mViewFlags & WILL_NOT_DRAW) != 0
17305                     && (mForegroundInfo == null || mForegroundInfo.mDrawable == null)) {
17306                 mPrivateFlags |= PFLAG_SKIP_DRAW;
17307             }
17308 
17309             /*
17310              * When the background is set, we try to apply its padding to this
17311              * View. When the background is removed, we don't touch this View's
17312              * padding. This is noted in the Javadocs. Hence, we don't need to
17313              * requestLayout(), the invalidate() below is sufficient.
17314              */
17315 
17316             // The old background's minimum size could have affected this
17317             // View's layout, so let's requestLayout
17318             requestLayout = true;
17319         }
17320 
17321         computeOpaqueFlags();
17322 
17323         if (requestLayout) {
17324             requestLayout();
17325         }
17326 
17327         mBackgroundSizeChanged = true;
17328         invalidate(true);
17329     }
17330 
17331     /**
17332      * Gets the background drawable
17333      *
17334      * @return The drawable used as the background for this view, if any.
17335      *
17336      * @see #setBackground(Drawable)
17337      *
17338      * @attr ref android.R.styleable#View_background
17339      */
17340     public Drawable getBackground() {
17341         return mBackground;
17342     }
17343 
17344     /**
17345      * Applies a tint to the background drawable. Does not modify the current tint
17346      * mode, which is {@link PorterDuff.Mode#SRC_IN} by default.
17347      * <p>
17348      * Subsequent calls to {@link #setBackground(Drawable)} will automatically
17349      * mutate the drawable and apply the specified tint and tint mode using
17350      * {@link Drawable#setTintList(ColorStateList)}.
17351      *
17352      * @param tint the tint to apply, may be {@code null} to clear tint
17353      *
17354      * @attr ref android.R.styleable#View_backgroundTint
17355      * @see #getBackgroundTintList()
17356      * @see Drawable#setTintList(ColorStateList)
17357      */
17358     public void setBackgroundTintList(@Nullable ColorStateList tint) {
17359         if (mBackgroundTint == null) {
17360             mBackgroundTint = new TintInfo();
17361         }
17362         mBackgroundTint.mTintList = tint;
17363         mBackgroundTint.mHasTintList = true;
17364 
17365         applyBackgroundTint();
17366     }
17367 
17368     /**
17369      * Return the tint applied to the background drawable, if specified.
17370      *
17371      * @return the tint applied to the background drawable
17372      * @attr ref android.R.styleable#View_backgroundTint
17373      * @see #setBackgroundTintList(ColorStateList)
17374      */
17375     @Nullable
17376     public ColorStateList getBackgroundTintList() {
17377         return mBackgroundTint != null ? mBackgroundTint.mTintList : null;
17378     }
17379 
17380     /**
17381      * Specifies the blending mode used to apply the tint specified by
17382      * {@link #setBackgroundTintList(ColorStateList)}} to the background
17383      * drawable. The default mode is {@link PorterDuff.Mode#SRC_IN}.
17384      *
17385      * @param tintMode the blending mode used to apply the tint, may be
17386      *                 {@code null} to clear tint
17387      * @attr ref android.R.styleable#View_backgroundTintMode
17388      * @see #getBackgroundTintMode()
17389      * @see Drawable#setTintMode(PorterDuff.Mode)
17390      */
17391     public void setBackgroundTintMode(@Nullable PorterDuff.Mode tintMode) {
17392         if (mBackgroundTint == null) {
17393             mBackgroundTint = new TintInfo();
17394         }
17395         mBackgroundTint.mTintMode = tintMode;
17396         mBackgroundTint.mHasTintMode = true;
17397 
17398         applyBackgroundTint();
17399     }
17400 
17401     /**
17402      * Return the blending mode used to apply the tint to the background
17403      * drawable, if specified.
17404      *
17405      * @return the blending mode used to apply the tint to the background
17406      *         drawable
17407      * @attr ref android.R.styleable#View_backgroundTintMode
17408      * @see #setBackgroundTintMode(PorterDuff.Mode)
17409      */
17410     @Nullable
17411     public PorterDuff.Mode getBackgroundTintMode() {
17412         return mBackgroundTint != null ? mBackgroundTint.mTintMode : null;
17413     }
17414 
17415     private void applyBackgroundTint() {
17416         if (mBackground != null && mBackgroundTint != null) {
17417             final TintInfo tintInfo = mBackgroundTint;
17418             if (tintInfo.mHasTintList || tintInfo.mHasTintMode) {
17419                 mBackground = mBackground.mutate();
17420 
17421                 if (tintInfo.mHasTintList) {
17422                     mBackground.setTintList(tintInfo.mTintList);
17423                 }
17424 
17425                 if (tintInfo.mHasTintMode) {
17426                     mBackground.setTintMode(tintInfo.mTintMode);
17427                 }
17428 
17429                 // The drawable (or one of its children) may not have been
17430                 // stateful before applying the tint, so let's try again.
17431                 if (mBackground.isStateful()) {
17432                     mBackground.setState(getDrawableState());
17433                 }
17434             }
17435         }
17436     }
17437 
17438     /**
17439      * Returns the drawable used as the foreground of this View. The
17440      * foreground drawable, if non-null, is always drawn on top of the view's content.
17441      *
17442      * @return a Drawable or null if no foreground was set
17443      *
17444      * @see #onDrawForeground(Canvas)
17445      */
17446     public Drawable getForeground() {
17447         return mForegroundInfo != null ? mForegroundInfo.mDrawable : null;
17448     }
17449 
17450     /**
17451      * Supply a Drawable that is to be rendered on top of all of the content in the view.
17452      *
17453      * @param foreground the Drawable to be drawn on top of the children
17454      *
17455      * @attr ref android.R.styleable#View_foreground
17456      */
17457     public void setForeground(Drawable foreground) {
17458         if (mForegroundInfo == null) {
17459             if (foreground == null) {
17460                 // Nothing to do.
17461                 return;
17462             }
17463             mForegroundInfo = new ForegroundInfo();
17464         }
17465 
17466         if (foreground == mForegroundInfo.mDrawable) {
17467             // Nothing to do
17468             return;
17469         }
17470 
17471         if (mForegroundInfo.mDrawable != null) {
17472             mForegroundInfo.mDrawable.setCallback(null);
17473             unscheduleDrawable(mForegroundInfo.mDrawable);
17474         }
17475 
17476         mForegroundInfo.mDrawable = foreground;
17477         mForegroundInfo.mBoundsChanged = true;
17478         if (foreground != null) {
17479             if ((mPrivateFlags & PFLAG_SKIP_DRAW) != 0) {
17480                 mPrivateFlags &= ~PFLAG_SKIP_DRAW;
17481             }
17482             foreground.setCallback(this);
17483             foreground.setLayoutDirection(getLayoutDirection());
17484             if (foreground.isStateful()) {
17485                 foreground.setState(getDrawableState());
17486             }
17487             applyForegroundTint();
17488         } else if ((mViewFlags & WILL_NOT_DRAW) != 0 && mBackground == null) {
17489             mPrivateFlags |= PFLAG_SKIP_DRAW;
17490         }
17491         requestLayout();
17492         invalidate();
17493     }
17494 
17495     /**
17496      * Magic bit used to support features of framework-internal window decor implementation details.
17497      * This used to live exclusively in FrameLayout.
17498      *
17499      * @return true if the foreground should draw inside the padding region or false
17500      *         if it should draw inset by the view's padding
17501      * @hide internal use only; only used by FrameLayout and internal screen layouts.
17502      */
17503     public boolean isForegroundInsidePadding() {
17504         return mForegroundInfo != null ? mForegroundInfo.mInsidePadding : true;
17505     }
17506 
17507     /**
17508      * Describes how the foreground is positioned.
17509      *
17510      * @return foreground gravity.
17511      *
17512      * @see #setForegroundGravity(int)
17513      *
17514      * @attr ref android.R.styleable#View_foregroundGravity
17515      */
17516     public int getForegroundGravity() {
17517         return mForegroundInfo != null ? mForegroundInfo.mGravity
17518                 : Gravity.START | Gravity.TOP;
17519     }
17520 
17521     /**
17522      * Describes how the foreground is positioned. Defaults to START and TOP.
17523      *
17524      * @param gravity see {@link android.view.Gravity}
17525      *
17526      * @see #getForegroundGravity()
17527      *
17528      * @attr ref android.R.styleable#View_foregroundGravity
17529      */
17530     public void setForegroundGravity(int gravity) {
17531         if (mForegroundInfo == null) {
17532             mForegroundInfo = new ForegroundInfo();
17533         }
17534 
17535         if (mForegroundInfo.mGravity != gravity) {
17536             if ((gravity & Gravity.RELATIVE_HORIZONTAL_GRAVITY_MASK) == 0) {
17537                 gravity |= Gravity.START;
17538             }
17539 
17540             if ((gravity & Gravity.VERTICAL_GRAVITY_MASK) == 0) {
17541                 gravity |= Gravity.TOP;
17542             }
17543 
17544             mForegroundInfo.mGravity = gravity;
17545             requestLayout();
17546         }
17547     }
17548 
17549     /**
17550      * Applies a tint to the foreground drawable. Does not modify the current tint
17551      * mode, which is {@link PorterDuff.Mode#SRC_IN} by default.
17552      * <p>
17553      * Subsequent calls to {@link #setForeground(Drawable)} will automatically
17554      * mutate the drawable and apply the specified tint and tint mode using
17555      * {@link Drawable#setTintList(ColorStateList)}.
17556      *
17557      * @param tint the tint to apply, may be {@code null} to clear tint
17558      *
17559      * @attr ref android.R.styleable#View_foregroundTint
17560      * @see #getForegroundTintList()
17561      * @see Drawable#setTintList(ColorStateList)
17562      */
17563     public void setForegroundTintList(@Nullable ColorStateList tint) {
17564         if (mForegroundInfo == null) {
17565             mForegroundInfo = new ForegroundInfo();
17566         }
17567         if (mForegroundInfo.mTintInfo == null) {
17568             mForegroundInfo.mTintInfo = new TintInfo();
17569         }
17570         mForegroundInfo.mTintInfo.mTintList = tint;
17571         mForegroundInfo.mTintInfo.mHasTintList = true;
17572 
17573         applyForegroundTint();
17574     }
17575 
17576     /**
17577      * Return the tint applied to the foreground drawable, if specified.
17578      *
17579      * @return the tint applied to the foreground drawable
17580      * @attr ref android.R.styleable#View_foregroundTint
17581      * @see #setForegroundTintList(ColorStateList)
17582      */
17583     @Nullable
17584     public ColorStateList getForegroundTintList() {
17585         return mForegroundInfo != null && mForegroundInfo.mTintInfo != null
17586                 ? mForegroundInfo.mTintInfo.mTintList : null;
17587     }
17588 
17589     /**
17590      * Specifies the blending mode used to apply the tint specified by
17591      * {@link #setForegroundTintList(ColorStateList)}} to the background
17592      * drawable. The default mode is {@link PorterDuff.Mode#SRC_IN}.
17593      *
17594      * @param tintMode the blending mode used to apply the tint, may be
17595      *                 {@code null} to clear tint
17596      * @attr ref android.R.styleable#View_foregroundTintMode
17597      * @see #getForegroundTintMode()
17598      * @see Drawable#setTintMode(PorterDuff.Mode)
17599      */
17600     public void setForegroundTintMode(@Nullable PorterDuff.Mode tintMode) {
17601         if (mForegroundInfo == null) {
17602             mForegroundInfo = new ForegroundInfo();
17603         }
17604         if (mForegroundInfo.mTintInfo == null) {
17605             mForegroundInfo.mTintInfo = new TintInfo();
17606         }
17607         mForegroundInfo.mTintInfo.mTintMode = tintMode;
17608         mForegroundInfo.mTintInfo.mHasTintMode = true;
17609 
17610         applyForegroundTint();
17611     }
17612 
17613     /**
17614      * Return the blending mode used to apply the tint to the foreground
17615      * drawable, if specified.
17616      *
17617      * @return the blending mode used to apply the tint to the foreground
17618      *         drawable
17619      * @attr ref android.R.styleable#View_foregroundTintMode
17620      * @see #setForegroundTintMode(PorterDuff.Mode)
17621      */
17622     @Nullable
17623     public PorterDuff.Mode getForegroundTintMode() {
17624         return mForegroundInfo != null && mForegroundInfo.mTintInfo != null
17625                 ? mForegroundInfo.mTintInfo.mTintMode : null;
17626     }
17627 
17628     private void applyForegroundTint() {
17629         if (mForegroundInfo != null && mForegroundInfo.mDrawable != null
17630                 && mForegroundInfo.mTintInfo != null) {
17631             final TintInfo tintInfo = mForegroundInfo.mTintInfo;
17632             if (tintInfo.mHasTintList || tintInfo.mHasTintMode) {
17633                 mForegroundInfo.mDrawable = mForegroundInfo.mDrawable.mutate();
17634 
17635                 if (tintInfo.mHasTintList) {
17636                     mForegroundInfo.mDrawable.setTintList(tintInfo.mTintList);
17637                 }
17638 
17639                 if (tintInfo.mHasTintMode) {
17640                     mForegroundInfo.mDrawable.setTintMode(tintInfo.mTintMode);
17641                 }
17642 
17643                 // The drawable (or one of its children) may not have been
17644                 // stateful before applying the tint, so let's try again.
17645                 if (mForegroundInfo.mDrawable.isStateful()) {
17646                     mForegroundInfo.mDrawable.setState(getDrawableState());
17647                 }
17648             }
17649         }
17650     }
17651 
17652     /**
17653      * Draw any foreground content for this view.
17654      *
17655      * <p>Foreground content may consist of scroll bars, a {@link #setForeground foreground}
17656      * drawable or other view-specific decorations. The foreground is drawn on top of the
17657      * primary view content.</p>
17658      *
17659      * @param canvas canvas to draw into
17660      */
17661     public void onDrawForeground(Canvas canvas) {
17662         onDrawScrollIndicators(canvas);
17663         onDrawScrollBars(canvas);
17664 
17665         final Drawable foreground = mForegroundInfo != null ? mForegroundInfo.mDrawable : null;
17666         if (foreground != null) {
17667             if (mForegroundInfo.mBoundsChanged) {
17668                 mForegroundInfo.mBoundsChanged = false;
17669                 final Rect selfBounds = mForegroundInfo.mSelfBounds;
17670                 final Rect overlayBounds = mForegroundInfo.mOverlayBounds;
17671 
17672                 if (mForegroundInfo.mInsidePadding) {
17673                     selfBounds.set(0, 0, getWidth(), getHeight());
17674                 } else {
17675                     selfBounds.set(getPaddingLeft(), getPaddingTop(),
17676                             getWidth() - getPaddingRight(), getHeight() - getPaddingBottom());
17677                 }
17678 
17679                 final int ld = getLayoutDirection();
17680                 Gravity.apply(mForegroundInfo.mGravity, foreground.getIntrinsicWidth(),
17681                         foreground.getIntrinsicHeight(), selfBounds, overlayBounds, ld);
17682                 foreground.setBounds(overlayBounds);
17683             }
17684 
17685             foreground.draw(canvas);
17686         }
17687     }
17688 
17689     /**
17690      * Sets the padding. The view may add on the space required to display
17691      * the scrollbars, depending on the style and visibility of the scrollbars.
17692      * So the values returned from {@link #getPaddingLeft}, {@link #getPaddingTop},
17693      * {@link #getPaddingRight} and {@link #getPaddingBottom} may be different
17694      * from the values set in this call.
17695      *
17696      * @attr ref android.R.styleable#View_padding
17697      * @attr ref android.R.styleable#View_paddingBottom
17698      * @attr ref android.R.styleable#View_paddingLeft
17699      * @attr ref android.R.styleable#View_paddingRight
17700      * @attr ref android.R.styleable#View_paddingTop
17701      * @param left the left padding in pixels
17702      * @param top the top padding in pixels
17703      * @param right the right padding in pixels
17704      * @param bottom the bottom padding in pixels
17705      */
17706     public void setPadding(int left, int top, int right, int bottom) {
17707         resetResolvedPaddingInternal();
17708 
17709         mUserPaddingStart = UNDEFINED_PADDING;
17710         mUserPaddingEnd = UNDEFINED_PADDING;
17711 
17712         mUserPaddingLeftInitial = left;
17713         mUserPaddingRightInitial = right;
17714 
17715         mLeftPaddingDefined = true;
17716         mRightPaddingDefined = true;
17717 
17718         internalSetPadding(left, top, right, bottom);
17719     }
17720 
17721     /**
17722      * @hide
17723      */
17724     protected void internalSetPadding(int left, int top, int right, int bottom) {
17725         mUserPaddingLeft = left;
17726         mUserPaddingRight = right;
17727         mUserPaddingBottom = bottom;
17728 
17729         final int viewFlags = mViewFlags;
17730         boolean changed = false;
17731 
17732         // Common case is there are no scroll bars.
17733         if ((viewFlags & (SCROLLBARS_VERTICAL|SCROLLBARS_HORIZONTAL)) != 0) {
17734             if ((viewFlags & SCROLLBARS_VERTICAL) != 0) {
17735                 final int offset = (viewFlags & SCROLLBARS_INSET_MASK) == 0
17736                         ? 0 : getVerticalScrollbarWidth();
17737                 switch (mVerticalScrollbarPosition) {
17738                     case SCROLLBAR_POSITION_DEFAULT:
17739                         if (isLayoutRtl()) {
17740                             left += offset;
17741                         } else {
17742                             right += offset;
17743                         }
17744                         break;
17745                     case SCROLLBAR_POSITION_RIGHT:
17746                         right += offset;
17747                         break;
17748                     case SCROLLBAR_POSITION_LEFT:
17749                         left += offset;
17750                         break;
17751                 }
17752             }
17753             if ((viewFlags & SCROLLBARS_HORIZONTAL) != 0) {
17754                 bottom += (viewFlags & SCROLLBARS_INSET_MASK) == 0
17755                         ? 0 : getHorizontalScrollbarHeight();
17756             }
17757         }
17758 
17759         if (mPaddingLeft != left) {
17760             changed = true;
17761             mPaddingLeft = left;
17762         }
17763         if (mPaddingTop != top) {
17764             changed = true;
17765             mPaddingTop = top;
17766         }
17767         if (mPaddingRight != right) {
17768             changed = true;
17769             mPaddingRight = right;
17770         }
17771         if (mPaddingBottom != bottom) {
17772             changed = true;
17773             mPaddingBottom = bottom;
17774         }
17775 
17776         if (changed) {
17777             requestLayout();
17778             invalidateOutline();
17779         }
17780     }
17781 
17782     /**
17783      * Sets the relative padding. The view may add on the space required to display
17784      * the scrollbars, depending on the style and visibility of the scrollbars.
17785      * So the values returned from {@link #getPaddingStart}, {@link #getPaddingTop},
17786      * {@link #getPaddingEnd} and {@link #getPaddingBottom} may be different
17787      * from the values set in this call.
17788      *
17789      * @attr ref android.R.styleable#View_padding
17790      * @attr ref android.R.styleable#View_paddingBottom
17791      * @attr ref android.R.styleable#View_paddingStart
17792      * @attr ref android.R.styleable#View_paddingEnd
17793      * @attr ref android.R.styleable#View_paddingTop
17794      * @param start the start padding in pixels
17795      * @param top the top padding in pixels
17796      * @param end the end padding in pixels
17797      * @param bottom the bottom padding in pixels
17798      */
17799     public void setPaddingRelative(int start, int top, int end, int bottom) {
17800         resetResolvedPaddingInternal();
17801 
17802         mUserPaddingStart = start;
17803         mUserPaddingEnd = end;
17804         mLeftPaddingDefined = true;
17805         mRightPaddingDefined = true;
17806 
17807         switch(getLayoutDirection()) {
17808             case LAYOUT_DIRECTION_RTL:
17809                 mUserPaddingLeftInitial = end;
17810                 mUserPaddingRightInitial = start;
17811                 internalSetPadding(end, top, start, bottom);
17812                 break;
17813             case LAYOUT_DIRECTION_LTR:
17814             default:
17815                 mUserPaddingLeftInitial = start;
17816                 mUserPaddingRightInitial = end;
17817                 internalSetPadding(start, top, end, bottom);
17818         }
17819     }
17820 
17821     /**
17822      * Returns the top padding of this view.
17823      *
17824      * @return the top padding in pixels
17825      */
17826     public int getPaddingTop() {
17827         return mPaddingTop;
17828     }
17829 
17830     /**
17831      * Returns the bottom padding of this view. If there are inset and enabled
17832      * scrollbars, this value may include the space required to display the
17833      * scrollbars as well.
17834      *
17835      * @return the bottom padding in pixels
17836      */
17837     public int getPaddingBottom() {
17838         return mPaddingBottom;
17839     }
17840 
17841     /**
17842      * Returns the left padding of this view. If there are inset and enabled
17843      * scrollbars, this value may include the space required to display the
17844      * scrollbars as well.
17845      *
17846      * @return the left padding in pixels
17847      */
17848     public int getPaddingLeft() {
17849         if (!isPaddingResolved()) {
17850             resolvePadding();
17851         }
17852         return mPaddingLeft;
17853     }
17854 
17855     /**
17856      * Returns the start padding of this view depending on its resolved layout direction.
17857      * If there are inset and enabled scrollbars, this value may include the space
17858      * required to display the scrollbars as well.
17859      *
17860      * @return the start padding in pixels
17861      */
17862     public int getPaddingStart() {
17863         if (!isPaddingResolved()) {
17864             resolvePadding();
17865         }
17866         return (getLayoutDirection() == LAYOUT_DIRECTION_RTL) ?
17867                 mPaddingRight : mPaddingLeft;
17868     }
17869 
17870     /**
17871      * Returns the right padding of this view. If there are inset and enabled
17872      * scrollbars, this value may include the space required to display the
17873      * scrollbars as well.
17874      *
17875      * @return the right padding in pixels
17876      */
17877     public int getPaddingRight() {
17878         if (!isPaddingResolved()) {
17879             resolvePadding();
17880         }
17881         return mPaddingRight;
17882     }
17883 
17884     /**
17885      * Returns the end padding of this view depending on its resolved layout direction.
17886      * If there are inset and enabled scrollbars, this value may include the space
17887      * required to display the scrollbars as well.
17888      *
17889      * @return the end padding in pixels
17890      */
17891     public int getPaddingEnd() {
17892         if (!isPaddingResolved()) {
17893             resolvePadding();
17894         }
17895         return (getLayoutDirection() == LAYOUT_DIRECTION_RTL) ?
17896                 mPaddingLeft : mPaddingRight;
17897     }
17898 
17899     /**
17900      * Return if the padding has been set through relative values
17901      * {@link #setPaddingRelative(int, int, int, int)} or through
17902      * @attr ref android.R.styleable#View_paddingStart or
17903      * @attr ref android.R.styleable#View_paddingEnd
17904      *
17905      * @return true if the padding is relative or false if it is not.
17906      */
17907     public boolean isPaddingRelative() {
17908         return (mUserPaddingStart != UNDEFINED_PADDING || mUserPaddingEnd != UNDEFINED_PADDING);
17909     }
17910 
17911     Insets computeOpticalInsets() {
17912         return (mBackground == null) ? Insets.NONE : mBackground.getOpticalInsets();
17913     }
17914 
17915     /**
17916      * @hide
17917      */
17918     public void resetPaddingToInitialValues() {
17919         if (isRtlCompatibilityMode()) {
17920             mPaddingLeft = mUserPaddingLeftInitial;
17921             mPaddingRight = mUserPaddingRightInitial;
17922             return;
17923         }
17924         if (isLayoutRtl()) {
17925             mPaddingLeft = (mUserPaddingEnd >= 0) ? mUserPaddingEnd : mUserPaddingLeftInitial;
17926             mPaddingRight = (mUserPaddingStart >= 0) ? mUserPaddingStart : mUserPaddingRightInitial;
17927         } else {
17928             mPaddingLeft = (mUserPaddingStart >= 0) ? mUserPaddingStart : mUserPaddingLeftInitial;
17929             mPaddingRight = (mUserPaddingEnd >= 0) ? mUserPaddingEnd : mUserPaddingRightInitial;
17930         }
17931     }
17932 
17933     /**
17934      * @hide
17935      */
17936     public Insets getOpticalInsets() {
17937         if (mLayoutInsets == null) {
17938             mLayoutInsets = computeOpticalInsets();
17939         }
17940         return mLayoutInsets;
17941     }
17942 
17943     /**
17944      * Set this view's optical insets.
17945      *
17946      * <p>This method should be treated similarly to setMeasuredDimension and not as a general
17947      * property. Views that compute their own optical insets should call it as part of measurement.
17948      * This method does not request layout. If you are setting optical insets outside of
17949      * measure/layout itself you will want to call requestLayout() yourself.
17950      * </p>
17951      * @hide
17952      */
17953     public void setOpticalInsets(Insets insets) {
17954         mLayoutInsets = insets;
17955     }
17956 
17957     /**
17958      * Changes the selection state of this view. A view can be selected or not.
17959      * Note that selection is not the same as focus. Views are typically
17960      * selected in the context of an AdapterView like ListView or GridView;
17961      * the selected view is the view that is highlighted.
17962      *
17963      * @param selected true if the view must be selected, false otherwise
17964      */
17965     public void setSelected(boolean selected) {
17966         //noinspection DoubleNegation
17967         if (((mPrivateFlags & PFLAG_SELECTED) != 0) != selected) {
17968             mPrivateFlags = (mPrivateFlags & ~PFLAG_SELECTED) | (selected ? PFLAG_SELECTED : 0);
17969             if (!selected) resetPressedState();
17970             invalidate(true);
17971             refreshDrawableState();
17972             dispatchSetSelected(selected);
17973             if (selected) {
17974                 sendAccessibilityEvent(AccessibilityEvent.TYPE_VIEW_SELECTED);
17975             } else {
17976                 notifyViewAccessibilityStateChangedIfNeeded(
17977                         AccessibilityEvent.CONTENT_CHANGE_TYPE_UNDEFINED);
17978             }
17979         }
17980     }
17981 
17982     /**
17983      * Dispatch setSelected to all of this View's children.
17984      *
17985      * @see #setSelected(boolean)
17986      *
17987      * @param selected The new selected state
17988      */
17989     protected void dispatchSetSelected(boolean selected) {
17990     }
17991 
17992     /**
17993      * Indicates the selection state of this view.
17994      *
17995      * @return true if the view is selected, false otherwise
17996      */
17997     @ViewDebug.ExportedProperty
17998     public boolean isSelected() {
17999         return (mPrivateFlags & PFLAG_SELECTED) != 0;
18000     }
18001 
18002     /**
18003      * Changes the activated state of this view. A view can be activated or not.
18004      * Note that activation is not the same as selection.  Selection is
18005      * a transient property, representing the view (hierarchy) the user is
18006      * currently interacting with.  Activation is a longer-term state that the
18007      * user can move views in and out of.  For example, in a list view with
18008      * single or multiple selection enabled, the views in the current selection
18009      * set are activated.  (Um, yeah, we are deeply sorry about the terminology
18010      * here.)  The activated state is propagated down to children of the view it
18011      * is set on.
18012      *
18013      * @param activated true if the view must be activated, false otherwise
18014      */
18015     public void setActivated(boolean activated) {
18016         //noinspection DoubleNegation
18017         if (((mPrivateFlags & PFLAG_ACTIVATED) != 0) != activated) {
18018             mPrivateFlags = (mPrivateFlags & ~PFLAG_ACTIVATED) | (activated ? PFLAG_ACTIVATED : 0);
18019             invalidate(true);
18020             refreshDrawableState();
18021             dispatchSetActivated(activated);
18022         }
18023     }
18024 
18025     /**
18026      * Dispatch setActivated to all of this View's children.
18027      *
18028      * @see #setActivated(boolean)
18029      *
18030      * @param activated The new activated state
18031      */
18032     protected void dispatchSetActivated(boolean activated) {
18033     }
18034 
18035     /**
18036      * Indicates the activation state of this view.
18037      *
18038      * @return true if the view is activated, false otherwise
18039      */
18040     @ViewDebug.ExportedProperty
18041     public boolean isActivated() {
18042         return (mPrivateFlags & PFLAG_ACTIVATED) != 0;
18043     }
18044 
18045     /**
18046      * Returns the ViewTreeObserver for this view's hierarchy. The view tree
18047      * observer can be used to get notifications when global events, like
18048      * layout, happen.
18049      *
18050      * The returned ViewTreeObserver observer is not guaranteed to remain
18051      * valid for the lifetime of this View. If the caller of this method keeps
18052      * a long-lived reference to ViewTreeObserver, it should always check for
18053      * the return value of {@link ViewTreeObserver#isAlive()}.
18054      *
18055      * @return The ViewTreeObserver for this view's hierarchy.
18056      */
18057     public ViewTreeObserver getViewTreeObserver() {
18058         if (mAttachInfo != null) {
18059             return mAttachInfo.mTreeObserver;
18060         }
18061         if (mFloatingTreeObserver == null) {
18062             mFloatingTreeObserver = new ViewTreeObserver();
18063         }
18064         return mFloatingTreeObserver;
18065     }
18066 
18067     /**
18068      * <p>Finds the topmost view in the current view hierarchy.</p>
18069      *
18070      * @return the topmost view containing this view
18071      */
18072     public View getRootView() {
18073         if (mAttachInfo != null) {
18074             final View v = mAttachInfo.mRootView;
18075             if (v != null) {
18076                 return v;
18077             }
18078         }
18079 
18080         View parent = this;
18081 
18082         while (parent.mParent != null && parent.mParent instanceof View) {
18083             parent = (View) parent.mParent;
18084         }
18085 
18086         return parent;
18087     }
18088 
18089     /**
18090      * Transforms a motion event from view-local coordinates to on-screen
18091      * coordinates.
18092      *
18093      * @param ev the view-local motion event
18094      * @return false if the transformation could not be applied
18095      * @hide
18096      */
18097     public boolean toGlobalMotionEvent(MotionEvent ev) {
18098         final AttachInfo info = mAttachInfo;
18099         if (info == null) {
18100             return false;
18101         }
18102 
18103         final Matrix m = info.mTmpMatrix;
18104         m.set(Matrix.IDENTITY_MATRIX);
18105         transformMatrixToGlobal(m);
18106         ev.transform(m);
18107         return true;
18108     }
18109 
18110     /**
18111      * Transforms a motion event from on-screen coordinates to view-local
18112      * coordinates.
18113      *
18114      * @param ev the on-screen motion event
18115      * @return false if the transformation could not be applied
18116      * @hide
18117      */
18118     public boolean toLocalMotionEvent(MotionEvent ev) {
18119         final AttachInfo info = mAttachInfo;
18120         if (info == null) {
18121             return false;
18122         }
18123 
18124         final Matrix m = info.mTmpMatrix;
18125         m.set(Matrix.IDENTITY_MATRIX);
18126         transformMatrixToLocal(m);
18127         ev.transform(m);
18128         return true;
18129     }
18130 
18131     /**
18132      * Modifies the input matrix such that it maps view-local coordinates to
18133      * on-screen coordinates.
18134      *
18135      * @param m input matrix to modify
18136      * @hide
18137      */
18138     public void transformMatrixToGlobal(Matrix m) {
18139         final ViewParent parent = mParent;
18140         if (parent instanceof View) {
18141             final View vp = (View) parent;
18142             vp.transformMatrixToGlobal(m);
18143             m.preTranslate(-vp.mScrollX, -vp.mScrollY);
18144         } else if (parent instanceof ViewRootImpl) {
18145             final ViewRootImpl vr = (ViewRootImpl) parent;
18146             vr.transformMatrixToGlobal(m);
18147             m.preTranslate(0, -vr.mCurScrollY);
18148         }
18149 
18150         m.preTranslate(mLeft, mTop);
18151 
18152         if (!hasIdentityMatrix()) {
18153             m.preConcat(getMatrix());
18154         }
18155     }
18156 
18157     /**
18158      * Modifies the input matrix such that it maps on-screen coordinates to
18159      * view-local coordinates.
18160      *
18161      * @param m input matrix to modify
18162      * @hide
18163      */
18164     public void transformMatrixToLocal(Matrix m) {
18165         final ViewParent parent = mParent;
18166         if (parent instanceof View) {
18167             final View vp = (View) parent;
18168             vp.transformMatrixToLocal(m);
18169             m.postTranslate(vp.mScrollX, vp.mScrollY);
18170         } else if (parent instanceof ViewRootImpl) {
18171             final ViewRootImpl vr = (ViewRootImpl) parent;
18172             vr.transformMatrixToLocal(m);
18173             m.postTranslate(0, vr.mCurScrollY);
18174         }
18175 
18176         m.postTranslate(-mLeft, -mTop);
18177 
18178         if (!hasIdentityMatrix()) {
18179             m.postConcat(getInverseMatrix());
18180         }
18181     }
18182 
18183     /**
18184      * @hide
18185      */
18186     @ViewDebug.ExportedProperty(category = "layout", indexMapping = {
18187             @ViewDebug.IntToString(from = 0, to = "x"),
18188             @ViewDebug.IntToString(from = 1, to = "y")
18189     })
18190     public int[] getLocationOnScreen() {
18191         int[] location = new int[2];
18192         getLocationOnScreen(location);
18193         return location;
18194     }
18195 
18196     /**
18197      * <p>Computes the coordinates of this view on the screen. The argument
18198      * must be an array of two integers. After the method returns, the array
18199      * contains the x and y location in that order.</p>
18200      *
18201      * @param location an array of two integers in which to hold the coordinates
18202      */
18203     public void getLocationOnScreen(@Size(2) int[] location) {
18204         getLocationInWindow(location);
18205 
18206         final AttachInfo info = mAttachInfo;
18207         if (info != null) {
18208             location[0] += info.mWindowLeft;
18209             location[1] += info.mWindowTop;
18210         }
18211     }
18212 
18213     /**
18214      * <p>Computes the coordinates of this view in its window. The argument
18215      * must be an array of two integers. After the method returns, the array
18216      * contains the x and y location in that order.</p>
18217      *
18218      * @param location an array of two integers in which to hold the coordinates
18219      */
18220     public void getLocationInWindow(@Size(2) int[] location) {
18221         if (location == null || location.length < 2) {
18222             throw new IllegalArgumentException("location must be an array of two integers");
18223         }
18224 
18225         if (mAttachInfo == null) {
18226             // When the view is not attached to a window, this method does not make sense
18227             location[0] = location[1] = 0;
18228             return;
18229         }
18230 
18231         float[] position = mAttachInfo.mTmpTransformLocation;
18232         position[0] = position[1] = 0.0f;
18233 
18234         if (!hasIdentityMatrix()) {
18235             getMatrix().mapPoints(position);
18236         }
18237 
18238         position[0] += mLeft;
18239         position[1] += mTop;
18240 
18241         ViewParent viewParent = mParent;
18242         while (viewParent instanceof View) {
18243             final View view = (View) viewParent;
18244 
18245             position[0] -= view.mScrollX;
18246             position[1] -= view.mScrollY;
18247 
18248             if (!view.hasIdentityMatrix()) {
18249                 view.getMatrix().mapPoints(position);
18250             }
18251 
18252             position[0] += view.mLeft;
18253             position[1] += view.mTop;
18254 
18255             viewParent = view.mParent;
18256          }
18257 
18258         if (viewParent instanceof ViewRootImpl) {
18259             // *cough*
18260             final ViewRootImpl vr = (ViewRootImpl) viewParent;
18261             position[1] -= vr.mCurScrollY;
18262         }
18263 
18264         location[0] = (int) (position[0] + 0.5f);
18265         location[1] = (int) (position[1] + 0.5f);
18266     }
18267 
18268     /**
18269      * {@hide}
18270      * @param id the id of the view to be found
18271      * @return the view of the specified id, null if cannot be found
18272      */
18273     protected View findViewTraversal(@IdRes int id) {
18274         if (id == mID) {
18275             return this;
18276         }
18277         return null;
18278     }
18279 
18280     /**
18281      * {@hide}
18282      * @param tag the tag of the view to be found
18283      * @return the view of specified tag, null if cannot be found
18284      */
18285     protected View findViewWithTagTraversal(Object tag) {
18286         if (tag != null && tag.equals(mTag)) {
18287             return this;
18288         }
18289         return null;
18290     }
18291 
18292     /**
18293      * {@hide}
18294      * @param predicate The predicate to evaluate.
18295      * @param childToSkip If not null, ignores this child during the recursive traversal.
18296      * @return The first view that matches the predicate or null.
18297      */
18298     protected View findViewByPredicateTraversal(Predicate<View> predicate, View childToSkip) {
18299         if (predicate.apply(this)) {
18300             return this;
18301         }
18302         return null;
18303     }
18304 
18305     /**
18306      * Look for a child view with the given id.  If this view has the given
18307      * id, return this view.
18308      *
18309      * @param id The id to search for.
18310      * @return The view that has the given id in the hierarchy or null
18311      */
18312     @Nullable
18313     public final View findViewById(@IdRes int id) {
18314         if (id < 0) {
18315             return null;
18316         }
18317         return findViewTraversal(id);
18318     }
18319 
18320     /**
18321      * Finds a view by its unuque and stable accessibility id.
18322      *
18323      * @param accessibilityId The searched accessibility id.
18324      * @return The found view.
18325      */
18326     final View findViewByAccessibilityId(int accessibilityId) {
18327         if (accessibilityId < 0) {
18328             return null;
18329         }
18330         View view = findViewByAccessibilityIdTraversal(accessibilityId);
18331         if (view != null) {
18332             return view.includeForAccessibility() ? view : null;
18333         }
18334         return null;
18335     }
18336 
18337     /**
18338      * Performs the traversal to find a view by its unuque and stable accessibility id.
18339      *
18340      * <strong>Note:</strong>This method does not stop at the root namespace
18341      * boundary since the user can touch the screen at an arbitrary location
18342      * potentially crossing the root namespace bounday which will send an
18343      * accessibility event to accessibility services and they should be able
18344      * to obtain the event source. Also accessibility ids are guaranteed to be
18345      * unique in the window.
18346      *
18347      * @param accessibilityId The accessibility id.
18348      * @return The found view.
18349      *
18350      * @hide
18351      */
18352     public View findViewByAccessibilityIdTraversal(int accessibilityId) {
18353         if (getAccessibilityViewId() == accessibilityId) {
18354             return this;
18355         }
18356         return null;
18357     }
18358 
18359     /**
18360      * Look for a child view with the given tag.  If this view has the given
18361      * tag, return this view.
18362      *
18363      * @param tag The tag to search for, using "tag.equals(getTag())".
18364      * @return The View that has the given tag in the hierarchy or null
18365      */
18366     public final View findViewWithTag(Object tag) {
18367         if (tag == null) {
18368             return null;
18369         }
18370         return findViewWithTagTraversal(tag);
18371     }
18372 
18373     /**
18374      * {@hide}
18375      * Look for a child view that matches the specified predicate.
18376      * If this view matches the predicate, return this view.
18377      *
18378      * @param predicate The predicate to evaluate.
18379      * @return The first view that matches the predicate or null.
18380      */
18381     public final View findViewByPredicate(Predicate<View> predicate) {
18382         return findViewByPredicateTraversal(predicate, null);
18383     }
18384 
18385     /**
18386      * {@hide}
18387      * Look for a child view that matches the specified predicate,
18388      * starting with the specified view and its descendents and then
18389      * recusively searching the ancestors and siblings of that view
18390      * until this view is reached.
18391      *
18392      * This method is useful in cases where the predicate does not match
18393      * a single unique view (perhaps multiple views use the same id)
18394      * and we are trying to find the view that is "closest" in scope to the
18395      * starting view.
18396      *
18397      * @param start The view to start from.
18398      * @param predicate The predicate to evaluate.
18399      * @return The first view that matches the predicate or null.
18400      */
18401     public final View findViewByPredicateInsideOut(View start, Predicate<View> predicate) {
18402         View childToSkip = null;
18403         for (;;) {
18404             View view = start.findViewByPredicateTraversal(predicate, childToSkip);
18405             if (view != null || start == this) {
18406                 return view;
18407             }
18408 
18409             ViewParent parent = start.getParent();
18410             if (parent == null || !(parent instanceof View)) {
18411                 return null;
18412             }
18413 
18414             childToSkip = start;
18415             start = (View) parent;
18416         }
18417     }
18418 
18419     /**
18420      * Sets the identifier for this view. The identifier does not have to be
18421      * unique in this view's hierarchy. The identifier should be a positive
18422      * number.
18423      *
18424      * @see #NO_ID
18425      * @see #getId()
18426      * @see #findViewById(int)
18427      *
18428      * @param id a number used to identify the view
18429      *
18430      * @attr ref android.R.styleable#View_id
18431      */
18432     public void setId(@IdRes int id) {
18433         mID = id;
18434         if (mID == View.NO_ID && mLabelForId != View.NO_ID) {
18435             mID = generateViewId();
18436         }
18437     }
18438 
18439     /**
18440      * {@hide}
18441      *
18442      * @param isRoot true if the view belongs to the root namespace, false
18443      *        otherwise
18444      */
18445     public void setIsRootNamespace(boolean isRoot) {
18446         if (isRoot) {
18447             mPrivateFlags |= PFLAG_IS_ROOT_NAMESPACE;
18448         } else {
18449             mPrivateFlags &= ~PFLAG_IS_ROOT_NAMESPACE;
18450         }
18451     }
18452 
18453     /**
18454      * {@hide}
18455      *
18456      * @return true if the view belongs to the root namespace, false otherwise
18457      */
18458     public boolean isRootNamespace() {
18459         return (mPrivateFlags&PFLAG_IS_ROOT_NAMESPACE) != 0;
18460     }
18461 
18462     /**
18463      * Returns this view's identifier.
18464      *
18465      * @return a positive integer used to identify the view or {@link #NO_ID}
18466      *         if the view has no ID
18467      *
18468      * @see #setId(int)
18469      * @see #findViewById(int)
18470      * @attr ref android.R.styleable#View_id
18471      */
18472     @IdRes
18473     @ViewDebug.CapturedViewProperty
18474     public int getId() {
18475         return mID;
18476     }
18477 
18478     /**
18479      * Returns this view's tag.
18480      *
18481      * @return the Object stored in this view as a tag, or {@code null} if not
18482      *         set
18483      *
18484      * @see #setTag(Object)
18485      * @see #getTag(int)
18486      */
18487     @ViewDebug.ExportedProperty
18488     public Object getTag() {
18489         return mTag;
18490     }
18491 
18492     /**
18493      * Sets the tag associated with this view. A tag can be used to mark
18494      * a view in its hierarchy and does not have to be unique within the
18495      * hierarchy. Tags can also be used to store data within a view without
18496      * resorting to another data structure.
18497      *
18498      * @param tag an Object to tag the view with
18499      *
18500      * @see #getTag()
18501      * @see #setTag(int, Object)
18502      */
18503     public void setTag(final Object tag) {
18504         mTag = tag;
18505     }
18506 
18507     /**
18508      * Returns the tag associated with this view and the specified key.
18509      *
18510      * @param key The key identifying the tag
18511      *
18512      * @return the Object stored in this view as a tag, or {@code null} if not
18513      *         set
18514      *
18515      * @see #setTag(int, Object)
18516      * @see #getTag()
18517      */
18518     public Object getTag(int key) {
18519         if (mKeyedTags != null) return mKeyedTags.get(key);
18520         return null;
18521     }
18522 
18523     /**
18524      * Sets a tag associated with this view and a key. A tag can be used
18525      * to mark a view in its hierarchy and does not have to be unique within
18526      * the hierarchy. Tags can also be used to store data within a view
18527      * without resorting to another data structure.
18528      *
18529      * The specified key should be an id declared in the resources of the
18530      * application to ensure it is unique (see the <a
18531      * href="{@docRoot}guide/topics/resources/more-resources.html#Id">ID resource type</a>).
18532      * Keys identified as belonging to
18533      * the Android framework or not associated with any package will cause
18534      * an {@link IllegalArgumentException} to be thrown.
18535      *
18536      * @param key The key identifying the tag
18537      * @param tag An Object to tag the view with
18538      *
18539      * @throws IllegalArgumentException If they specified key is not valid
18540      *
18541      * @see #setTag(Object)
18542      * @see #getTag(int)
18543      */
18544     public void setTag(int key, final Object tag) {
18545         // If the package id is 0x00 or 0x01, it's either an undefined package
18546         // or a framework id
18547         if ((key >>> 24) < 2) {
18548             throw new IllegalArgumentException("The key must be an application-specific "
18549                     + "resource id.");
18550         }
18551 
18552         setKeyedTag(key, tag);
18553     }
18554 
18555     /**
18556      * Variation of {@link #setTag(int, Object)} that enforces the key to be a
18557      * framework id.
18558      *
18559      * @hide
18560      */
18561     public void setTagInternal(int key, Object tag) {
18562         if ((key >>> 24) != 0x1) {
18563             throw new IllegalArgumentException("The key must be a framework-specific "
18564                     + "resource id.");
18565         }
18566 
18567         setKeyedTag(key, tag);
18568     }
18569 
18570     private void setKeyedTag(int key, Object tag) {
18571         if (mKeyedTags == null) {
18572             mKeyedTags = new SparseArray<Object>(2);
18573         }
18574 
18575         mKeyedTags.put(key, tag);
18576     }
18577 
18578     /**
18579      * Prints information about this view in the log output, with the tag
18580      * {@link #VIEW_LOG_TAG}.
18581      *
18582      * @hide
18583      */
18584     public void debug() {
18585         debug(0);
18586     }
18587 
18588     /**
18589      * Prints information about this view in the log output, with the tag
18590      * {@link #VIEW_LOG_TAG}. Each line in the output is preceded with an
18591      * indentation defined by the <code>depth</code>.
18592      *
18593      * @param depth the indentation level
18594      *
18595      * @hide
18596      */
18597     protected void debug(int depth) {
18598         String output = debugIndent(depth - 1);
18599 
18600         output += "+ " + this;
18601         int id = getId();
18602         if (id != -1) {
18603             output += " (id=" + id + ")";
18604         }
18605         Object tag = getTag();
18606         if (tag != null) {
18607             output += " (tag=" + tag + ")";
18608         }
18609         Log.d(VIEW_LOG_TAG, output);
18610 
18611         if ((mPrivateFlags & PFLAG_FOCUSED) != 0) {
18612             output = debugIndent(depth) + " FOCUSED";
18613             Log.d(VIEW_LOG_TAG, output);
18614         }
18615 
18616         output = debugIndent(depth);
18617         output += "frame={" + mLeft + ", " + mTop + ", " + mRight
18618                 + ", " + mBottom + "} scroll={" + mScrollX + ", " + mScrollY
18619                 + "} ";
18620         Log.d(VIEW_LOG_TAG, output);
18621 
18622         if (mPaddingLeft != 0 || mPaddingTop != 0 || mPaddingRight != 0
18623                 || mPaddingBottom != 0) {
18624             output = debugIndent(depth);
18625             output += "padding={" + mPaddingLeft + ", " + mPaddingTop
18626                     + ", " + mPaddingRight + ", " + mPaddingBottom + "}";
18627             Log.d(VIEW_LOG_TAG, output);
18628         }
18629 
18630         output = debugIndent(depth);
18631         output += "mMeasureWidth=" + mMeasuredWidth +
18632                 " mMeasureHeight=" + mMeasuredHeight;
18633         Log.d(VIEW_LOG_TAG, output);
18634 
18635         output = debugIndent(depth);
18636         if (mLayoutParams == null) {
18637             output += "BAD! no layout params";
18638         } else {
18639             output = mLayoutParams.debug(output);
18640         }
18641         Log.d(VIEW_LOG_TAG, output);
18642 
18643         output = debugIndent(depth);
18644         output += "flags={";
18645         output += View.printFlags(mViewFlags);
18646         output += "}";
18647         Log.d(VIEW_LOG_TAG, output);
18648 
18649         output = debugIndent(depth);
18650         output += "privateFlags={";
18651         output += View.printPrivateFlags(mPrivateFlags);
18652         output += "}";
18653         Log.d(VIEW_LOG_TAG, output);
18654     }
18655 
18656     /**
18657      * Creates a string of whitespaces used for indentation.
18658      *
18659      * @param depth the indentation level
18660      * @return a String containing (depth * 2 + 3) * 2 white spaces
18661      *
18662      * @hide
18663      */
18664     protected static String debugIndent(int depth) {
18665         StringBuilder spaces = new StringBuilder((depth * 2 + 3) * 2);
18666         for (int i = 0; i < (depth * 2) + 3; i++) {
18667             spaces.append(' ').append(' ');
18668         }
18669         return spaces.toString();
18670     }
18671 
18672     /**
18673      * <p>Return the offset of the widget's text baseline from the widget's top
18674      * boundary. If this widget does not support baseline alignment, this
18675      * method returns -1. </p>
18676      *
18677      * @return the offset of the baseline within the widget's bounds or -1
18678      *         if baseline alignment is not supported
18679      */
18680     @ViewDebug.ExportedProperty(category = "layout")
18681     public int getBaseline() {
18682         return -1;
18683     }
18684 
18685     /**
18686      * Returns whether the view hierarchy is currently undergoing a layout pass. This
18687      * information is useful to avoid situations such as calling {@link #requestLayout()} during
18688      * a layout pass.
18689      *
18690      * @return whether the view hierarchy is currently undergoing a layout pass
18691      */
18692     public boolean isInLayout() {
18693         ViewRootImpl viewRoot = getViewRootImpl();
18694         return (viewRoot != null && viewRoot.isInLayout());
18695     }
18696 
18697     /**
18698      * Call this when something has changed which has invalidated the
18699      * layout of this view. This will schedule a layout pass of the view
18700      * tree. This should not be called while the view hierarchy is currently in a layout
18701      * pass ({@link #isInLayout()}. If layout is happening, the request may be honored at the
18702      * end of the current layout pass (and then layout will run again) or after the current
18703      * frame is drawn and the next layout occurs.
18704      *
18705      * <p>Subclasses which override this method should call the superclass method to
18706      * handle possible request-during-layout errors correctly.</p>
18707      */
18708     @CallSuper
18709     public void requestLayout() {
18710         if (mMeasureCache != null) mMeasureCache.clear();
18711 
18712         if (mAttachInfo != null && mAttachInfo.mViewRequestingLayout == null) {
18713             // Only trigger request-during-layout logic if this is the view requesting it,
18714             // not the views in its parent hierarchy
18715             ViewRootImpl viewRoot = getViewRootImpl();
18716             if (viewRoot != null && viewRoot.isInLayout()) {
18717                 if (!viewRoot.requestLayoutDuringLayout(this)) {
18718                     return;
18719                 }
18720             }
18721             mAttachInfo.mViewRequestingLayout = this;
18722         }
18723 
18724         mPrivateFlags |= PFLAG_FORCE_LAYOUT;
18725         mPrivateFlags |= PFLAG_INVALIDATED;
18726 
18727         if (mParent != null && !mParent.isLayoutRequested()) {
18728             mParent.requestLayout();
18729         }
18730         if (mAttachInfo != null && mAttachInfo.mViewRequestingLayout == this) {
18731             mAttachInfo.mViewRequestingLayout = null;
18732         }
18733     }
18734 
18735     /**
18736      * Forces this view to be laid out during the next layout pass.
18737      * This method does not call requestLayout() or forceLayout()
18738      * on the parent.
18739      */
18740     public void forceLayout() {
18741         if (mMeasureCache != null) mMeasureCache.clear();
18742 
18743         mPrivateFlags |= PFLAG_FORCE_LAYOUT;
18744         mPrivateFlags |= PFLAG_INVALIDATED;
18745     }
18746 
18747     /**
18748      * <p>
18749      * This is called to find out how big a view should be. The parent
18750      * supplies constraint information in the width and height parameters.
18751      * </p>
18752      *
18753      * <p>
18754      * The actual measurement work of a view is performed in
18755      * {@link #onMeasure(int, int)}, called by this method. Therefore, only
18756      * {@link #onMeasure(int, int)} can and must be overridden by subclasses.
18757      * </p>
18758      *
18759      *
18760      * @param widthMeasureSpec Horizontal space requirements as imposed by the
18761      *        parent
18762      * @param heightMeasureSpec Vertical space requirements as imposed by the
18763      *        parent
18764      *
18765      * @see #onMeasure(int, int)
18766      */
18767     public final void measure(int widthMeasureSpec, int heightMeasureSpec) {
18768         boolean optical = isLayoutModeOptical(this);
18769         if (optical != isLayoutModeOptical(mParent)) {
18770             Insets insets = getOpticalInsets();
18771             int oWidth  = insets.left + insets.right;
18772             int oHeight = insets.top  + insets.bottom;
18773             widthMeasureSpec  = MeasureSpec.adjust(widthMeasureSpec,  optical ? -oWidth  : oWidth);
18774             heightMeasureSpec = MeasureSpec.adjust(heightMeasureSpec, optical ? -oHeight : oHeight);
18775         }
18776 
18777         // Suppress sign extension for the low bytes
18778         long key = (long) widthMeasureSpec << 32 | (long) heightMeasureSpec & 0xffffffffL;
18779         if (mMeasureCache == null) mMeasureCache = new LongSparseLongArray(2);
18780 
18781         if ((mPrivateFlags & PFLAG_FORCE_LAYOUT) == PFLAG_FORCE_LAYOUT ||
18782                 widthMeasureSpec != mOldWidthMeasureSpec ||
18783                 heightMeasureSpec != mOldHeightMeasureSpec) {
18784 
18785             // first clears the measured dimension flag
18786             mPrivateFlags &= ~PFLAG_MEASURED_DIMENSION_SET;
18787 
18788             resolveRtlPropertiesIfNeeded();
18789 
18790             int cacheIndex = (mPrivateFlags & PFLAG_FORCE_LAYOUT) == PFLAG_FORCE_LAYOUT ? -1 :
18791                     mMeasureCache.indexOfKey(key);
18792             if (cacheIndex < 0 || sIgnoreMeasureCache) {
18793                 // measure ourselves, this should set the measured dimension flag back
18794                 onMeasure(widthMeasureSpec, heightMeasureSpec);
18795                 mPrivateFlags3 &= ~PFLAG3_MEASURE_NEEDED_BEFORE_LAYOUT;
18796             } else {
18797                 long value = mMeasureCache.valueAt(cacheIndex);
18798                 // Casting a long to int drops the high 32 bits, no mask needed
18799                 setMeasuredDimensionRaw((int) (value >> 32), (int) value);
18800                 mPrivateFlags3 |= PFLAG3_MEASURE_NEEDED_BEFORE_LAYOUT;
18801             }
18802 
18803             // flag not set, setMeasuredDimension() was not invoked, we raise
18804             // an exception to warn the developer
18805             if ((mPrivateFlags & PFLAG_MEASURED_DIMENSION_SET) != PFLAG_MEASURED_DIMENSION_SET) {
18806                 throw new IllegalStateException("View with id " + getId() + ": "
18807                         + getClass().getName() + "#onMeasure() did not set the"
18808                         + " measured dimension by calling"
18809                         + " setMeasuredDimension()");
18810             }
18811 
18812             mPrivateFlags |= PFLAG_LAYOUT_REQUIRED;
18813         }
18814 
18815         mOldWidthMeasureSpec = widthMeasureSpec;
18816         mOldHeightMeasureSpec = heightMeasureSpec;
18817 
18818         mMeasureCache.put(key, ((long) mMeasuredWidth) << 32 |
18819                 (long) mMeasuredHeight & 0xffffffffL); // suppress sign extension
18820     }
18821 
18822     /**
18823      * <p>
18824      * Measure the view and its content to determine the measured width and the
18825      * measured height. This method is invoked by {@link #measure(int, int)} and
18826      * should be overridden by subclasses to provide accurate and efficient
18827      * measurement of their contents.
18828      * </p>
18829      *
18830      * <p>
18831      * <strong>CONTRACT:</strong> When overriding this method, you
18832      * <em>must</em> call {@link #setMeasuredDimension(int, int)} to store the
18833      * measured width and height of this view. Failure to do so will trigger an
18834      * <code>IllegalStateException</code>, thrown by
18835      * {@link #measure(int, int)}. Calling the superclass'
18836      * {@link #onMeasure(int, int)} is a valid use.
18837      * </p>
18838      *
18839      * <p>
18840      * The base class implementation of measure defaults to the background size,
18841      * unless a larger size is allowed by the MeasureSpec. Subclasses should
18842      * override {@link #onMeasure(int, int)} to provide better measurements of
18843      * their content.
18844      * </p>
18845      *
18846      * <p>
18847      * If this method is overridden, it is the subclass's responsibility to make
18848      * sure the measured height and width are at least the view's minimum height
18849      * and width ({@link #getSuggestedMinimumHeight()} and
18850      * {@link #getSuggestedMinimumWidth()}).
18851      * </p>
18852      *
18853      * @param widthMeasureSpec horizontal space requirements as imposed by the parent.
18854      *                         The requirements are encoded with
18855      *                         {@link android.view.View.MeasureSpec}.
18856      * @param heightMeasureSpec vertical space requirements as imposed by the parent.
18857      *                         The requirements are encoded with
18858      *                         {@link android.view.View.MeasureSpec}.
18859      *
18860      * @see #getMeasuredWidth()
18861      * @see #getMeasuredHeight()
18862      * @see #setMeasuredDimension(int, int)
18863      * @see #getSuggestedMinimumHeight()
18864      * @see #getSuggestedMinimumWidth()
18865      * @see android.view.View.MeasureSpec#getMode(int)
18866      * @see android.view.View.MeasureSpec#getSize(int)
18867      */
18868     protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
18869         setMeasuredDimension(getDefaultSize(getSuggestedMinimumWidth(), widthMeasureSpec),
18870                 getDefaultSize(getSuggestedMinimumHeight(), heightMeasureSpec));
18871     }
18872 
18873     /**
18874      * <p>This method must be called by {@link #onMeasure(int, int)} to store the
18875      * measured width and measured height. Failing to do so will trigger an
18876      * exception at measurement time.</p>
18877      *
18878      * @param measuredWidth The measured width of this view.  May be a complex
18879      * bit mask as defined by {@link #MEASURED_SIZE_MASK} and
18880      * {@link #MEASURED_STATE_TOO_SMALL}.
18881      * @param measuredHeight The measured height of this view.  May be a complex
18882      * bit mask as defined by {@link #MEASURED_SIZE_MASK} and
18883      * {@link #MEASURED_STATE_TOO_SMALL}.
18884      */
18885     protected final void setMeasuredDimension(int measuredWidth, int measuredHeight) {
18886         boolean optical = isLayoutModeOptical(this);
18887         if (optical != isLayoutModeOptical(mParent)) {
18888             Insets insets = getOpticalInsets();
18889             int opticalWidth  = insets.left + insets.right;
18890             int opticalHeight = insets.top  + insets.bottom;
18891 
18892             measuredWidth  += optical ? opticalWidth  : -opticalWidth;
18893             measuredHeight += optical ? opticalHeight : -opticalHeight;
18894         }
18895         setMeasuredDimensionRaw(measuredWidth, measuredHeight);
18896     }
18897 
18898     /**
18899      * Sets the measured dimension without extra processing for things like optical bounds.
18900      * Useful for reapplying consistent values that have already been cooked with adjustments
18901      * for optical bounds, etc. such as those from the measurement cache.
18902      *
18903      * @param measuredWidth The measured width of this view.  May be a complex
18904      * bit mask as defined by {@link #MEASURED_SIZE_MASK} and
18905      * {@link #MEASURED_STATE_TOO_SMALL}.
18906      * @param measuredHeight The measured height of this view.  May be a complex
18907      * bit mask as defined by {@link #MEASURED_SIZE_MASK} and
18908      * {@link #MEASURED_STATE_TOO_SMALL}.
18909      */
18910     private void setMeasuredDimensionRaw(int measuredWidth, int measuredHeight) {
18911         mMeasuredWidth = measuredWidth;
18912         mMeasuredHeight = measuredHeight;
18913 
18914         mPrivateFlags |= PFLAG_MEASURED_DIMENSION_SET;
18915     }
18916 
18917     /**
18918      * Merge two states as returned by {@link #getMeasuredState()}.
18919      * @param curState The current state as returned from a view or the result
18920      * of combining multiple views.
18921      * @param newState The new view state to combine.
18922      * @return Returns a new integer reflecting the combination of the two
18923      * states.
18924      */
18925     public static int combineMeasuredStates(int curState, int newState) {
18926         return curState | newState;
18927     }
18928 
18929     /**
18930      * Version of {@link #resolveSizeAndState(int, int, int)}
18931      * returning only the {@link #MEASURED_SIZE_MASK} bits of the result.
18932      */
18933     public static int resolveSize(int size, int measureSpec) {
18934         return resolveSizeAndState(size, measureSpec, 0) & MEASURED_SIZE_MASK;
18935     }
18936 
18937     /**
18938      * Utility to reconcile a desired size and state, with constraints imposed
18939      * by a MeasureSpec. Will take the desired size, unless a different size
18940      * is imposed by the constraints. The returned value is a compound integer,
18941      * with the resolved size in the {@link #MEASURED_SIZE_MASK} bits and
18942      * optionally the bit {@link #MEASURED_STATE_TOO_SMALL} set if the
18943      * resulting size is smaller than the size the view wants to be.
18944      *
18945      * @param size How big the view wants to be.
18946      * @param measureSpec Constraints imposed by the parent.
18947      * @param childMeasuredState Size information bit mask for the view's
18948      *                           children.
18949      * @return Size information bit mask as defined by
18950      *         {@link #MEASURED_SIZE_MASK} and
18951      *         {@link #MEASURED_STATE_TOO_SMALL}.
18952      */
18953     public static int resolveSizeAndState(int size, int measureSpec, int childMeasuredState) {
18954         final int specMode = MeasureSpec.getMode(measureSpec);
18955         final int specSize = MeasureSpec.getSize(measureSpec);
18956         final int result;
18957         switch (specMode) {
18958             case MeasureSpec.AT_MOST:
18959                 if (specSize < size) {
18960                     result = specSize | MEASURED_STATE_TOO_SMALL;
18961                 } else {
18962                     result = size;
18963                 }
18964                 break;
18965             case MeasureSpec.EXACTLY:
18966                 result = specSize;
18967                 break;
18968             case MeasureSpec.UNSPECIFIED:
18969             default:
18970                 result = size;
18971         }
18972         return result | (childMeasuredState & MEASURED_STATE_MASK);
18973     }
18974 
18975     /**
18976      * Utility to return a default size. Uses the supplied size if the
18977      * MeasureSpec imposed no constraints. Will get larger if allowed
18978      * by the MeasureSpec.
18979      *
18980      * @param size Default size for this view
18981      * @param measureSpec Constraints imposed by the parent
18982      * @return The size this view should be.
18983      */
18984     public static int getDefaultSize(int size, int measureSpec) {
18985         int result = size;
18986         int specMode = MeasureSpec.getMode(measureSpec);
18987         int specSize = MeasureSpec.getSize(measureSpec);
18988 
18989         switch (specMode) {
18990         case MeasureSpec.UNSPECIFIED:
18991             result = size;
18992             break;
18993         case MeasureSpec.AT_MOST:
18994         case MeasureSpec.EXACTLY:
18995             result = specSize;
18996             break;
18997         }
18998         return result;
18999     }
19000 
19001     /**
19002      * Returns the suggested minimum height that the view should use. This
19003      * returns the maximum of the view's minimum height
19004      * and the background's minimum height
19005      * ({@link android.graphics.drawable.Drawable#getMinimumHeight()}).
19006      * <p>
19007      * When being used in {@link #onMeasure(int, int)}, the caller should still
19008      * ensure the returned height is within the requirements of the parent.
19009      *
19010      * @return The suggested minimum height of the view.
19011      */
19012     protected int getSuggestedMinimumHeight() {
19013         return (mBackground == null) ? mMinHeight : max(mMinHeight, mBackground.getMinimumHeight());
19014 
19015     }
19016 
19017     /**
19018      * Returns the suggested minimum width that the view should use. This
19019      * returns the maximum of the view's minimum width)
19020      * and the background's minimum width
19021      *  ({@link android.graphics.drawable.Drawable#getMinimumWidth()}).
19022      * <p>
19023      * When being used in {@link #onMeasure(int, int)}, the caller should still
19024      * ensure the returned width is within the requirements of the parent.
19025      *
19026      * @return The suggested minimum width of the view.
19027      */
19028     protected int getSuggestedMinimumWidth() {
19029         return (mBackground == null) ? mMinWidth : max(mMinWidth, mBackground.getMinimumWidth());
19030     }
19031 
19032     /**
19033      * Returns the minimum height of the view.
19034      *
19035      * @return the minimum height the view will try to be.
19036      *
19037      * @see #setMinimumHeight(int)
19038      *
19039      * @attr ref android.R.styleable#View_minHeight
19040      */
19041     public int getMinimumHeight() {
19042         return mMinHeight;
19043     }
19044 
19045     /**
19046      * Sets the minimum height of the view. It is not guaranteed the view will
19047      * be able to achieve this minimum height (for example, if its parent layout
19048      * constrains it with less available height).
19049      *
19050      * @param minHeight The minimum height the view will try to be.
19051      *
19052      * @see #getMinimumHeight()
19053      *
19054      * @attr ref android.R.styleable#View_minHeight
19055      */
19056     public void setMinimumHeight(int minHeight) {
19057         mMinHeight = minHeight;
19058         requestLayout();
19059     }
19060 
19061     /**
19062      * Returns the minimum width of the view.
19063      *
19064      * @return the minimum width the view will try to be.
19065      *
19066      * @see #setMinimumWidth(int)
19067      *
19068      * @attr ref android.R.styleable#View_minWidth
19069      */
19070     public int getMinimumWidth() {
19071         return mMinWidth;
19072     }
19073 
19074     /**
19075      * Sets the minimum width of the view. It is not guaranteed the view will
19076      * be able to achieve this minimum width (for example, if its parent layout
19077      * constrains it with less available width).
19078      *
19079      * @param minWidth The minimum width the view will try to be.
19080      *
19081      * @see #getMinimumWidth()
19082      *
19083      * @attr ref android.R.styleable#View_minWidth
19084      */
19085     public void setMinimumWidth(int minWidth) {
19086         mMinWidth = minWidth;
19087         requestLayout();
19088 
19089     }
19090 
19091     /**
19092      * Get the animation currently associated with this view.
19093      *
19094      * @return The animation that is currently playing or
19095      *         scheduled to play for this view.
19096      */
19097     public Animation getAnimation() {
19098         return mCurrentAnimation;
19099     }
19100 
19101     /**
19102      * Start the specified animation now.
19103      *
19104      * @param animation the animation to start now
19105      */
19106     public void startAnimation(Animation animation) {
19107         animation.setStartTime(Animation.START_ON_FIRST_FRAME);
19108         setAnimation(animation);
19109         invalidateParentCaches();
19110         invalidate(true);
19111     }
19112 
19113     /**
19114      * Cancels any animations for this view.
19115      */
19116     public void clearAnimation() {
19117         if (mCurrentAnimation != null) {
19118             mCurrentAnimation.detach();
19119         }
19120         mCurrentAnimation = null;
19121         invalidateParentIfNeeded();
19122     }
19123 
19124     /**
19125      * Sets the next animation to play for this view.
19126      * If you want the animation to play immediately, use
19127      * {@link #startAnimation(android.view.animation.Animation)} instead.
19128      * This method provides allows fine-grained
19129      * control over the start time and invalidation, but you
19130      * must make sure that 1) the animation has a start time set, and
19131      * 2) the view's parent (which controls animations on its children)
19132      * will be invalidated when the animation is supposed to
19133      * start.
19134      *
19135      * @param animation The next animation, or null.
19136      */
19137     public void setAnimation(Animation animation) {
19138         mCurrentAnimation = animation;
19139 
19140         if (animation != null) {
19141             // If the screen is off assume the animation start time is now instead of
19142             // the next frame we draw. Keeping the START_ON_FIRST_FRAME start time
19143             // would cause the animation to start when the screen turns back on
19144             if (mAttachInfo != null && mAttachInfo.mDisplayState == Display.STATE_OFF
19145                     && animation.getStartTime() == Animation.START_ON_FIRST_FRAME) {
19146                 animation.setStartTime(AnimationUtils.currentAnimationTimeMillis());
19147             }
19148             animation.reset();
19149         }
19150     }
19151 
19152     /**
19153      * Invoked by a parent ViewGroup to notify the start of the animation
19154      * currently associated with this view. If you override this method,
19155      * always call super.onAnimationStart();
19156      *
19157      * @see #setAnimation(android.view.animation.Animation)
19158      * @see #getAnimation()
19159      */
19160     @CallSuper
19161     protected void onAnimationStart() {
19162         mPrivateFlags |= PFLAG_ANIMATION_STARTED;
19163     }
19164 
19165     /**
19166      * Invoked by a parent ViewGroup to notify the end of the animation
19167      * currently associated with this view. If you override this method,
19168      * always call super.onAnimationEnd();
19169      *
19170      * @see #setAnimation(android.view.animation.Animation)
19171      * @see #getAnimation()
19172      */
19173     @CallSuper
19174     protected void onAnimationEnd() {
19175         mPrivateFlags &= ~PFLAG_ANIMATION_STARTED;
19176     }
19177 
19178     /**
19179      * Invoked if there is a Transform that involves alpha. Subclass that can
19180      * draw themselves with the specified alpha should return true, and then
19181      * respect that alpha when their onDraw() is called. If this returns false
19182      * then the view may be redirected to draw into an offscreen buffer to
19183      * fulfill the request, which will look fine, but may be slower than if the
19184      * subclass handles it internally. The default implementation returns false.
19185      *
19186      * @param alpha The alpha (0..255) to apply to the view's drawing
19187      * @return true if the view can draw with the specified alpha.
19188      */
19189     protected boolean onSetAlpha(int alpha) {
19190         return false;
19191     }
19192 
19193     /**
19194      * This is used by the RootView to perform an optimization when
19195      * the view hierarchy contains one or several SurfaceView.
19196      * SurfaceView is always considered transparent, but its children are not,
19197      * therefore all View objects remove themselves from the global transparent
19198      * region (passed as a parameter to this function).
19199      *
19200      * @param region The transparent region for this ViewAncestor (window).
19201      *
19202      * @return Returns true if the effective visibility of the view at this
19203      * point is opaque, regardless of the transparent region; returns false
19204      * if it is possible for underlying windows to be seen behind the view.
19205      *
19206      * {@hide}
19207      */
19208     public boolean gatherTransparentRegion(Region region) {
19209         final AttachInfo attachInfo = mAttachInfo;
19210         if (region != null && attachInfo != null) {
19211             final int pflags = mPrivateFlags;
19212             if ((pflags & PFLAG_SKIP_DRAW) == 0) {
19213                 // The SKIP_DRAW flag IS NOT set, so this view draws. We need to
19214                 // remove it from the transparent region.
19215                 final int[] location = attachInfo.mTransparentLocation;
19216                 getLocationInWindow(location);
19217                 region.op(location[0], location[1], location[0] + mRight - mLeft,
19218                         location[1] + mBottom - mTop, Region.Op.DIFFERENCE);
19219             } else {
19220                 if (mBackground != null && mBackground.getOpacity() != PixelFormat.TRANSPARENT) {
19221                     // The SKIP_DRAW flag IS set and the background drawable exists, we remove
19222                     // the background drawable's non-transparent parts from this transparent region.
19223                     applyDrawableToTransparentRegion(mBackground, region);
19224                 }
19225                 if (mForegroundInfo != null && mForegroundInfo.mDrawable != null
19226                         && mForegroundInfo.mDrawable.getOpacity() != PixelFormat.TRANSPARENT) {
19227                     // Similarly, we remove the foreground drawable's non-transparent parts.
19228                     applyDrawableToTransparentRegion(mForegroundInfo.mDrawable, region);
19229                 }
19230             }
19231         }
19232         return true;
19233     }
19234 
19235     /**
19236      * Play a sound effect for this view.
19237      *
19238      * <p>The framework will play sound effects for some built in actions, such as
19239      * clicking, but you may wish to play these effects in your widget,
19240      * for instance, for internal navigation.
19241      *
19242      * <p>The sound effect will only be played if sound effects are enabled by the user, and
19243      * {@link #isSoundEffectsEnabled()} is true.
19244      *
19245      * @param soundConstant One of the constants defined in {@link SoundEffectConstants}
19246      */
19247     public void playSoundEffect(int soundConstant) {
19248         if (mAttachInfo == null || mAttachInfo.mRootCallbacks == null || !isSoundEffectsEnabled()) {
19249             return;
19250         }
19251         mAttachInfo.mRootCallbacks.playSoundEffect(soundConstant);
19252     }
19253 
19254     /**
19255      * BZZZTT!!1!
19256      *
19257      * <p>Provide haptic feedback to the user for this view.
19258      *
19259      * <p>The framework will provide haptic feedback for some built in actions,
19260      * such as long presses, but you may wish to provide feedback for your
19261      * own widget.
19262      *
19263      * <p>The feedback will only be performed if
19264      * {@link #isHapticFeedbackEnabled()} is true.
19265      *
19266      * @param feedbackConstant One of the constants defined in
19267      * {@link HapticFeedbackConstants}
19268      */
19269     public boolean performHapticFeedback(int feedbackConstant) {
19270         return performHapticFeedback(feedbackConstant, 0);
19271     }
19272 
19273     /**
19274      * BZZZTT!!1!
19275      *
19276      * <p>Like {@link #performHapticFeedback(int)}, with additional options.
19277      *
19278      * @param feedbackConstant One of the constants defined in
19279      * {@link HapticFeedbackConstants}
19280      * @param flags Additional flags as per {@link HapticFeedbackConstants}.
19281      */
19282     public boolean performHapticFeedback(int feedbackConstant, int flags) {
19283         if (mAttachInfo == null) {
19284             return false;
19285         }
19286         //noinspection SimplifiableIfStatement
19287         if ((flags & HapticFeedbackConstants.FLAG_IGNORE_VIEW_SETTING) == 0
19288                 && !isHapticFeedbackEnabled()) {
19289             return false;
19290         }
19291         return mAttachInfo.mRootCallbacks.performHapticFeedback(feedbackConstant,
19292                 (flags & HapticFeedbackConstants.FLAG_IGNORE_GLOBAL_SETTING) != 0);
19293     }
19294 
19295     /**
19296      * Request that the visibility of the status bar or other screen/window
19297      * decorations be changed.
19298      *
19299      * <p>This method is used to put the over device UI into temporary modes
19300      * where the user's attention is focused more on the application content,
19301      * by dimming or hiding surrounding system affordances.  This is typically
19302      * used in conjunction with {@link Window#FEATURE_ACTION_BAR_OVERLAY
19303      * Window.FEATURE_ACTION_BAR_OVERLAY}, allowing the applications content
19304      * to be placed behind the action bar (and with these flags other system
19305      * affordances) so that smooth transitions between hiding and showing them
19306      * can be done.
19307      *
19308      * <p>Two representative examples of the use of system UI visibility is
19309      * implementing a content browsing application (like a magazine reader)
19310      * and a video playing application.
19311      *
19312      * <p>The first code shows a typical implementation of a View in a content
19313      * browsing application.  In this implementation, the application goes
19314      * into a content-oriented mode by hiding the status bar and action bar,
19315      * and putting the navigation elements into lights out mode.  The user can
19316      * then interact with content while in this mode.  Such an application should
19317      * provide an easy way for the user to toggle out of the mode (such as to
19318      * check information in the status bar or access notifications).  In the
19319      * implementation here, this is done simply by tapping on the content.
19320      *
19321      * {@sample development/samples/ApiDemos/src/com/example/android/apis/view/ContentBrowserActivity.java
19322      *      content}
19323      *
19324      * <p>This second code sample shows a typical implementation of a View
19325      * in a video playing application.  In this situation, while the video is
19326      * playing the application would like to go into a complete full-screen mode,
19327      * to use as much of the display as possible for the video.  When in this state
19328      * the user can not interact with the application; the system intercepts
19329      * touching on the screen to pop the UI out of full screen mode.  See
19330      * {@link #fitSystemWindows(Rect)} for a sample layout that goes with this code.
19331      *
19332      * {@sample development/samples/ApiDemos/src/com/example/android/apis/view/VideoPlayerActivity.java
19333      *      content}
19334      *
19335      * @param visibility  Bitwise-or of flags {@link #SYSTEM_UI_FLAG_LOW_PROFILE},
19336      * {@link #SYSTEM_UI_FLAG_HIDE_NAVIGATION}, {@link #SYSTEM_UI_FLAG_FULLSCREEN},
19337      * {@link #SYSTEM_UI_FLAG_LAYOUT_STABLE}, {@link #SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION},
19338      * {@link #SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN}, {@link #SYSTEM_UI_FLAG_IMMERSIVE},
19339      * and {@link #SYSTEM_UI_FLAG_IMMERSIVE_STICKY}.
19340      */
19341     public void setSystemUiVisibility(int visibility) {
19342         if (visibility != mSystemUiVisibility) {
19343             mSystemUiVisibility = visibility;
19344             if (mParent != null && mAttachInfo != null && !mAttachInfo.mRecomputeGlobalAttributes) {
19345                 mParent.recomputeViewAttributes(this);
19346             }
19347         }
19348     }
19349 
19350     /**
19351      * Returns the last {@link #setSystemUiVisibility(int)} that this view has requested.
19352      * @return  Bitwise-or of flags {@link #SYSTEM_UI_FLAG_LOW_PROFILE},
19353      * {@link #SYSTEM_UI_FLAG_HIDE_NAVIGATION}, {@link #SYSTEM_UI_FLAG_FULLSCREEN},
19354      * {@link #SYSTEM_UI_FLAG_LAYOUT_STABLE}, {@link #SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION},
19355      * {@link #SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN}, {@link #SYSTEM_UI_FLAG_IMMERSIVE},
19356      * and {@link #SYSTEM_UI_FLAG_IMMERSIVE_STICKY}.
19357      */
19358     public int getSystemUiVisibility() {
19359         return mSystemUiVisibility;
19360     }
19361 
19362     /**
19363      * Returns the current system UI visibility that is currently set for
19364      * the entire window.  This is the combination of the
19365      * {@link #setSystemUiVisibility(int)} values supplied by all of the
19366      * views in the window.
19367      */
19368     public int getWindowSystemUiVisibility() {
19369         return mAttachInfo != null ? mAttachInfo.mSystemUiVisibility : 0;
19370     }
19371 
19372     /**
19373      * Override to find out when the window's requested system UI visibility
19374      * has changed, that is the value returned by {@link #getWindowSystemUiVisibility()}.
19375      * This is different from the callbacks received through
19376      * {@link #setOnSystemUiVisibilityChangeListener(OnSystemUiVisibilityChangeListener)}
19377      * in that this is only telling you about the local request of the window,
19378      * not the actual values applied by the system.
19379      */
19380     public void onWindowSystemUiVisibilityChanged(int visible) {
19381     }
19382 
19383     /**
19384      * Dispatch callbacks to {@link #onWindowSystemUiVisibilityChanged(int)} down
19385      * the view hierarchy.
19386      */
19387     public void dispatchWindowSystemUiVisiblityChanged(int visible) {
19388         onWindowSystemUiVisibilityChanged(visible);
19389     }
19390 
19391     /**
19392      * Set a listener to receive callbacks when the visibility of the system bar changes.
19393      * @param l  The {@link OnSystemUiVisibilityChangeListener} to receive callbacks.
19394      */
19395     public void setOnSystemUiVisibilityChangeListener(OnSystemUiVisibilityChangeListener l) {
19396         getListenerInfo().mOnSystemUiVisibilityChangeListener = l;
19397         if (mParent != null && mAttachInfo != null && !mAttachInfo.mRecomputeGlobalAttributes) {
19398             mParent.recomputeViewAttributes(this);
19399         }
19400     }
19401 
19402     /**
19403      * Dispatch callbacks to {@link #setOnSystemUiVisibilityChangeListener} down
19404      * the view hierarchy.
19405      */
19406     public void dispatchSystemUiVisibilityChanged(int visibility) {
19407         ListenerInfo li = mListenerInfo;
19408         if (li != null && li.mOnSystemUiVisibilityChangeListener != null) {
19409             li.mOnSystemUiVisibilityChangeListener.onSystemUiVisibilityChange(
19410                     visibility & PUBLIC_STATUS_BAR_VISIBILITY_MASK);
19411         }
19412     }
19413 
19414     boolean updateLocalSystemUiVisibility(int localValue, int localChanges) {
19415         int val = (mSystemUiVisibility&~localChanges) | (localValue&localChanges);
19416         if (val != mSystemUiVisibility) {
19417             setSystemUiVisibility(val);
19418             return true;
19419         }
19420         return false;
19421     }
19422 
19423     /** @hide */
19424     public void setDisabledSystemUiVisibility(int flags) {
19425         if (mAttachInfo != null) {
19426             if (mAttachInfo.mDisabledSystemUiVisibility != flags) {
19427                 mAttachInfo.mDisabledSystemUiVisibility = flags;
19428                 if (mParent != null) {
19429                     mParent.recomputeViewAttributes(this);
19430                 }
19431             }
19432         }
19433     }
19434 
19435     /**
19436      * Creates an image that the system displays during the drag and drop
19437      * operation. This is called a &quot;drag shadow&quot;. The default implementation
19438      * for a DragShadowBuilder based on a View returns an image that has exactly the same
19439      * appearance as the given View. The default also positions the center of the drag shadow
19440      * directly under the touch point. If no View is provided (the constructor with no parameters
19441      * is used), and {@link #onProvideShadowMetrics(Point,Point) onProvideShadowMetrics()} and
19442      * {@link #onDrawShadow(Canvas) onDrawShadow()} are not overridden, then the
19443      * default is an invisible drag shadow.
19444      * <p>
19445      * You are not required to use the View you provide to the constructor as the basis of the
19446      * drag shadow. The {@link #onDrawShadow(Canvas) onDrawShadow()} method allows you to draw
19447      * anything you want as the drag shadow.
19448      * </p>
19449      * <p>
19450      *  You pass a DragShadowBuilder object to the system when you start the drag. The system
19451      *  calls {@link #onProvideShadowMetrics(Point,Point) onProvideShadowMetrics()} to get the
19452      *  size and position of the drag shadow. It uses this data to construct a
19453      *  {@link android.graphics.Canvas} object, then it calls {@link #onDrawShadow(Canvas) onDrawShadow()}
19454      *  so that your application can draw the shadow image in the Canvas.
19455      * </p>
19456      *
19457      * <div class="special reference">
19458      * <h3>Developer Guides</h3>
19459      * <p>For a guide to implementing drag and drop features, read the
19460      * <a href="{@docRoot}guide/topics/ui/drag-drop.html">Drag and Drop</a> developer guide.</p>
19461      * </div>
19462      */
19463     public static class DragShadowBuilder {
19464         private final WeakReference<View> mView;
19465 
19466         /**
19467          * Constructs a shadow image builder based on a View. By default, the resulting drag
19468          * shadow will have the same appearance and dimensions as the View, with the touch point
19469          * over the center of the View.
19470          * @param view A View. Any View in scope can be used.
19471          */
19472         public DragShadowBuilder(View view) {
19473             mView = new WeakReference<View>(view);
19474         }
19475 
19476         /**
19477          * Construct a shadow builder object with no associated View.  This
19478          * constructor variant is only useful when the {@link #onProvideShadowMetrics(Point, Point)}
19479          * and {@link #onDrawShadow(Canvas)} methods are also overridden in order
19480          * to supply the drag shadow's dimensions and appearance without
19481          * reference to any View object. If they are not overridden, then the result is an
19482          * invisible drag shadow.
19483          */
19484         public DragShadowBuilder() {
19485             mView = new WeakReference<View>(null);
19486         }
19487 
19488         /**
19489          * Returns the View object that had been passed to the
19490          * {@link #View.DragShadowBuilder(View)}
19491          * constructor.  If that View parameter was {@code null} or if the
19492          * {@link #View.DragShadowBuilder()}
19493          * constructor was used to instantiate the builder object, this method will return
19494          * null.
19495          *
19496          * @return The View object associate with this builder object.
19497          */
19498         @SuppressWarnings({"JavadocReference"})
19499         final public View getView() {
19500             return mView.get();
19501         }
19502 
19503         /**
19504          * Provides the metrics for the shadow image. These include the dimensions of
19505          * the shadow image, and the point within that shadow that should
19506          * be centered under the touch location while dragging.
19507          * <p>
19508          * The default implementation sets the dimensions of the shadow to be the
19509          * same as the dimensions of the View itself and centers the shadow under
19510          * the touch point.
19511          * </p>
19512          *
19513          * @param shadowSize A {@link android.graphics.Point} containing the width and height
19514          * of the shadow image. Your application must set {@link android.graphics.Point#x} to the
19515          * desired width and must set {@link android.graphics.Point#y} to the desired height of the
19516          * image.
19517          *
19518          * @param shadowTouchPoint A {@link android.graphics.Point} for the position within the
19519          * shadow image that should be underneath the touch point during the drag and drop
19520          * operation. Your application must set {@link android.graphics.Point#x} to the
19521          * X coordinate and {@link android.graphics.Point#y} to the Y coordinate of this position.
19522          */
19523         public void onProvideShadowMetrics(Point shadowSize, Point shadowTouchPoint) {
19524             final View view = mView.get();
19525             if (view != null) {
19526                 shadowSize.set(view.getWidth(), view.getHeight());
19527                 shadowTouchPoint.set(shadowSize.x / 2, shadowSize.y / 2);
19528             } else {
19529                 Log.e(View.VIEW_LOG_TAG, "Asked for drag thumb metrics but no view");
19530             }
19531         }
19532 
19533         /**
19534          * Draws the shadow image. The system creates the {@link android.graphics.Canvas} object
19535          * based on the dimensions it received from the
19536          * {@link #onProvideShadowMetrics(Point, Point)} callback.
19537          *
19538          * @param canvas A {@link android.graphics.Canvas} object in which to draw the shadow image.
19539          */
19540         public void onDrawShadow(Canvas canvas) {
19541             final View view = mView.get();
19542             if (view != null) {
19543                 view.draw(canvas);
19544             } else {
19545                 Log.e(View.VIEW_LOG_TAG, "Asked to draw drag shadow but no view");
19546             }
19547         }
19548     }
19549 
19550     /**
19551      * Starts a drag and drop operation. When your application calls this method, it passes a
19552      * {@link android.view.View.DragShadowBuilder} object to the system. The
19553      * system calls this object's {@link DragShadowBuilder#onProvideShadowMetrics(Point, Point)}
19554      * to get metrics for the drag shadow, and then calls the object's
19555      * {@link DragShadowBuilder#onDrawShadow(Canvas)} to draw the drag shadow itself.
19556      * <p>
19557      *  Once the system has the drag shadow, it begins the drag and drop operation by sending
19558      *  drag events to all the View objects in your application that are currently visible. It does
19559      *  this either by calling the View object's drag listener (an implementation of
19560      *  {@link android.view.View.OnDragListener#onDrag(View,DragEvent) onDrag()} or by calling the
19561      *  View object's {@link android.view.View#onDragEvent(DragEvent) onDragEvent()} method.
19562      *  Both are passed a {@link android.view.DragEvent} object that has a
19563      *  {@link android.view.DragEvent#getAction()} value of
19564      *  {@link android.view.DragEvent#ACTION_DRAG_STARTED}.
19565      * </p>
19566      * <p>
19567      * Your application can invoke startDrag() on any attached View object. The View object does not
19568      * need to be the one used in {@link android.view.View.DragShadowBuilder}, nor does it need to
19569      * be related to the View the user selected for dragging.
19570      * </p>
19571      * @param data A {@link android.content.ClipData} object pointing to the data to be
19572      * transferred by the drag and drop operation.
19573      * @param shadowBuilder A {@link android.view.View.DragShadowBuilder} object for building the
19574      * drag shadow.
19575      * @param myLocalState An {@link java.lang.Object} containing local data about the drag and
19576      * drop operation. This Object is put into every DragEvent object sent by the system during the
19577      * current drag.
19578      * <p>
19579      * myLocalState is a lightweight mechanism for the sending information from the dragged View
19580      * to the target Views. For example, it can contain flags that differentiate between a
19581      * a copy operation and a move operation.
19582      * </p>
19583      * @param flags Flags that control the drag and drop operation. No flags are currently defined,
19584      * so the parameter should be set to 0.
19585      * @return {@code true} if the method completes successfully, or
19586      * {@code false} if it fails anywhere. Returning {@code false} means the system was unable to
19587      * do a drag, and so no drag operation is in progress.
19588      */
19589     public final boolean startDrag(ClipData data, DragShadowBuilder shadowBuilder,
19590             Object myLocalState, int flags) {
19591         if (ViewDebug.DEBUG_DRAG) {
19592             Log.d(VIEW_LOG_TAG, "startDrag: data=" + data + " flags=" + flags);
19593         }
19594         boolean okay = false;
19595 
19596         Point shadowSize = new Point();
19597         Point shadowTouchPoint = new Point();
19598         shadowBuilder.onProvideShadowMetrics(shadowSize, shadowTouchPoint);
19599 
19600         if ((shadowSize.x < 0) || (shadowSize.y < 0) ||
19601                 (shadowTouchPoint.x < 0) || (shadowTouchPoint.y < 0)) {
19602             throw new IllegalStateException("Drag shadow dimensions must not be negative");
19603         }
19604 
19605         if (ViewDebug.DEBUG_DRAG) {
19606             Log.d(VIEW_LOG_TAG, "drag shadow: width=" + shadowSize.x + " height=" + shadowSize.y
19607                     + " shadowX=" + shadowTouchPoint.x + " shadowY=" + shadowTouchPoint.y);
19608         }
19609         Surface surface = new Surface();
19610         try {
19611             IBinder token = mAttachInfo.mSession.prepareDrag(mAttachInfo.mWindow,
19612                     flags, shadowSize.x, shadowSize.y, surface);
19613             if (ViewDebug.DEBUG_DRAG) Log.d(VIEW_LOG_TAG, "prepareDrag returned token=" + token
19614                     + " surface=" + surface);
19615             if (token != null) {
19616                 Canvas canvas = surface.lockCanvas(null);
19617                 try {
19618                     canvas.drawColor(0, PorterDuff.Mode.CLEAR);
19619                     shadowBuilder.onDrawShadow(canvas);
19620                 } finally {
19621                     surface.unlockCanvasAndPost(canvas);
19622                 }
19623 
19624                 final ViewRootImpl root = getViewRootImpl();
19625 
19626                 // Cache the local state object for delivery with DragEvents
19627                 root.setLocalDragState(myLocalState);
19628 
19629                 // repurpose 'shadowSize' for the last touch point
19630                 root.getLastTouchPoint(shadowSize);
19631 
19632                 okay = mAttachInfo.mSession.performDrag(mAttachInfo.mWindow, token,
19633                         shadowSize.x, shadowSize.y,
19634                         shadowTouchPoint.x, shadowTouchPoint.y, data);
19635                 if (ViewDebug.DEBUG_DRAG) Log.d(VIEW_LOG_TAG, "performDrag returned " + okay);
19636 
19637                 // Off and running!  Release our local surface instance; the drag
19638                 // shadow surface is now managed by the system process.
19639                 surface.release();
19640             }
19641         } catch (Exception e) {
19642             Log.e(VIEW_LOG_TAG, "Unable to initiate drag", e);
19643             surface.destroy();
19644         }
19645 
19646         return okay;
19647     }
19648 
19649     /**
19650      * Handles drag events sent by the system following a call to
19651      * {@link android.view.View#startDrag(ClipData,DragShadowBuilder,Object,int) startDrag()}.
19652      *<p>
19653      * When the system calls this method, it passes a
19654      * {@link android.view.DragEvent} object. A call to
19655      * {@link android.view.DragEvent#getAction()} returns one of the action type constants defined
19656      * in DragEvent. The method uses these to determine what is happening in the drag and drop
19657      * operation.
19658      * @param event The {@link android.view.DragEvent} sent by the system.
19659      * The {@link android.view.DragEvent#getAction()} method returns an action type constant defined
19660      * in DragEvent, indicating the type of drag event represented by this object.
19661      * @return {@code true} if the method was successful, otherwise {@code false}.
19662      * <p>
19663      *  The method should return {@code true} in response to an action type of
19664      *  {@link android.view.DragEvent#ACTION_DRAG_STARTED} to receive drag events for the current
19665      *  operation.
19666      * </p>
19667      * <p>
19668      *  The method should also return {@code true} in response to an action type of
19669      *  {@link android.view.DragEvent#ACTION_DROP} if it consumed the drop, or
19670      *  {@code false} if it didn't.
19671      * </p>
19672      */
19673     public boolean onDragEvent(DragEvent event) {
19674         return false;
19675     }
19676 
19677     /**
19678      * Detects if this View is enabled and has a drag event listener.
19679      * If both are true, then it calls the drag event listener with the
19680      * {@link android.view.DragEvent} it received. If the drag event listener returns
19681      * {@code true}, then dispatchDragEvent() returns {@code true}.
19682      * <p>
19683      * For all other cases, the method calls the
19684      * {@link android.view.View#onDragEvent(DragEvent) onDragEvent()} drag event handler
19685      * method and returns its result.
19686      * </p>
19687      * <p>
19688      * This ensures that a drag event is always consumed, even if the View does not have a drag
19689      * event listener. However, if the View has a listener and the listener returns true, then
19690      * onDragEvent() is not called.
19691      * </p>
19692      */
19693     public boolean dispatchDragEvent(DragEvent event) {
19694         ListenerInfo li = mListenerInfo;
19695         //noinspection SimplifiableIfStatement
19696         if (li != null && li.mOnDragListener != null && (mViewFlags & ENABLED_MASK) == ENABLED
19697                 && li.mOnDragListener.onDrag(this, event)) {
19698             return true;
19699         }
19700         return onDragEvent(event);
19701     }
19702 
19703     boolean canAcceptDrag() {
19704         return (mPrivateFlags2 & PFLAG2_DRAG_CAN_ACCEPT) != 0;
19705     }
19706 
19707     /**
19708      * This needs to be a better API (NOT ON VIEW) before it is exposed.  If
19709      * it is ever exposed at all.
19710      * @hide
19711      */
19712     public void onCloseSystemDialogs(String reason) {
19713     }
19714 
19715     /**
19716      * Given a Drawable whose bounds have been set to draw into this view,
19717      * update a Region being computed for
19718      * {@link #gatherTransparentRegion(android.graphics.Region)} so
19719      * that any non-transparent parts of the Drawable are removed from the
19720      * given transparent region.
19721      *
19722      * @param dr The Drawable whose transparency is to be applied to the region.
19723      * @param region A Region holding the current transparency information,
19724      * where any parts of the region that are set are considered to be
19725      * transparent.  On return, this region will be modified to have the
19726      * transparency information reduced by the corresponding parts of the
19727      * Drawable that are not transparent.
19728      * {@hide}
19729      */
19730     public void applyDrawableToTransparentRegion(Drawable dr, Region region) {
19731         if (DBG) {
19732             Log.i("View", "Getting transparent region for: " + this);
19733         }
19734         final Region r = dr.getTransparentRegion();
19735         final Rect db = dr.getBounds();
19736         final AttachInfo attachInfo = mAttachInfo;
19737         if (r != null && attachInfo != null) {
19738             final int w = getRight()-getLeft();
19739             final int h = getBottom()-getTop();
19740             if (db.left > 0) {
19741                 //Log.i("VIEW", "Drawable left " + db.left + " > view 0");
19742                 r.op(0, 0, db.left, h, Region.Op.UNION);
19743             }
19744             if (db.right < w) {
19745                 //Log.i("VIEW", "Drawable right " + db.right + " < view " + w);
19746                 r.op(db.right, 0, w, h, Region.Op.UNION);
19747             }
19748             if (db.top > 0) {
19749                 //Log.i("VIEW", "Drawable top " + db.top + " > view 0");
19750                 r.op(0, 0, w, db.top, Region.Op.UNION);
19751             }
19752             if (db.bottom < h) {
19753                 //Log.i("VIEW", "Drawable bottom " + db.bottom + " < view " + h);
19754                 r.op(0, db.bottom, w, h, Region.Op.UNION);
19755             }
19756             final int[] location = attachInfo.mTransparentLocation;
19757             getLocationInWindow(location);
19758             r.translate(location[0], location[1]);
19759             region.op(r, Region.Op.INTERSECT);
19760         } else {
19761             region.op(db, Region.Op.DIFFERENCE);
19762         }
19763     }
19764 
19765     private void checkForLongClick(int delayOffset) {
19766         if ((mViewFlags & LONG_CLICKABLE) == LONG_CLICKABLE) {
19767             mHasPerformedLongPress = false;
19768 
19769             if (mPendingCheckForLongPress == null) {
19770                 mPendingCheckForLongPress = new CheckForLongPress();
19771             }
19772             mPendingCheckForLongPress.rememberWindowAttachCount();
19773             postDelayed(mPendingCheckForLongPress,
19774                     ViewConfiguration.getLongPressTimeout() - delayOffset);
19775         }
19776     }
19777 
19778     /**
19779      * Inflate a view from an XML resource.  This convenience method wraps the {@link
19780      * LayoutInflater} class, which provides a full range of options for view inflation.
19781      *
19782      * @param context The Context object for your activity or application.
19783      * @param resource The resource ID to inflate
19784      * @param root A view group that will be the parent.  Used to properly inflate the
19785      * layout_* parameters.
19786      * @see LayoutInflater
19787      */
19788     public static View inflate(Context context, @LayoutRes int resource, ViewGroup root) {
19789         LayoutInflater factory = LayoutInflater.from(context);
19790         return factory.inflate(resource, root);
19791     }
19792 
19793     /**
19794      * Scroll the view with standard behavior for scrolling beyond the normal
19795      * content boundaries. Views that call this method should override
19796      * {@link #onOverScrolled(int, int, boolean, boolean)} to respond to the
19797      * results of an over-scroll operation.
19798      *
19799      * Views can use this method to handle any touch or fling-based scrolling.
19800      *
19801      * @param deltaX Change in X in pixels
19802      * @param deltaY Change in Y in pixels
19803      * @param scrollX Current X scroll value in pixels before applying deltaX
19804      * @param scrollY Current Y scroll value in pixels before applying deltaY
19805      * @param scrollRangeX Maximum content scroll range along the X axis
19806      * @param scrollRangeY Maximum content scroll range along the Y axis
19807      * @param maxOverScrollX Number of pixels to overscroll by in either direction
19808      *          along the X axis.
19809      * @param maxOverScrollY Number of pixels to overscroll by in either direction
19810      *          along the Y axis.
19811      * @param isTouchEvent true if this scroll operation is the result of a touch event.
19812      * @return true if scrolling was clamped to an over-scroll boundary along either
19813      *          axis, false otherwise.
19814      */
19815     @SuppressWarnings({"UnusedParameters"})
19816     protected boolean overScrollBy(int deltaX, int deltaY,
19817             int scrollX, int scrollY,
19818             int scrollRangeX, int scrollRangeY,
19819             int maxOverScrollX, int maxOverScrollY,
19820             boolean isTouchEvent) {
19821         final int overScrollMode = mOverScrollMode;
19822         final boolean canScrollHorizontal =
19823                 computeHorizontalScrollRange() > computeHorizontalScrollExtent();
19824         final boolean canScrollVertical =
19825                 computeVerticalScrollRange() > computeVerticalScrollExtent();
19826         final boolean overScrollHorizontal = overScrollMode == OVER_SCROLL_ALWAYS ||
19827                 (overScrollMode == OVER_SCROLL_IF_CONTENT_SCROLLS && canScrollHorizontal);
19828         final boolean overScrollVertical = overScrollMode == OVER_SCROLL_ALWAYS ||
19829                 (overScrollMode == OVER_SCROLL_IF_CONTENT_SCROLLS && canScrollVertical);
19830 
19831         int newScrollX = scrollX + deltaX;
19832         if (!overScrollHorizontal) {
19833             maxOverScrollX = 0;
19834         }
19835 
19836         int newScrollY = scrollY + deltaY;
19837         if (!overScrollVertical) {
19838             maxOverScrollY = 0;
19839         }
19840 
19841         // Clamp values if at the limits and record
19842         final int left = -maxOverScrollX;
19843         final int right = maxOverScrollX + scrollRangeX;
19844         final int top = -maxOverScrollY;
19845         final int bottom = maxOverScrollY + scrollRangeY;
19846 
19847         boolean clampedX = false;
19848         if (newScrollX > right) {
19849             newScrollX = right;
19850             clampedX = true;
19851         } else if (newScrollX < left) {
19852             newScrollX = left;
19853             clampedX = true;
19854         }
19855 
19856         boolean clampedY = false;
19857         if (newScrollY > bottom) {
19858             newScrollY = bottom;
19859             clampedY = true;
19860         } else if (newScrollY < top) {
19861             newScrollY = top;
19862             clampedY = true;
19863         }
19864 
19865         onOverScrolled(newScrollX, newScrollY, clampedX, clampedY);
19866 
19867         return clampedX || clampedY;
19868     }
19869 
19870     /**
19871      * Called by {@link #overScrollBy(int, int, int, int, int, int, int, int, boolean)} to
19872      * respond to the results of an over-scroll operation.
19873      *
19874      * @param scrollX New X scroll value in pixels
19875      * @param scrollY New Y scroll value in pixels
19876      * @param clampedX True if scrollX was clamped to an over-scroll boundary
19877      * @param clampedY True if scrollY was clamped to an over-scroll boundary
19878      */
19879     protected void onOverScrolled(int scrollX, int scrollY,
19880             boolean clampedX, boolean clampedY) {
19881         // Intentionally empty.
19882     }
19883 
19884     /**
19885      * Returns the over-scroll mode for this view. The result will be
19886      * one of {@link #OVER_SCROLL_ALWAYS} (default), {@link #OVER_SCROLL_IF_CONTENT_SCROLLS}
19887      * (allow over-scrolling only if the view content is larger than the container),
19888      * or {@link #OVER_SCROLL_NEVER}.
19889      *
19890      * @return This view's over-scroll mode.
19891      */
19892     public int getOverScrollMode() {
19893         return mOverScrollMode;
19894     }
19895 
19896     /**
19897      * Set the over-scroll mode for this view. Valid over-scroll modes are
19898      * {@link #OVER_SCROLL_ALWAYS} (default), {@link #OVER_SCROLL_IF_CONTENT_SCROLLS}
19899      * (allow over-scrolling only if the view content is larger than the container),
19900      * or {@link #OVER_SCROLL_NEVER}.
19901      *
19902      * Setting the over-scroll mode of a view will have an effect only if the
19903      * view is capable of scrolling.
19904      *
19905      * @param overScrollMode The new over-scroll mode for this view.
19906      */
19907     public void setOverScrollMode(int overScrollMode) {
19908         if (overScrollMode != OVER_SCROLL_ALWAYS &&
19909                 overScrollMode != OVER_SCROLL_IF_CONTENT_SCROLLS &&
19910                 overScrollMode != OVER_SCROLL_NEVER) {
19911             throw new IllegalArgumentException("Invalid overscroll mode " + overScrollMode);
19912         }
19913         mOverScrollMode = overScrollMode;
19914     }
19915 
19916     /**
19917      * Enable or disable nested scrolling for this view.
19918      *
19919      * <p>If this property is set to true the view will be permitted to initiate nested
19920      * scrolling operations with a compatible parent view in the current hierarchy. If this
19921      * view does not implement nested scrolling this will have no effect. Disabling nested scrolling
19922      * while a nested scroll is in progress has the effect of {@link #stopNestedScroll() stopping}
19923      * the nested scroll.</p>
19924      *
19925      * @param enabled true to enable nested scrolling, false to disable
19926      *
19927      * @see #isNestedScrollingEnabled()
19928      */
19929     public void setNestedScrollingEnabled(boolean enabled) {
19930         if (enabled) {
19931             mPrivateFlags3 |= PFLAG3_NESTED_SCROLLING_ENABLED;
19932         } else {
19933             stopNestedScroll();
19934             mPrivateFlags3 &= ~PFLAG3_NESTED_SCROLLING_ENABLED;
19935         }
19936     }
19937 
19938     /**
19939      * Returns true if nested scrolling is enabled for this view.
19940      *
19941      * <p>If nested scrolling is enabled and this View class implementation supports it,
19942      * this view will act as a nested scrolling child view when applicable, forwarding data
19943      * about the scroll operation in progress to a compatible and cooperating nested scrolling
19944      * parent.</p>
19945      *
19946      * @return true if nested scrolling is enabled
19947      *
19948      * @see #setNestedScrollingEnabled(boolean)
19949      */
19950     public boolean isNestedScrollingEnabled() {
19951         return (mPrivateFlags3 & PFLAG3_NESTED_SCROLLING_ENABLED) ==
19952                 PFLAG3_NESTED_SCROLLING_ENABLED;
19953     }
19954 
19955     /**
19956      * Begin a nestable scroll operation along the given axes.
19957      *
19958      * <p>A view starting a nested scroll promises to abide by the following contract:</p>
19959      *
19960      * <p>The view will call startNestedScroll upon initiating a scroll operation. In the case
19961      * of a touch scroll this corresponds to the initial {@link MotionEvent#ACTION_DOWN}.
19962      * In the case of touch scrolling the nested scroll will be terminated automatically in
19963      * the same manner as {@link ViewParent#requestDisallowInterceptTouchEvent(boolean)}.
19964      * In the event of programmatic scrolling the caller must explicitly call
19965      * {@link #stopNestedScroll()} to indicate the end of the nested scroll.</p>
19966      *
19967      * <p>If <code>startNestedScroll</code> returns true, a cooperative parent was found.
19968      * If it returns false the caller may ignore the rest of this contract until the next scroll.
19969      * Calling startNestedScroll while a nested scroll is already in progress will return true.</p>
19970      *
19971      * <p>At each incremental step of the scroll the caller should invoke
19972      * {@link #dispatchNestedPreScroll(int, int, int[], int[]) dispatchNestedPreScroll}
19973      * once it has calculated the requested scrolling delta. If it returns true the nested scrolling
19974      * parent at least partially consumed the scroll and the caller should adjust the amount it
19975      * scrolls by.</p>
19976      *
19977      * <p>After applying the remainder of the scroll delta the caller should invoke
19978      * {@link #dispatchNestedScroll(int, int, int, int, int[]) dispatchNestedScroll}, passing
19979      * both the delta consumed and the delta unconsumed. A nested scrolling parent may treat
19980      * these values differently. See {@link ViewParent#onNestedScroll(View, int, int, int, int)}.
19981      * </p>
19982      *
19983      * @param axes Flags consisting of a combination of {@link #SCROLL_AXIS_HORIZONTAL} and/or
19984      *             {@link #SCROLL_AXIS_VERTICAL}.
19985      * @return true if a cooperative parent was found and nested scrolling has been enabled for
19986      *         the current gesture.
19987      *
19988      * @see #stopNestedScroll()
19989      * @see #dispatchNestedPreScroll(int, int, int[], int[])
19990      * @see #dispatchNestedScroll(int, int, int, int, int[])
19991      */
19992     public boolean startNestedScroll(int axes) {
19993         if (hasNestedScrollingParent()) {
19994             // Already in progress
19995             return true;
19996         }
19997         if (isNestedScrollingEnabled()) {
19998             ViewParent p = getParent();
19999             View child = this;
20000             while (p != null) {
20001                 try {
20002                     if (p.onStartNestedScroll(child, this, axes)) {
20003                         mNestedScrollingParent = p;
20004                         p.onNestedScrollAccepted(child, this, axes);
20005                         return true;
20006                     }
20007                 } catch (AbstractMethodError e) {
20008                     Log.e(VIEW_LOG_TAG, "ViewParent " + p + " does not implement interface " +
20009                             "method onStartNestedScroll", e);
20010                     // Allow the search upward to continue
20011                 }
20012                 if (p instanceof View) {
20013                     child = (View) p;
20014                 }
20015                 p = p.getParent();
20016             }
20017         }
20018         return false;
20019     }
20020 
20021     /**
20022      * Stop a nested scroll in progress.
20023      *
20024      * <p>Calling this method when a nested scroll is not currently in progress is harmless.</p>
20025      *
20026      * @see #startNestedScroll(int)
20027      */
20028     public void stopNestedScroll() {
20029         if (mNestedScrollingParent != null) {
20030             mNestedScrollingParent.onStopNestedScroll(this);
20031             mNestedScrollingParent = null;
20032         }
20033     }
20034 
20035     /**
20036      * Returns true if this view has a nested scrolling parent.
20037      *
20038      * <p>The presence of a nested scrolling parent indicates that this view has initiated
20039      * a nested scroll and it was accepted by an ancestor view further up the view hierarchy.</p>
20040      *
20041      * @return whether this view has a nested scrolling parent
20042      */
20043     public boolean hasNestedScrollingParent() {
20044         return mNestedScrollingParent != null;
20045     }
20046 
20047     /**
20048      * Dispatch one step of a nested scroll in progress.
20049      *
20050      * <p>Implementations of views that support nested scrolling should call this to report
20051      * info about a scroll in progress to the current nested scrolling parent. If a nested scroll
20052      * is not currently in progress or nested scrolling is not
20053      * {@link #isNestedScrollingEnabled() enabled} for this view this method does nothing.</p>
20054      *
20055      * <p>Compatible View implementations should also call
20056      * {@link #dispatchNestedPreScroll(int, int, int[], int[]) dispatchNestedPreScroll} before
20057      * consuming a component of the scroll event themselves.</p>
20058      *
20059      * @param dxConsumed Horizontal distance in pixels consumed by this view during this scroll step
20060      * @param dyConsumed Vertical distance in pixels consumed by this view during this scroll step
20061      * @param dxUnconsumed Horizontal scroll distance in pixels not consumed by this view
20062      * @param dyUnconsumed Horizontal scroll distance in pixels not consumed by this view
20063      * @param offsetInWindow Optional. If not null, on return this will contain the offset
20064      *                       in local view coordinates of this view from before this operation
20065      *                       to after it completes. View implementations may use this to adjust
20066      *                       expected input coordinate tracking.
20067      * @return true if the event was dispatched, false if it could not be dispatched.
20068      * @see #dispatchNestedPreScroll(int, int, int[], int[])
20069      */
20070     public boolean dispatchNestedScroll(int dxConsumed, int dyConsumed,
20071             int dxUnconsumed, int dyUnconsumed, @Nullable @Size(2) int[] offsetInWindow) {
20072         if (isNestedScrollingEnabled() && mNestedScrollingParent != null) {
20073             if (dxConsumed != 0 || dyConsumed != 0 || dxUnconsumed != 0 || dyUnconsumed != 0) {
20074                 int startX = 0;
20075                 int startY = 0;
20076                 if (offsetInWindow != null) {
20077                     getLocationInWindow(offsetInWindow);
20078                     startX = offsetInWindow[0];
20079                     startY = offsetInWindow[1];
20080                 }
20081 
20082                 mNestedScrollingParent.onNestedScroll(this, dxConsumed, dyConsumed,
20083                         dxUnconsumed, dyUnconsumed);
20084 
20085                 if (offsetInWindow != null) {
20086                     getLocationInWindow(offsetInWindow);
20087                     offsetInWindow[0] -= startX;
20088                     offsetInWindow[1] -= startY;
20089                 }
20090                 return true;
20091             } else if (offsetInWindow != null) {
20092                 // No motion, no dispatch. Keep offsetInWindow up to date.
20093                 offsetInWindow[0] = 0;
20094                 offsetInWindow[1] = 0;
20095             }
20096         }
20097         return false;
20098     }
20099 
20100     /**
20101      * Dispatch one step of a nested scroll in progress before this view consumes any portion of it.
20102      *
20103      * <p>Nested pre-scroll events are to nested scroll events what touch intercept is to touch.
20104      * <code>dispatchNestedPreScroll</code> offers an opportunity for the parent view in a nested
20105      * scrolling operation to consume some or all of the scroll operation before the child view
20106      * consumes it.</p>
20107      *
20108      * @param dx Horizontal scroll distance in pixels
20109      * @param dy Vertical scroll distance in pixels
20110      * @param consumed Output. If not null, consumed[0] will contain the consumed component of dx
20111      *                 and consumed[1] the consumed dy.
20112      * @param offsetInWindow Optional. If not null, on return this will contain the offset
20113      *                       in local view coordinates of this view from before this operation
20114      *                       to after it completes. View implementations may use this to adjust
20115      *                       expected input coordinate tracking.
20116      * @return true if the parent consumed some or all of the scroll delta
20117      * @see #dispatchNestedScroll(int, int, int, int, int[])
20118      */
20119     public boolean dispatchNestedPreScroll(int dx, int dy,
20120             @Nullable @Size(2) int[] consumed, @Nullable @Size(2) int[] offsetInWindow) {
20121         if (isNestedScrollingEnabled() && mNestedScrollingParent != null) {
20122             if (dx != 0 || dy != 0) {
20123                 int startX = 0;
20124                 int startY = 0;
20125                 if (offsetInWindow != null) {
20126                     getLocationInWindow(offsetInWindow);
20127                     startX = offsetInWindow[0];
20128                     startY = offsetInWindow[1];
20129                 }
20130 
20131                 if (consumed == null) {
20132                     if (mTempNestedScrollConsumed == null) {
20133                         mTempNestedScrollConsumed = new int[2];
20134                     }
20135                     consumed = mTempNestedScrollConsumed;
20136                 }
20137                 consumed[0] = 0;
20138                 consumed[1] = 0;
20139                 mNestedScrollingParent.onNestedPreScroll(this, dx, dy, consumed);
20140 
20141                 if (offsetInWindow != null) {
20142                     getLocationInWindow(offsetInWindow);
20143                     offsetInWindow[0] -= startX;
20144                     offsetInWindow[1] -= startY;
20145                 }
20146                 return consumed[0] != 0 || consumed[1] != 0;
20147             } else if (offsetInWindow != null) {
20148                 offsetInWindow[0] = 0;
20149                 offsetInWindow[1] = 0;
20150             }
20151         }
20152         return false;
20153     }
20154 
20155     /**
20156      * Dispatch a fling to a nested scrolling parent.
20157      *
20158      * <p>This method should be used to indicate that a nested scrolling child has detected
20159      * suitable conditions for a fling. Generally this means that a touch scroll has ended with a
20160      * {@link VelocityTracker velocity} in the direction of scrolling that meets or exceeds
20161      * the {@link ViewConfiguration#getScaledMinimumFlingVelocity() minimum fling velocity}
20162      * along a scrollable axis.</p>
20163      *
20164      * <p>If a nested scrolling child view would normally fling but it is at the edge of
20165      * its own content, it can use this method to delegate the fling to its nested scrolling
20166      * parent instead. The parent may optionally consume the fling or observe a child fling.</p>
20167      *
20168      * @param velocityX Horizontal fling velocity in pixels per second
20169      * @param velocityY Vertical fling velocity in pixels per second
20170      * @param consumed true if the child consumed the fling, false otherwise
20171      * @return true if the nested scrolling parent consumed or otherwise reacted to the fling
20172      */
20173     public boolean dispatchNestedFling(float velocityX, float velocityY, boolean consumed) {
20174         if (isNestedScrollingEnabled() && mNestedScrollingParent != null) {
20175             return mNestedScrollingParent.onNestedFling(this, velocityX, velocityY, consumed);
20176         }
20177         return false;
20178     }
20179 
20180     /**
20181      * Dispatch a fling to a nested scrolling parent before it is processed by this view.
20182      *
20183      * <p>Nested pre-fling events are to nested fling events what touch intercept is to touch
20184      * and what nested pre-scroll is to nested scroll. <code>dispatchNestedPreFling</code>
20185      * offsets an opportunity for the parent view in a nested fling to fully consume the fling
20186      * before the child view consumes it. If this method returns <code>true</code>, a nested
20187      * parent view consumed the fling and this view should not scroll as a result.</p>
20188      *
20189      * <p>For a better user experience, only one view in a nested scrolling chain should consume
20190      * the fling at a time. If a parent view consumed the fling this method will return false.
20191      * Custom view implementations should account for this in two ways:</p>
20192      *
20193      * <ul>
20194      *     <li>If a custom view is paged and needs to settle to a fixed page-point, do not
20195      *     call <code>dispatchNestedPreFling</code>; consume the fling and settle to a valid
20196      *     position regardless.</li>
20197      *     <li>If a nested parent does consume the fling, this view should not scroll at all,
20198      *     even to settle back to a valid idle position.</li>
20199      * </ul>
20200      *
20201      * <p>Views should also not offer fling velocities to nested parent views along an axis
20202      * where scrolling is not currently supported; a {@link android.widget.ScrollView ScrollView}
20203      * should not offer a horizontal fling velocity to its parents since scrolling along that
20204      * axis is not permitted and carrying velocity along that motion does not make sense.</p>
20205      *
20206      * @param velocityX Horizontal fling velocity in pixels per second
20207      * @param velocityY Vertical fling velocity in pixels per second
20208      * @return true if a nested scrolling parent consumed the fling
20209      */
20210     public boolean dispatchNestedPreFling(float velocityX, float velocityY) {
20211         if (isNestedScrollingEnabled() && mNestedScrollingParent != null) {
20212             return mNestedScrollingParent.onNestedPreFling(this, velocityX, velocityY);
20213         }
20214         return false;
20215     }
20216 
20217     /**
20218      * Gets a scale factor that determines the distance the view should scroll
20219      * vertically in response to {@link MotionEvent#ACTION_SCROLL}.
20220      * @return The vertical scroll scale factor.
20221      * @hide
20222      */
20223     protected float getVerticalScrollFactor() {
20224         if (mVerticalScrollFactor == 0) {
20225             TypedValue outValue = new TypedValue();
20226             if (!mContext.getTheme().resolveAttribute(
20227                     com.android.internal.R.attr.listPreferredItemHeight, outValue, true)) {
20228                 throw new IllegalStateException(
20229                         "Expected theme to define listPreferredItemHeight.");
20230             }
20231             mVerticalScrollFactor = outValue.getDimension(
20232                     mContext.getResources().getDisplayMetrics());
20233         }
20234         return mVerticalScrollFactor;
20235     }
20236 
20237     /**
20238      * Gets a scale factor that determines the distance the view should scroll
20239      * horizontally in response to {@link MotionEvent#ACTION_SCROLL}.
20240      * @return The horizontal scroll scale factor.
20241      * @hide
20242      */
20243     protected float getHorizontalScrollFactor() {
20244         // TODO: Should use something else.
20245         return getVerticalScrollFactor();
20246     }
20247 
20248     /**
20249      * Return the value specifying the text direction or policy that was set with
20250      * {@link #setTextDirection(int)}.
20251      *
20252      * @return the defined text direction. It can be one of:
20253      *
20254      * {@link #TEXT_DIRECTION_INHERIT},
20255      * {@link #TEXT_DIRECTION_FIRST_STRONG},
20256      * {@link #TEXT_DIRECTION_ANY_RTL},
20257      * {@link #TEXT_DIRECTION_LTR},
20258      * {@link #TEXT_DIRECTION_RTL},
20259      * {@link #TEXT_DIRECTION_LOCALE},
20260      * {@link #TEXT_DIRECTION_FIRST_STRONG_LTR},
20261      * {@link #TEXT_DIRECTION_FIRST_STRONG_RTL}
20262      *
20263      * @attr ref android.R.styleable#View_textDirection
20264      *
20265      * @hide
20266      */
20267     @ViewDebug.ExportedProperty(category = "text", mapping = {
20268             @ViewDebug.IntToString(from = TEXT_DIRECTION_INHERIT, to = "INHERIT"),
20269             @ViewDebug.IntToString(from = TEXT_DIRECTION_FIRST_STRONG, to = "FIRST_STRONG"),
20270             @ViewDebug.IntToString(from = TEXT_DIRECTION_ANY_RTL, to = "ANY_RTL"),
20271             @ViewDebug.IntToString(from = TEXT_DIRECTION_LTR, to = "LTR"),
20272             @ViewDebug.IntToString(from = TEXT_DIRECTION_RTL, to = "RTL"),
20273             @ViewDebug.IntToString(from = TEXT_DIRECTION_LOCALE, to = "LOCALE"),
20274             @ViewDebug.IntToString(from = TEXT_DIRECTION_FIRST_STRONG_LTR, to = "FIRST_STRONG_LTR"),
20275             @ViewDebug.IntToString(from = TEXT_DIRECTION_FIRST_STRONG_RTL, to = "FIRST_STRONG_RTL")
20276     })
20277     public int getRawTextDirection() {
20278         return (mPrivateFlags2 & PFLAG2_TEXT_DIRECTION_MASK) >> PFLAG2_TEXT_DIRECTION_MASK_SHIFT;
20279     }
20280 
20281     /**
20282      * Set the text direction.
20283      *
20284      * @param textDirection the direction to set. Should be one of:
20285      *
20286      * {@link #TEXT_DIRECTION_INHERIT},
20287      * {@link #TEXT_DIRECTION_FIRST_STRONG},
20288      * {@link #TEXT_DIRECTION_ANY_RTL},
20289      * {@link #TEXT_DIRECTION_LTR},
20290      * {@link #TEXT_DIRECTION_RTL},
20291      * {@link #TEXT_DIRECTION_LOCALE}
20292      * {@link #TEXT_DIRECTION_FIRST_STRONG_LTR},
20293      * {@link #TEXT_DIRECTION_FIRST_STRONG_RTL},
20294      *
20295      * Resolution will be done if the value is set to TEXT_DIRECTION_INHERIT. The resolution
20296      * proceeds up the parent chain of the view to get the value. If there is no parent, then it will
20297      * return the default {@link #TEXT_DIRECTION_FIRST_STRONG}.
20298      *
20299      * @attr ref android.R.styleable#View_textDirection
20300      */
20301     public void setTextDirection(int textDirection) {
20302         if (getRawTextDirection() != textDirection) {
20303             // Reset the current text direction and the resolved one
20304             mPrivateFlags2 &= ~PFLAG2_TEXT_DIRECTION_MASK;
20305             resetResolvedTextDirection();
20306             // Set the new text direction
20307             mPrivateFlags2 |= ((textDirection << PFLAG2_TEXT_DIRECTION_MASK_SHIFT) & PFLAG2_TEXT_DIRECTION_MASK);
20308             // Do resolution
20309             resolveTextDirection();
20310             // Notify change
20311             onRtlPropertiesChanged(getLayoutDirection());
20312             // Refresh
20313             requestLayout();
20314             invalidate(true);
20315         }
20316     }
20317 
20318     /**
20319      * Return the resolved text direction.
20320      *
20321      * @return the resolved text direction. Returns one of:
20322      *
20323      * {@link #TEXT_DIRECTION_FIRST_STRONG},
20324      * {@link #TEXT_DIRECTION_ANY_RTL},
20325      * {@link #TEXT_DIRECTION_LTR},
20326      * {@link #TEXT_DIRECTION_RTL},
20327      * {@link #TEXT_DIRECTION_LOCALE},
20328      * {@link #TEXT_DIRECTION_FIRST_STRONG_LTR},
20329      * {@link #TEXT_DIRECTION_FIRST_STRONG_RTL}
20330      *
20331      * @attr ref android.R.styleable#View_textDirection
20332      */
20333     @ViewDebug.ExportedProperty(category = "text", mapping = {
20334             @ViewDebug.IntToString(from = TEXT_DIRECTION_INHERIT, to = "INHERIT"),
20335             @ViewDebug.IntToString(from = TEXT_DIRECTION_FIRST_STRONG, to = "FIRST_STRONG"),
20336             @ViewDebug.IntToString(from = TEXT_DIRECTION_ANY_RTL, to = "ANY_RTL"),
20337             @ViewDebug.IntToString(from = TEXT_DIRECTION_LTR, to = "LTR"),
20338             @ViewDebug.IntToString(from = TEXT_DIRECTION_RTL, to = "RTL"),
20339             @ViewDebug.IntToString(from = TEXT_DIRECTION_LOCALE, to = "LOCALE"),
20340             @ViewDebug.IntToString(from = TEXT_DIRECTION_FIRST_STRONG_LTR, to = "FIRST_STRONG_LTR"),
20341             @ViewDebug.IntToString(from = TEXT_DIRECTION_FIRST_STRONG_RTL, to = "FIRST_STRONG_RTL")
20342     })
20343     public int getTextDirection() {
20344         return (mPrivateFlags2 & PFLAG2_TEXT_DIRECTION_RESOLVED_MASK) >> PFLAG2_TEXT_DIRECTION_RESOLVED_MASK_SHIFT;
20345     }
20346 
20347     /**
20348      * Resolve the text direction.
20349      *
20350      * @return true if resolution has been done, false otherwise.
20351      *
20352      * @hide
20353      */
20354     public boolean resolveTextDirection() {
20355         // Reset any previous text direction resolution
20356         mPrivateFlags2 &= ~(PFLAG2_TEXT_DIRECTION_RESOLVED | PFLAG2_TEXT_DIRECTION_RESOLVED_MASK);
20357 
20358         if (hasRtlSupport()) {
20359             // Set resolved text direction flag depending on text direction flag
20360             final int textDirection = getRawTextDirection();
20361             switch(textDirection) {
20362                 case TEXT_DIRECTION_INHERIT:
20363                     if (!canResolveTextDirection()) {
20364                         // We cannot do the resolution if there is no parent, so use the default one
20365                         mPrivateFlags2 |= PFLAG2_TEXT_DIRECTION_RESOLVED_DEFAULT;
20366                         // Resolution will need to happen again later
20367                         return false;
20368                     }
20369 
20370                     // Parent has not yet resolved, so we still return the default
20371                     try {
20372                         if (!mParent.isTextDirectionResolved()) {
20373                             mPrivateFlags2 |= PFLAG2_TEXT_DIRECTION_RESOLVED_DEFAULT;
20374                             // Resolution will need to happen again later
20375                             return false;
20376                         }
20377                     } catch (AbstractMethodError e) {
20378                         Log.e(VIEW_LOG_TAG, mParent.getClass().getSimpleName() +
20379                                 " does not fully implement ViewParent", e);
20380                         mPrivateFlags2 |= PFLAG2_TEXT_DIRECTION_RESOLVED |
20381                                 PFLAG2_TEXT_DIRECTION_RESOLVED_DEFAULT;
20382                         return true;
20383                     }
20384 
20385                     // Set current resolved direction to the same value as the parent's one
20386                     int parentResolvedDirection;
20387                     try {
20388                         parentResolvedDirection = mParent.getTextDirection();
20389                     } catch (AbstractMethodError e) {
20390                         Log.e(VIEW_LOG_TAG, mParent.getClass().getSimpleName() +
20391                                 " does not fully implement ViewParent", e);
20392                         parentResolvedDirection = TEXT_DIRECTION_LTR;
20393                     }
20394                     switch (parentResolvedDirection) {
20395                         case TEXT_DIRECTION_FIRST_STRONG:
20396                         case TEXT_DIRECTION_ANY_RTL:
20397                         case TEXT_DIRECTION_LTR:
20398                         case TEXT_DIRECTION_RTL:
20399                         case TEXT_DIRECTION_LOCALE:
20400                         case TEXT_DIRECTION_FIRST_STRONG_LTR:
20401                         case TEXT_DIRECTION_FIRST_STRONG_RTL:
20402                             mPrivateFlags2 |=
20403                                     (parentResolvedDirection << PFLAG2_TEXT_DIRECTION_RESOLVED_MASK_SHIFT);
20404                             break;
20405                         default:
20406                             // Default resolved direction is "first strong" heuristic
20407                             mPrivateFlags2 |= PFLAG2_TEXT_DIRECTION_RESOLVED_DEFAULT;
20408                     }
20409                     break;
20410                 case TEXT_DIRECTION_FIRST_STRONG:
20411                 case TEXT_DIRECTION_ANY_RTL:
20412                 case TEXT_DIRECTION_LTR:
20413                 case TEXT_DIRECTION_RTL:
20414                 case TEXT_DIRECTION_LOCALE:
20415                 case TEXT_DIRECTION_FIRST_STRONG_LTR:
20416                 case TEXT_DIRECTION_FIRST_STRONG_RTL:
20417                     // Resolved direction is the same as text direction
20418                     mPrivateFlags2 |= (textDirection << PFLAG2_TEXT_DIRECTION_RESOLVED_MASK_SHIFT);
20419                     break;
20420                 default:
20421                     // Default resolved direction is "first strong" heuristic
20422                     mPrivateFlags2 |= PFLAG2_TEXT_DIRECTION_RESOLVED_DEFAULT;
20423             }
20424         } else {
20425             // Default resolved direction is "first strong" heuristic
20426             mPrivateFlags2 |= PFLAG2_TEXT_DIRECTION_RESOLVED_DEFAULT;
20427         }
20428 
20429         // Set to resolved
20430         mPrivateFlags2 |= PFLAG2_TEXT_DIRECTION_RESOLVED;
20431         return true;
20432     }
20433 
20434     /**
20435      * Check if text direction resolution can be done.
20436      *
20437      * @return true if text direction resolution can be done otherwise return false.
20438      */
20439     public boolean canResolveTextDirection() {
20440         switch (getRawTextDirection()) {
20441             case TEXT_DIRECTION_INHERIT:
20442                 if (mParent != null) {
20443                     try {
20444                         return mParent.canResolveTextDirection();
20445                     } catch (AbstractMethodError e) {
20446                         Log.e(VIEW_LOG_TAG, mParent.getClass().getSimpleName() +
20447                                 " does not fully implement ViewParent", e);
20448                     }
20449                 }
20450                 return false;
20451 
20452             default:
20453                 return true;
20454         }
20455     }
20456 
20457     /**
20458      * Reset resolved text direction. Text direction will be resolved during a call to
20459      * {@link #onMeasure(int, int)}.
20460      *
20461      * @hide
20462      */
20463     public void resetResolvedTextDirection() {
20464         // Reset any previous text direction resolution
20465         mPrivateFlags2 &= ~(PFLAG2_TEXT_DIRECTION_RESOLVED | PFLAG2_TEXT_DIRECTION_RESOLVED_MASK);
20466         // Set to default value
20467         mPrivateFlags2 |= PFLAG2_TEXT_DIRECTION_RESOLVED_DEFAULT;
20468     }
20469 
20470     /**
20471      * @return true if text direction is inherited.
20472      *
20473      * @hide
20474      */
20475     public boolean isTextDirectionInherited() {
20476         return (getRawTextDirection() == TEXT_DIRECTION_INHERIT);
20477     }
20478 
20479     /**
20480      * @return true if text direction is resolved.
20481      */
20482     public boolean isTextDirectionResolved() {
20483         return (mPrivateFlags2 & PFLAG2_TEXT_DIRECTION_RESOLVED) == PFLAG2_TEXT_DIRECTION_RESOLVED;
20484     }
20485 
20486     /**
20487      * Return the value specifying the text alignment or policy that was set with
20488      * {@link #setTextAlignment(int)}.
20489      *
20490      * @return the defined text alignment. It can be one of:
20491      *
20492      * {@link #TEXT_ALIGNMENT_INHERIT},
20493      * {@link #TEXT_ALIGNMENT_GRAVITY},
20494      * {@link #TEXT_ALIGNMENT_CENTER},
20495      * {@link #TEXT_ALIGNMENT_TEXT_START},
20496      * {@link #TEXT_ALIGNMENT_TEXT_END},
20497      * {@link #TEXT_ALIGNMENT_VIEW_START},
20498      * {@link #TEXT_ALIGNMENT_VIEW_END}
20499      *
20500      * @attr ref android.R.styleable#View_textAlignment
20501      *
20502      * @hide
20503      */
20504     @ViewDebug.ExportedProperty(category = "text", mapping = {
20505             @ViewDebug.IntToString(from = TEXT_ALIGNMENT_INHERIT, to = "INHERIT"),
20506             @ViewDebug.IntToString(from = TEXT_ALIGNMENT_GRAVITY, to = "GRAVITY"),
20507             @ViewDebug.IntToString(from = TEXT_ALIGNMENT_TEXT_START, to = "TEXT_START"),
20508             @ViewDebug.IntToString(from = TEXT_ALIGNMENT_TEXT_END, to = "TEXT_END"),
20509             @ViewDebug.IntToString(from = TEXT_ALIGNMENT_CENTER, to = "CENTER"),
20510             @ViewDebug.IntToString(from = TEXT_ALIGNMENT_VIEW_START, to = "VIEW_START"),
20511             @ViewDebug.IntToString(from = TEXT_ALIGNMENT_VIEW_END, to = "VIEW_END")
20512     })
20513     @TextAlignment
20514     public int getRawTextAlignment() {
20515         return (mPrivateFlags2 & PFLAG2_TEXT_ALIGNMENT_MASK) >> PFLAG2_TEXT_ALIGNMENT_MASK_SHIFT;
20516     }
20517 
20518     /**
20519      * Set the text alignment.
20520      *
20521      * @param textAlignment The text alignment to set. Should be one of
20522      *
20523      * {@link #TEXT_ALIGNMENT_INHERIT},
20524      * {@link #TEXT_ALIGNMENT_GRAVITY},
20525      * {@link #TEXT_ALIGNMENT_CENTER},
20526      * {@link #TEXT_ALIGNMENT_TEXT_START},
20527      * {@link #TEXT_ALIGNMENT_TEXT_END},
20528      * {@link #TEXT_ALIGNMENT_VIEW_START},
20529      * {@link #TEXT_ALIGNMENT_VIEW_END}
20530      *
20531      * Resolution will be done if the value is set to TEXT_ALIGNMENT_INHERIT. The resolution
20532      * proceeds up the parent chain of the view to get the value. If there is no parent, then it
20533      * will return the default {@link #TEXT_ALIGNMENT_GRAVITY}.
20534      *
20535      * @attr ref android.R.styleable#View_textAlignment
20536      */
20537     public void setTextAlignment(@TextAlignment int textAlignment) {
20538         if (textAlignment != getRawTextAlignment()) {
20539             // Reset the current and resolved text alignment
20540             mPrivateFlags2 &= ~PFLAG2_TEXT_ALIGNMENT_MASK;
20541             resetResolvedTextAlignment();
20542             // Set the new text alignment
20543             mPrivateFlags2 |=
20544                     ((textAlignment << PFLAG2_TEXT_ALIGNMENT_MASK_SHIFT) & PFLAG2_TEXT_ALIGNMENT_MASK);
20545             // Do resolution
20546             resolveTextAlignment();
20547             // Notify change
20548             onRtlPropertiesChanged(getLayoutDirection());
20549             // Refresh
20550             requestLayout();
20551             invalidate(true);
20552         }
20553     }
20554 
20555     /**
20556      * Return the resolved text alignment.
20557      *
20558      * @return the resolved text alignment. Returns one of:
20559      *
20560      * {@link #TEXT_ALIGNMENT_GRAVITY},
20561      * {@link #TEXT_ALIGNMENT_CENTER},
20562      * {@link #TEXT_ALIGNMENT_TEXT_START},
20563      * {@link #TEXT_ALIGNMENT_TEXT_END},
20564      * {@link #TEXT_ALIGNMENT_VIEW_START},
20565      * {@link #TEXT_ALIGNMENT_VIEW_END}
20566      *
20567      * @attr ref android.R.styleable#View_textAlignment
20568      */
20569     @ViewDebug.ExportedProperty(category = "text", mapping = {
20570             @ViewDebug.IntToString(from = TEXT_ALIGNMENT_INHERIT, to = "INHERIT"),
20571             @ViewDebug.IntToString(from = TEXT_ALIGNMENT_GRAVITY, to = "GRAVITY"),
20572             @ViewDebug.IntToString(from = TEXT_ALIGNMENT_TEXT_START, to = "TEXT_START"),
20573             @ViewDebug.IntToString(from = TEXT_ALIGNMENT_TEXT_END, to = "TEXT_END"),
20574             @ViewDebug.IntToString(from = TEXT_ALIGNMENT_CENTER, to = "CENTER"),
20575             @ViewDebug.IntToString(from = TEXT_ALIGNMENT_VIEW_START, to = "VIEW_START"),
20576             @ViewDebug.IntToString(from = TEXT_ALIGNMENT_VIEW_END, to = "VIEW_END")
20577     })
20578     @TextAlignment
20579     public int getTextAlignment() {
20580         return (mPrivateFlags2 & PFLAG2_TEXT_ALIGNMENT_RESOLVED_MASK) >>
20581                 PFLAG2_TEXT_ALIGNMENT_RESOLVED_MASK_SHIFT;
20582     }
20583 
20584     /**
20585      * Resolve the text alignment.
20586      *
20587      * @return true if resolution has been done, false otherwise.
20588      *
20589      * @hide
20590      */
20591     public boolean resolveTextAlignment() {
20592         // Reset any previous text alignment resolution
20593         mPrivateFlags2 &= ~(PFLAG2_TEXT_ALIGNMENT_RESOLVED | PFLAG2_TEXT_ALIGNMENT_RESOLVED_MASK);
20594 
20595         if (hasRtlSupport()) {
20596             // Set resolved text alignment flag depending on text alignment flag
20597             final int textAlignment = getRawTextAlignment();
20598             switch (textAlignment) {
20599                 case TEXT_ALIGNMENT_INHERIT:
20600                     // Check if we can resolve the text alignment
20601                     if (!canResolveTextAlignment()) {
20602                         // We cannot do the resolution if there is no parent so use the default
20603                         mPrivateFlags2 |= PFLAG2_TEXT_ALIGNMENT_RESOLVED_DEFAULT;
20604                         // Resolution will need to happen again later
20605                         return false;
20606                     }
20607 
20608                     // Parent has not yet resolved, so we still return the default
20609                     try {
20610                         if (!mParent.isTextAlignmentResolved()) {
20611                             mPrivateFlags2 |= PFLAG2_TEXT_ALIGNMENT_RESOLVED_DEFAULT;
20612                             // Resolution will need to happen again later
20613                             return false;
20614                         }
20615                     } catch (AbstractMethodError e) {
20616                         Log.e(VIEW_LOG_TAG, mParent.getClass().getSimpleName() +
20617                                 " does not fully implement ViewParent", e);
20618                         mPrivateFlags2 |= PFLAG2_TEXT_ALIGNMENT_RESOLVED |
20619                                 PFLAG2_TEXT_ALIGNMENT_RESOLVED_DEFAULT;
20620                         return true;
20621                     }
20622 
20623                     int parentResolvedTextAlignment;
20624                     try {
20625                         parentResolvedTextAlignment = mParent.getTextAlignment();
20626                     } catch (AbstractMethodError e) {
20627                         Log.e(VIEW_LOG_TAG, mParent.getClass().getSimpleName() +
20628                                 " does not fully implement ViewParent", e);
20629                         parentResolvedTextAlignment = TEXT_ALIGNMENT_GRAVITY;
20630                     }
20631                     switch (parentResolvedTextAlignment) {
20632                         case TEXT_ALIGNMENT_GRAVITY:
20633                         case TEXT_ALIGNMENT_TEXT_START:
20634                         case TEXT_ALIGNMENT_TEXT_END:
20635                         case TEXT_ALIGNMENT_CENTER:
20636                         case TEXT_ALIGNMENT_VIEW_START:
20637                         case TEXT_ALIGNMENT_VIEW_END:
20638                             // Resolved text alignment is the same as the parent resolved
20639                             // text alignment
20640                             mPrivateFlags2 |=
20641                                     (parentResolvedTextAlignment << PFLAG2_TEXT_ALIGNMENT_RESOLVED_MASK_SHIFT);
20642                             break;
20643                         default:
20644                             // Use default resolved text alignment
20645                             mPrivateFlags2 |= PFLAG2_TEXT_ALIGNMENT_RESOLVED_DEFAULT;
20646                     }
20647                     break;
20648                 case TEXT_ALIGNMENT_GRAVITY:
20649                 case TEXT_ALIGNMENT_TEXT_START:
20650                 case TEXT_ALIGNMENT_TEXT_END:
20651                 case TEXT_ALIGNMENT_CENTER:
20652                 case TEXT_ALIGNMENT_VIEW_START:
20653                 case TEXT_ALIGNMENT_VIEW_END:
20654                     // Resolved text alignment is the same as text alignment
20655                     mPrivateFlags2 |= (textAlignment << PFLAG2_TEXT_ALIGNMENT_RESOLVED_MASK_SHIFT);
20656                     break;
20657                 default:
20658                     // Use default resolved text alignment
20659                     mPrivateFlags2 |= PFLAG2_TEXT_ALIGNMENT_RESOLVED_DEFAULT;
20660             }
20661         } else {
20662             // Use default resolved text alignment
20663             mPrivateFlags2 |= PFLAG2_TEXT_ALIGNMENT_RESOLVED_DEFAULT;
20664         }
20665 
20666         // Set the resolved
20667         mPrivateFlags2 |= PFLAG2_TEXT_ALIGNMENT_RESOLVED;
20668         return true;
20669     }
20670 
20671     /**
20672      * Check if text alignment resolution can be done.
20673      *
20674      * @return true if text alignment resolution can be done otherwise return false.
20675      */
20676     public boolean canResolveTextAlignment() {
20677         switch (getRawTextAlignment()) {
20678             case TEXT_DIRECTION_INHERIT:
20679                 if (mParent != null) {
20680                     try {
20681                         return mParent.canResolveTextAlignment();
20682                     } catch (AbstractMethodError e) {
20683                         Log.e(VIEW_LOG_TAG, mParent.getClass().getSimpleName() +
20684                                 " does not fully implement ViewParent", e);
20685                     }
20686                 }
20687                 return false;
20688 
20689             default:
20690                 return true;
20691         }
20692     }
20693 
20694     /**
20695      * Reset resolved text alignment. Text alignment will be resolved during a call to
20696      * {@link #onMeasure(int, int)}.
20697      *
20698      * @hide
20699      */
20700     public void resetResolvedTextAlignment() {
20701         // Reset any previous text alignment resolution
20702         mPrivateFlags2 &= ~(PFLAG2_TEXT_ALIGNMENT_RESOLVED | PFLAG2_TEXT_ALIGNMENT_RESOLVED_MASK);
20703         // Set to default
20704         mPrivateFlags2 |= PFLAG2_TEXT_ALIGNMENT_RESOLVED_DEFAULT;
20705     }
20706 
20707     /**
20708      * @return true if text alignment is inherited.
20709      *
20710      * @hide
20711      */
20712     public boolean isTextAlignmentInherited() {
20713         return (getRawTextAlignment() == TEXT_ALIGNMENT_INHERIT);
20714     }
20715 
20716     /**
20717      * @return true if text alignment is resolved.
20718      */
20719     public boolean isTextAlignmentResolved() {
20720         return (mPrivateFlags2 & PFLAG2_TEXT_ALIGNMENT_RESOLVED) == PFLAG2_TEXT_ALIGNMENT_RESOLVED;
20721     }
20722 
20723     /**
20724      * Generate a value suitable for use in {@link #setId(int)}.
20725      * This value will not collide with ID values generated at build time by aapt for R.id.
20726      *
20727      * @return a generated ID value
20728      */
20729     public static int generateViewId() {
20730         for (;;) {
20731             final int result = sNextGeneratedId.get();
20732             // aapt-generated IDs have the high byte nonzero; clamp to the range under that.
20733             int newValue = result + 1;
20734             if (newValue > 0x00FFFFFF) newValue = 1; // Roll over to 1, not 0.
20735             if (sNextGeneratedId.compareAndSet(result, newValue)) {
20736                 return result;
20737             }
20738         }
20739     }
20740 
20741     /**
20742      * Gets the Views in the hierarchy affected by entering and exiting Activity Scene transitions.
20743      * @param transitioningViews This View will be added to transitioningViews if it is VISIBLE and
20744      *                           a normal View or a ViewGroup with
20745      *                           {@link android.view.ViewGroup#isTransitionGroup()} true.
20746      * @hide
20747      */
20748     public void captureTransitioningViews(List<View> transitioningViews) {
20749         if (getVisibility() == View.VISIBLE) {
20750             transitioningViews.add(this);
20751         }
20752     }
20753 
20754     /**
20755      * Adds all Views that have {@link #getTransitionName()} non-null to namedElements.
20756      * @param namedElements Will contain all Views in the hierarchy having a transitionName.
20757      * @hide
20758      */
20759     public void findNamedViews(Map<String, View> namedElements) {
20760         if (getVisibility() == VISIBLE || mGhostView != null) {
20761             String transitionName = getTransitionName();
20762             if (transitionName != null) {
20763                 namedElements.put(transitionName, this);
20764             }
20765         }
20766     }
20767 
20768     //
20769     // Properties
20770     //
20771     /**
20772      * A Property wrapper around the <code>alpha</code> functionality handled by the
20773      * {@link View#setAlpha(float)} and {@link View#getAlpha()} methods.
20774      */
20775     public static final Property<View, Float> ALPHA = new FloatProperty<View>("alpha") {
20776         @Override
20777         public void setValue(View object, float value) {
20778             object.setAlpha(value);
20779         }
20780 
20781         @Override
20782         public Float get(View object) {
20783             return object.getAlpha();
20784         }
20785     };
20786 
20787     /**
20788      * A Property wrapper around the <code>translationX</code> functionality handled by the
20789      * {@link View#setTranslationX(float)} and {@link View#getTranslationX()} methods.
20790      */
20791     public static final Property<View, Float> TRANSLATION_X = new FloatProperty<View>("translationX") {
20792         @Override
20793         public void setValue(View object, float value) {
20794             object.setTranslationX(value);
20795         }
20796 
20797                 @Override
20798         public Float get(View object) {
20799             return object.getTranslationX();
20800         }
20801     };
20802 
20803     /**
20804      * A Property wrapper around the <code>translationY</code> functionality handled by the
20805      * {@link View#setTranslationY(float)} and {@link View#getTranslationY()} methods.
20806      */
20807     public static final Property<View, Float> TRANSLATION_Y = new FloatProperty<View>("translationY") {
20808         @Override
20809         public void setValue(View object, float value) {
20810             object.setTranslationY(value);
20811         }
20812 
20813         @Override
20814         public Float get(View object) {
20815             return object.getTranslationY();
20816         }
20817     };
20818 
20819     /**
20820      * A Property wrapper around the <code>translationZ</code> functionality handled by the
20821      * {@link View#setTranslationZ(float)} and {@link View#getTranslationZ()} methods.
20822      */
20823     public static final Property<View, Float> TRANSLATION_Z = new FloatProperty<View>("translationZ") {
20824         @Override
20825         public void setValue(View object, float value) {
20826             object.setTranslationZ(value);
20827         }
20828 
20829         @Override
20830         public Float get(View object) {
20831             return object.getTranslationZ();
20832         }
20833     };
20834 
20835     /**
20836      * A Property wrapper around the <code>x</code> functionality handled by the
20837      * {@link View#setX(float)} and {@link View#getX()} methods.
20838      */
20839     public static final Property<View, Float> X = new FloatProperty<View>("x") {
20840         @Override
20841         public void setValue(View object, float value) {
20842             object.setX(value);
20843         }
20844 
20845         @Override
20846         public Float get(View object) {
20847             return object.getX();
20848         }
20849     };
20850 
20851     /**
20852      * A Property wrapper around the <code>y</code> functionality handled by the
20853      * {@link View#setY(float)} and {@link View#getY()} methods.
20854      */
20855     public static final Property<View, Float> Y = new FloatProperty<View>("y") {
20856         @Override
20857         public void setValue(View object, float value) {
20858             object.setY(value);
20859         }
20860 
20861         @Override
20862         public Float get(View object) {
20863             return object.getY();
20864         }
20865     };
20866 
20867     /**
20868      * A Property wrapper around the <code>z</code> functionality handled by the
20869      * {@link View#setZ(float)} and {@link View#getZ()} methods.
20870      */
20871     public static final Property<View, Float> Z = new FloatProperty<View>("z") {
20872         @Override
20873         public void setValue(View object, float value) {
20874             object.setZ(value);
20875         }
20876 
20877         @Override
20878         public Float get(View object) {
20879             return object.getZ();
20880         }
20881     };
20882 
20883     /**
20884      * A Property wrapper around the <code>rotation</code> functionality handled by the
20885      * {@link View#setRotation(float)} and {@link View#getRotation()} methods.
20886      */
20887     public static final Property<View, Float> ROTATION = new FloatProperty<View>("rotation") {
20888         @Override
20889         public void setValue(View object, float value) {
20890             object.setRotation(value);
20891         }
20892 
20893         @Override
20894         public Float get(View object) {
20895             return object.getRotation();
20896         }
20897     };
20898 
20899     /**
20900      * A Property wrapper around the <code>rotationX</code> functionality handled by the
20901      * {@link View#setRotationX(float)} and {@link View#getRotationX()} methods.
20902      */
20903     public static final Property<View, Float> ROTATION_X = new FloatProperty<View>("rotationX") {
20904         @Override
20905         public void setValue(View object, float value) {
20906             object.setRotationX(value);
20907         }
20908 
20909         @Override
20910         public Float get(View object) {
20911             return object.getRotationX();
20912         }
20913     };
20914 
20915     /**
20916      * A Property wrapper around the <code>rotationY</code> functionality handled by the
20917      * {@link View#setRotationY(float)} and {@link View#getRotationY()} methods.
20918      */
20919     public static final Property<View, Float> ROTATION_Y = new FloatProperty<View>("rotationY") {
20920         @Override
20921         public void setValue(View object, float value) {
20922             object.setRotationY(value);
20923         }
20924 
20925         @Override
20926         public Float get(View object) {
20927             return object.getRotationY();
20928         }
20929     };
20930 
20931     /**
20932      * A Property wrapper around the <code>scaleX</code> functionality handled by the
20933      * {@link View#setScaleX(float)} and {@link View#getScaleX()} methods.
20934      */
20935     public static final Property<View, Float> SCALE_X = new FloatProperty<View>("scaleX") {
20936         @Override
20937         public void setValue(View object, float value) {
20938             object.setScaleX(value);
20939         }
20940 
20941         @Override
20942         public Float get(View object) {
20943             return object.getScaleX();
20944         }
20945     };
20946 
20947     /**
20948      * A Property wrapper around the <code>scaleY</code> functionality handled by the
20949      * {@link View#setScaleY(float)} and {@link View#getScaleY()} methods.
20950      */
20951     public static final Property<View, Float> SCALE_Y = new FloatProperty<View>("scaleY") {
20952         @Override
20953         public void setValue(View object, float value) {
20954             object.setScaleY(value);
20955         }
20956 
20957         @Override
20958         public Float get(View object) {
20959             return object.getScaleY();
20960         }
20961     };
20962 
20963     /**
20964      * A MeasureSpec encapsulates the layout requirements passed from parent to child.
20965      * Each MeasureSpec represents a requirement for either the width or the height.
20966      * A MeasureSpec is comprised of a size and a mode. There are three possible
20967      * modes:
20968      * <dl>
20969      * <dt>UNSPECIFIED</dt>
20970      * <dd>
20971      * The parent has not imposed any constraint on the child. It can be whatever size
20972      * it wants.
20973      * </dd>
20974      *
20975      * <dt>EXACTLY</dt>
20976      * <dd>
20977      * The parent has determined an exact size for the child. The child is going to be
20978      * given those bounds regardless of how big it wants to be.
20979      * </dd>
20980      *
20981      * <dt>AT_MOST</dt>
20982      * <dd>
20983      * The child can be as large as it wants up to the specified size.
20984      * </dd>
20985      * </dl>
20986      *
20987      * MeasureSpecs are implemented as ints to reduce object allocation. This class
20988      * is provided to pack and unpack the &lt;size, mode&gt; tuple into the int.
20989      */
20990     public static class MeasureSpec {
20991         private static final int MODE_SHIFT = 30;
20992         private static final int MODE_MASK  = 0x3 << MODE_SHIFT;
20993 
20994         /**
20995          * Measure specification mode: The parent has not imposed any constraint
20996          * on the child. It can be whatever size it wants.
20997          */
20998         public static final int UNSPECIFIED = 0 << MODE_SHIFT;
20999 
21000         /**
21001          * Measure specification mode: The parent has determined an exact size
21002          * for the child. The child is going to be given those bounds regardless
21003          * of how big it wants to be.
21004          */
21005         public static final int EXACTLY     = 1 << MODE_SHIFT;
21006 
21007         /**
21008          * Measure specification mode: The child can be as large as it wants up
21009          * to the specified size.
21010          */
21011         public static final int AT_MOST     = 2 << MODE_SHIFT;
21012 
21013         /**
21014          * Creates a measure specification based on the supplied size and mode.
21015          *
21016          * The mode must always be one of the following:
21017          * <ul>
21018          *  <li>{@link android.view.View.MeasureSpec#UNSPECIFIED}</li>
21019          *  <li>{@link android.view.View.MeasureSpec#EXACTLY}</li>
21020          *  <li>{@link android.view.View.MeasureSpec#AT_MOST}</li>
21021          * </ul>
21022          *
21023          * <p><strong>Note:</strong> On API level 17 and lower, makeMeasureSpec's
21024          * implementation was such that the order of arguments did not matter
21025          * and overflow in either value could impact the resulting MeasureSpec.
21026          * {@link android.widget.RelativeLayout} was affected by this bug.
21027          * Apps targeting API levels greater than 17 will get the fixed, more strict
21028          * behavior.</p>
21029          *
21030          * @param size the size of the measure specification
21031          * @param mode the mode of the measure specification
21032          * @return the measure specification based on size and mode
21033          */
21034         public static int makeMeasureSpec(int size, int mode) {
21035             if (sUseBrokenMakeMeasureSpec) {
21036                 return size + mode;
21037             } else {
21038                 return (size & ~MODE_MASK) | (mode & MODE_MASK);
21039             }
21040         }
21041 
21042         /**
21043          * Like {@link #makeMeasureSpec(int, int)}, but any spec with a mode of UNSPECIFIED
21044          * will automatically get a size of 0. Older apps expect this.
21045          *
21046          * @hide internal use only for compatibility with system widgets and older apps
21047          */
21048         public static int makeSafeMeasureSpec(int size, int mode) {
21049             if (sUseZeroUnspecifiedMeasureSpec && mode == UNSPECIFIED) {
21050                 return 0;
21051             }
21052             return makeMeasureSpec(size, mode);
21053         }
21054 
21055         /**
21056          * Extracts the mode from the supplied measure specification.
21057          *
21058          * @param measureSpec the measure specification to extract the mode from
21059          * @return {@link android.view.View.MeasureSpec#UNSPECIFIED},
21060          *         {@link android.view.View.MeasureSpec#AT_MOST} or
21061          *         {@link android.view.View.MeasureSpec#EXACTLY}
21062          */
21063         public static int getMode(int measureSpec) {
21064             return (measureSpec & MODE_MASK);
21065         }
21066 
21067         /**
21068          * Extracts the size from the supplied measure specification.
21069          *
21070          * @param measureSpec the measure specification to extract the size from
21071          * @return the size in pixels defined in the supplied measure specification
21072          */
21073         public static int getSize(int measureSpec) {
21074             return (measureSpec & ~MODE_MASK);
21075         }
21076 
21077         static int adjust(int measureSpec, int delta) {
21078             final int mode = getMode(measureSpec);
21079             int size = getSize(measureSpec);
21080             if (mode == UNSPECIFIED) {
21081                 // No need to adjust size for UNSPECIFIED mode.
21082                 return makeMeasureSpec(size, UNSPECIFIED);
21083             }
21084             size += delta;
21085             if (size < 0) {
21086                 Log.e(VIEW_LOG_TAG, "MeasureSpec.adjust: new size would be negative! (" + size +
21087                         ") spec: " + toString(measureSpec) + " delta: " + delta);
21088                 size = 0;
21089             }
21090             return makeMeasureSpec(size, mode);
21091         }
21092 
21093         /**
21094          * Returns a String representation of the specified measure
21095          * specification.
21096          *
21097          * @param measureSpec the measure specification to convert to a String
21098          * @return a String with the following format: "MeasureSpec: MODE SIZE"
21099          */
21100         public static String toString(int measureSpec) {
21101             int mode = getMode(measureSpec);
21102             int size = getSize(measureSpec);
21103 
21104             StringBuilder sb = new StringBuilder("MeasureSpec: ");
21105 
21106             if (mode == UNSPECIFIED)
21107                 sb.append("UNSPECIFIED ");
21108             else if (mode == EXACTLY)
21109                 sb.append("EXACTLY ");
21110             else if (mode == AT_MOST)
21111                 sb.append("AT_MOST ");
21112             else
21113                 sb.append(mode).append(" ");
21114 
21115             sb.append(size);
21116             return sb.toString();
21117         }
21118     }
21119 
21120     private final class CheckForLongPress implements Runnable {
21121         private int mOriginalWindowAttachCount;
21122 
21123         @Override
21124         public void run() {
21125             if (isPressed() && (mParent != null)
21126                     && mOriginalWindowAttachCount == mWindowAttachCount) {
21127                 if (performLongClick()) {
21128                     mHasPerformedLongPress = true;
21129                 }
21130             }
21131         }
21132 
21133         public void rememberWindowAttachCount() {
21134             mOriginalWindowAttachCount = mWindowAttachCount;
21135         }
21136     }
21137 
21138     private final class CheckForTap implements Runnable {
21139         public float x;
21140         public float y;
21141 
21142         @Override
21143         public void run() {
21144             mPrivateFlags &= ~PFLAG_PREPRESSED;
21145             setPressed(true, x, y);
21146             checkForLongClick(ViewConfiguration.getTapTimeout());
21147         }
21148     }
21149 
21150     private final class PerformClick implements Runnable {
21151         @Override
21152         public void run() {
21153             performClick();
21154         }
21155     }
21156 
21157     /** @hide */
21158     public void hackTurnOffWindowResizeAnim(boolean off) {
21159         mAttachInfo.mTurnOffWindowResizeAnim = off;
21160     }
21161 
21162     /**
21163      * This method returns a ViewPropertyAnimator object, which can be used to animate
21164      * specific properties on this View.
21165      *
21166      * @return ViewPropertyAnimator The ViewPropertyAnimator associated with this View.
21167      */
21168     public ViewPropertyAnimator animate() {
21169         if (mAnimator == null) {
21170             mAnimator = new ViewPropertyAnimator(this);
21171         }
21172         return mAnimator;
21173     }
21174 
21175     /**
21176      * Sets the name of the View to be used to identify Views in Transitions.
21177      * Names should be unique in the View hierarchy.
21178      *
21179      * @param transitionName The name of the View to uniquely identify it for Transitions.
21180      */
21181     public final void setTransitionName(String transitionName) {
21182         mTransitionName = transitionName;
21183     }
21184 
21185     /**
21186      * Returns the name of the View to be used to identify Views in Transitions.
21187      * Names should be unique in the View hierarchy.
21188      *
21189      * <p>This returns null if the View has not been given a name.</p>
21190      *
21191      * @return The name used of the View to be used to identify Views in Transitions or null
21192      * if no name has been given.
21193      */
21194     @ViewDebug.ExportedProperty
21195     public String getTransitionName() {
21196         return mTransitionName;
21197     }
21198 
21199     /**
21200      * Interface definition for a callback to be invoked when a hardware key event is
21201      * dispatched to this view. The callback will be invoked before the key event is
21202      * given to the view. This is only useful for hardware keyboards; a software input
21203      * method has no obligation to trigger this listener.
21204      */
21205     public interface OnKeyListener {
21206         /**
21207          * Called when a hardware key is dispatched to a view. This allows listeners to
21208          * get a chance to respond before the target view.
21209          * <p>Key presses in software keyboards will generally NOT trigger this method,
21210          * although some may elect to do so in some situations. Do not assume a
21211          * software input method has to be key-based; even if it is, it may use key presses
21212          * in a different way than you expect, so there is no way to reliably catch soft
21213          * input key presses.
21214          *
21215          * @param v The view the key has been dispatched to.
21216          * @param keyCode The code for the physical key that was pressed
21217          * @param event The KeyEvent object containing full information about
21218          *        the event.
21219          * @return True if the listener has consumed the event, false otherwise.
21220          */
21221         boolean onKey(View v, int keyCode, KeyEvent event);
21222     }
21223 
21224     /**
21225      * Interface definition for a callback to be invoked when a touch event is
21226      * dispatched to this view. The callback will be invoked before the touch
21227      * event is given to the view.
21228      */
21229     public interface OnTouchListener {
21230         /**
21231          * Called when a touch event is dispatched to a view. This allows listeners to
21232          * get a chance to respond before the target view.
21233          *
21234          * @param v The view the touch event has been dispatched to.
21235          * @param event The MotionEvent object containing full information about
21236          *        the event.
21237          * @return True if the listener has consumed the event, false otherwise.
21238          */
21239         boolean onTouch(View v, MotionEvent event);
21240     }
21241 
21242     /**
21243      * Interface definition for a callback to be invoked when a hover event is
21244      * dispatched to this view. The callback will be invoked before the hover
21245      * event is given to the view.
21246      */
21247     public interface OnHoverListener {
21248         /**
21249          * Called when a hover event is dispatched to a view. This allows listeners to
21250          * get a chance to respond before the target view.
21251          *
21252          * @param v The view the hover event has been dispatched to.
21253          * @param event The MotionEvent object containing full information about
21254          *        the event.
21255          * @return True if the listener has consumed the event, false otherwise.
21256          */
21257         boolean onHover(View v, MotionEvent event);
21258     }
21259 
21260     /**
21261      * Interface definition for a callback to be invoked when a generic motion event is
21262      * dispatched to this view. The callback will be invoked before the generic motion
21263      * event is given to the view.
21264      */
21265     public interface OnGenericMotionListener {
21266         /**
21267          * Called when a generic motion event is dispatched to a view. This allows listeners to
21268          * get a chance to respond before the target view.
21269          *
21270          * @param v The view the generic motion event has been dispatched to.
21271          * @param event The MotionEvent object containing full information about
21272          *        the event.
21273          * @return True if the listener has consumed the event, false otherwise.
21274          */
21275         boolean onGenericMotion(View v, MotionEvent event);
21276     }
21277 
21278     /**
21279      * Interface definition for a callback to be invoked when a view has been clicked and held.
21280      */
21281     public interface OnLongClickListener {
21282         /**
21283          * Called when a view has been clicked and held.
21284          *
21285          * @param v The view that was clicked and held.
21286          *
21287          * @return true if the callback consumed the long click, false otherwise.
21288          */
21289         boolean onLongClick(View v);
21290     }
21291 
21292     /**
21293      * Interface definition for a callback to be invoked when a drag is being dispatched
21294      * to this view.  The callback will be invoked before the hosting view's own
21295      * onDrag(event) method.  If the listener wants to fall back to the hosting view's
21296      * onDrag(event) behavior, it should return 'false' from this callback.
21297      *
21298      * <div class="special reference">
21299      * <h3>Developer Guides</h3>
21300      * <p>For a guide to implementing drag and drop features, read the
21301      * <a href="{@docRoot}guide/topics/ui/drag-drop.html">Drag and Drop</a> developer guide.</p>
21302      * </div>
21303      */
21304     public interface OnDragListener {
21305         /**
21306          * Called when a drag event is dispatched to a view. This allows listeners
21307          * to get a chance to override base View behavior.
21308          *
21309          * @param v The View that received the drag event.
21310          * @param event The {@link android.view.DragEvent} object for the drag event.
21311          * @return {@code true} if the drag event was handled successfully, or {@code false}
21312          * if the drag event was not handled. Note that {@code false} will trigger the View
21313          * to call its {@link #onDragEvent(DragEvent) onDragEvent()} handler.
21314          */
21315         boolean onDrag(View v, DragEvent event);
21316     }
21317 
21318     /**
21319      * Interface definition for a callback to be invoked when the focus state of
21320      * a view changed.
21321      */
21322     public interface OnFocusChangeListener {
21323         /**
21324          * Called when the focus state of a view has changed.
21325          *
21326          * @param v The view whose state has changed.
21327          * @param hasFocus The new focus state of v.
21328          */
21329         void onFocusChange(View v, boolean hasFocus);
21330     }
21331 
21332     /**
21333      * Interface definition for a callback to be invoked when a view is clicked.
21334      */
21335     public interface OnClickListener {
21336         /**
21337          * Called when a view has been clicked.
21338          *
21339          * @param v The view that was clicked.
21340          */
21341         void onClick(View v);
21342     }
21343 
21344     /**
21345      * Interface definition for a callback to be invoked when a view is context clicked.
21346      */
21347     public interface OnContextClickListener {
21348         /**
21349          * Called when a view is context clicked.
21350          *
21351          * @param v The view that has been context clicked.
21352          * @return true if the callback consumed the context click, false otherwise.
21353          */
21354         boolean onContextClick(View v);
21355     }
21356 
21357     /**
21358      * Interface definition for a callback to be invoked when the context menu
21359      * for this view is being built.
21360      */
21361     public interface OnCreateContextMenuListener {
21362         /**
21363          * Called when the context menu for this view is being built. It is not
21364          * safe to hold onto the menu after this method returns.
21365          *
21366          * @param menu The context menu that is being built
21367          * @param v The view for which the context menu is being built
21368          * @param menuInfo Extra information about the item for which the
21369          *            context menu should be shown. This information will vary
21370          *            depending on the class of v.
21371          */
21372         void onCreateContextMenu(ContextMenu menu, View v, ContextMenuInfo menuInfo);
21373     }
21374 
21375     /**
21376      * Interface definition for a callback to be invoked when the status bar changes
21377      * visibility.  This reports <strong>global</strong> changes to the system UI
21378      * state, not what the application is requesting.
21379      *
21380      * @see View#setOnSystemUiVisibilityChangeListener(android.view.View.OnSystemUiVisibilityChangeListener)
21381      */
21382     public interface OnSystemUiVisibilityChangeListener {
21383         /**
21384          * Called when the status bar changes visibility because of a call to
21385          * {@link View#setSystemUiVisibility(int)}.
21386          *
21387          * @param visibility  Bitwise-or of flags {@link #SYSTEM_UI_FLAG_LOW_PROFILE},
21388          * {@link #SYSTEM_UI_FLAG_HIDE_NAVIGATION}, and {@link #SYSTEM_UI_FLAG_FULLSCREEN}.
21389          * This tells you the <strong>global</strong> state of these UI visibility
21390          * flags, not what your app is currently applying.
21391          */
21392         public void onSystemUiVisibilityChange(int visibility);
21393     }
21394 
21395     /**
21396      * Interface definition for a callback to be invoked when this view is attached
21397      * or detached from its window.
21398      */
21399     public interface OnAttachStateChangeListener {
21400         /**
21401          * Called when the view is attached to a window.
21402          * @param v The view that was attached
21403          */
21404         public void onViewAttachedToWindow(View v);
21405         /**
21406          * Called when the view is detached from a window.
21407          * @param v The view that was detached
21408          */
21409         public void onViewDetachedFromWindow(View v);
21410     }
21411 
21412     /**
21413      * Listener for applying window insets on a view in a custom way.
21414      *
21415      * <p>Apps may choose to implement this interface if they want to apply custom policy
21416      * to the way that window insets are treated for a view. If an OnApplyWindowInsetsListener
21417      * is set, its
21418      * {@link OnApplyWindowInsetsListener#onApplyWindowInsets(View, WindowInsets) onApplyWindowInsets}
21419      * method will be called instead of the View's own
21420      * {@link #onApplyWindowInsets(WindowInsets) onApplyWindowInsets} method. The listener
21421      * may optionally call the parameter View's <code>onApplyWindowInsets</code> method to apply
21422      * the View's normal behavior as part of its own.</p>
21423      */
21424     public interface OnApplyWindowInsetsListener {
21425         /**
21426          * When {@link View#setOnApplyWindowInsetsListener(View.OnApplyWindowInsetsListener) set}
21427          * on a View, this listener method will be called instead of the view's own
21428          * {@link View#onApplyWindowInsets(WindowInsets) onApplyWindowInsets} method.
21429          *
21430          * @param v The view applying window insets
21431          * @param insets The insets to apply
21432          * @return The insets supplied, minus any insets that were consumed
21433          */
21434         public WindowInsets onApplyWindowInsets(View v, WindowInsets insets);
21435     }
21436 
21437     private final class UnsetPressedState implements Runnable {
21438         @Override
21439         public void run() {
21440             setPressed(false);
21441         }
21442     }
21443 
21444     /**
21445      * Base class for derived classes that want to save and restore their own
21446      * state in {@link android.view.View#onSaveInstanceState()}.
21447      */
21448     public static class BaseSavedState extends AbsSavedState {
21449         String mStartActivityRequestWhoSaved;
21450 
21451         /**
21452          * Constructor used when reading from a parcel. Reads the state of the superclass.
21453          *
21454          * @param source
21455          */
21456         public BaseSavedState(Parcel source) {
21457             super(source);
21458             mStartActivityRequestWhoSaved = source.readString();
21459         }
21460 
21461         /**
21462          * Constructor called by derived classes when creating their SavedState objects
21463          *
21464          * @param superState The state of the superclass of this view
21465          */
21466         public BaseSavedState(Parcelable superState) {
21467             super(superState);
21468         }
21469 
21470         @Override
21471         public void writeToParcel(Parcel out, int flags) {
21472             super.writeToParcel(out, flags);
21473             out.writeString(mStartActivityRequestWhoSaved);
21474         }
21475 
21476         public static final Parcelable.Creator<BaseSavedState> CREATOR =
21477                 new Parcelable.Creator<BaseSavedState>() {
21478             public BaseSavedState createFromParcel(Parcel in) {
21479                 return new BaseSavedState(in);
21480             }
21481 
21482             public BaseSavedState[] newArray(int size) {
21483                 return new BaseSavedState[size];
21484             }
21485         };
21486     }
21487 
21488     /**
21489      * A set of information given to a view when it is attached to its parent
21490      * window.
21491      */
21492     final static class AttachInfo {
21493         interface Callbacks {
21494             void playSoundEffect(int effectId);
21495             boolean performHapticFeedback(int effectId, boolean always);
21496         }
21497 
21498         /**
21499          * InvalidateInfo is used to post invalidate(int, int, int, int) messages
21500          * to a Handler. This class contains the target (View) to invalidate and
21501          * the coordinates of the dirty rectangle.
21502          *
21503          * For performance purposes, this class also implements a pool of up to
21504          * POOL_LIMIT objects that get reused. This reduces memory allocations
21505          * whenever possible.
21506          */
21507         static class InvalidateInfo {
21508             private static final int POOL_LIMIT = 10;
21509 
21510             private static final SynchronizedPool<InvalidateInfo> sPool =
21511                     new SynchronizedPool<InvalidateInfo>(POOL_LIMIT);
21512 
21513             View target;
21514 
21515             int left;
21516             int top;
21517             int right;
21518             int bottom;
21519 
21520             public static InvalidateInfo obtain() {
21521                 InvalidateInfo instance = sPool.acquire();
21522                 return (instance != null) ? instance : new InvalidateInfo();
21523             }
21524 
21525             public void recycle() {
21526                 target = null;
21527                 sPool.release(this);
21528             }
21529         }
21530 
21531         final IWindowSession mSession;
21532 
21533         final IWindow mWindow;
21534 
21535         final IBinder mWindowToken;
21536 
21537         final Display mDisplay;
21538 
21539         final Callbacks mRootCallbacks;
21540 
21541         IWindowId mIWindowId;
21542         WindowId mWindowId;
21543 
21544         /**
21545          * The top view of the hierarchy.
21546          */
21547         View mRootView;
21548 
21549         IBinder mPanelParentWindowToken;
21550 
21551         boolean mHardwareAccelerated;
21552         boolean mHardwareAccelerationRequested;
21553         HardwareRenderer mHardwareRenderer;
21554         List<RenderNode> mPendingAnimatingRenderNodes;
21555 
21556         /**
21557          * The state of the display to which the window is attached, as reported
21558          * by {@link Display#getState()}.  Note that the display state constants
21559          * declared by {@link Display} do not exactly line up with the screen state
21560          * constants declared by {@link View} (there are more display states than
21561          * screen states).
21562          */
21563         int mDisplayState = Display.STATE_UNKNOWN;
21564 
21565         /**
21566          * Scale factor used by the compatibility mode
21567          */
21568         float mApplicationScale;
21569 
21570         /**
21571          * Indicates whether the application is in compatibility mode
21572          */
21573         boolean mScalingRequired;
21574 
21575         /**
21576          * If set, ViewRootImpl doesn't use its lame animation for when the window resizes.
21577          */
21578         boolean mTurnOffWindowResizeAnim;
21579 
21580         /**
21581          * Left position of this view's window
21582          */
21583         int mWindowLeft;
21584 
21585         /**
21586          * Top position of this view's window
21587          */
21588         int mWindowTop;
21589 
21590         /**
21591          * Indicates whether views need to use 32-bit drawing caches
21592          */
21593         boolean mUse32BitDrawingCache;
21594 
21595         /**
21596          * For windows that are full-screen but using insets to layout inside
21597          * of the screen areas, these are the current insets to appear inside
21598          * the overscan area of the display.
21599          */
21600         final Rect mOverscanInsets = new Rect();
21601 
21602         /**
21603          * For windows that are full-screen but using insets to layout inside
21604          * of the screen decorations, these are the current insets for the
21605          * content of the window.
21606          */
21607         final Rect mContentInsets = new Rect();
21608 
21609         /**
21610          * For windows that are full-screen but using insets to layout inside
21611          * of the screen decorations, these are the current insets for the
21612          * actual visible parts of the window.
21613          */
21614         final Rect mVisibleInsets = new Rect();
21615 
21616         /**
21617          * For windows that are full-screen but using insets to layout inside
21618          * of the screen decorations, these are the current insets for the
21619          * stable system windows.
21620          */
21621         final Rect mStableInsets = new Rect();
21622 
21623         /**
21624          * For windows that include areas that are not covered by real surface these are the outsets
21625          * for real surface.
21626          */
21627         final Rect mOutsets = new Rect();
21628 
21629         /**
21630          * The internal insets given by this window.  This value is
21631          * supplied by the client (through
21632          * {@link ViewTreeObserver.OnComputeInternalInsetsListener}) and will
21633          * be given to the window manager when changed to be used in laying
21634          * out windows behind it.
21635          */
21636         final ViewTreeObserver.InternalInsetsInfo mGivenInternalInsets
21637                 = new ViewTreeObserver.InternalInsetsInfo();
21638 
21639         /**
21640          * Set to true when mGivenInternalInsets is non-empty.
21641          */
21642         boolean mHasNonEmptyGivenInternalInsets;
21643 
21644         /**
21645          * All views in the window's hierarchy that serve as scroll containers,
21646          * used to determine if the window can be resized or must be panned
21647          * to adjust for a soft input area.
21648          */
21649         final ArrayList<View> mScrollContainers = new ArrayList<View>();
21650 
21651         final KeyEvent.DispatcherState mKeyDispatchState
21652                 = new KeyEvent.DispatcherState();
21653 
21654         /**
21655          * Indicates whether the view's window currently has the focus.
21656          */
21657         boolean mHasWindowFocus;
21658 
21659         /**
21660          * The current visibility of the window.
21661          */
21662         int mWindowVisibility;
21663 
21664         /**
21665          * Indicates the time at which drawing started to occur.
21666          */
21667         long mDrawingTime;
21668 
21669         /**
21670          * Indicates whether or not ignoring the DIRTY_MASK flags.
21671          */
21672         boolean mIgnoreDirtyState;
21673 
21674         /**
21675          * This flag tracks when the mIgnoreDirtyState flag is set during draw(),
21676          * to avoid clearing that flag prematurely.
21677          */
21678         boolean mSetIgnoreDirtyState = false;
21679 
21680         /**
21681          * Indicates whether the view's window is currently in touch mode.
21682          */
21683         boolean mInTouchMode;
21684 
21685         /**
21686          * Indicates whether the view has requested unbuffered input dispatching for the current
21687          * event stream.
21688          */
21689         boolean mUnbufferedDispatchRequested;
21690 
21691         /**
21692          * Indicates that ViewAncestor should trigger a global layout change
21693          * the next time it performs a traversal
21694          */
21695         boolean mRecomputeGlobalAttributes;
21696 
21697         /**
21698          * Always report new attributes at next traversal.
21699          */
21700         boolean mForceReportNewAttributes;
21701 
21702         /**
21703          * Set during a traveral if any views want to keep the screen on.
21704          */
21705         boolean mKeepScreenOn;
21706 
21707         /**
21708          * Bitwise-or of all of the values that views have passed to setSystemUiVisibility().
21709          */
21710         int mSystemUiVisibility;
21711 
21712         /**
21713          * Hack to force certain system UI visibility flags to be cleared.
21714          */
21715         int mDisabledSystemUiVisibility;
21716 
21717         /**
21718          * Last global system UI visibility reported by the window manager.
21719          */
21720         int mGlobalSystemUiVisibility;
21721 
21722         /**
21723          * True if a view in this hierarchy has an OnSystemUiVisibilityChangeListener
21724          * attached.
21725          */
21726         boolean mHasSystemUiListeners;
21727 
21728         /**
21729          * Set if the window has requested to extend into the overscan region
21730          * via WindowManager.LayoutParams.FLAG_LAYOUT_IN_OVERSCAN.
21731          */
21732         boolean mOverscanRequested;
21733 
21734         /**
21735          * Set if the visibility of any views has changed.
21736          */
21737         boolean mViewVisibilityChanged;
21738 
21739         /**
21740          * Set to true if a view has been scrolled.
21741          */
21742         boolean mViewScrollChanged;
21743 
21744         /**
21745          * Set to true if high contrast mode enabled
21746          */
21747         boolean mHighContrastText;
21748 
21749         /**
21750          * Global to the view hierarchy used as a temporary for dealing with
21751          * x/y points in the transparent region computations.
21752          */
21753         final int[] mTransparentLocation = new int[2];
21754 
21755         /**
21756          * Global to the view hierarchy used as a temporary for dealing with
21757          * x/y points in the ViewGroup.invalidateChild implementation.
21758          */
21759         final int[] mInvalidateChildLocation = new int[2];
21760 
21761         /**
21762          * Global to the view hierarchy used as a temporary for dealng with
21763          * computing absolute on-screen location.
21764          */
21765         final int[] mTmpLocation = new int[2];
21766 
21767         /**
21768          * Global to the view hierarchy used as a temporary for dealing with
21769          * x/y location when view is transformed.
21770          */
21771         final float[] mTmpTransformLocation = new float[2];
21772 
21773         /**
21774          * The view tree observer used to dispatch global events like
21775          * layout, pre-draw, touch mode change, etc.
21776          */
21777         final ViewTreeObserver mTreeObserver = new ViewTreeObserver();
21778 
21779         /**
21780          * A Canvas used by the view hierarchy to perform bitmap caching.
21781          */
21782         Canvas mCanvas;
21783 
21784         /**
21785          * The view root impl.
21786          */
21787         final ViewRootImpl mViewRootImpl;
21788 
21789         /**
21790          * A Handler supplied by a view's {@link android.view.ViewRootImpl}. This
21791          * handler can be used to pump events in the UI events queue.
21792          */
21793         final Handler mHandler;
21794 
21795         /**
21796          * Temporary for use in computing invalidate rectangles while
21797          * calling up the hierarchy.
21798          */
21799         final Rect mTmpInvalRect = new Rect();
21800 
21801         /**
21802          * Temporary for use in computing hit areas with transformed views
21803          */
21804         final RectF mTmpTransformRect = new RectF();
21805 
21806         /**
21807          * Temporary for use in computing hit areas with transformed views
21808          */
21809         final RectF mTmpTransformRect1 = new RectF();
21810 
21811         /**
21812          * Temporary list of rectanges.
21813          */
21814         final List<RectF> mTmpRectList = new ArrayList<>();
21815 
21816         /**
21817          * Temporary for use in transforming invalidation rect
21818          */
21819         final Matrix mTmpMatrix = new Matrix();
21820 
21821         /**
21822          * Temporary for use in transforming invalidation rect
21823          */
21824         final Transformation mTmpTransformation = new Transformation();
21825 
21826         /**
21827          * Temporary for use in querying outlines from OutlineProviders
21828          */
21829         final Outline mTmpOutline = new Outline();
21830 
21831         /**
21832          * Temporary list for use in collecting focusable descendents of a view.
21833          */
21834         final ArrayList<View> mTempArrayList = new ArrayList<View>(24);
21835 
21836         /**
21837          * The id of the window for accessibility purposes.
21838          */
21839         int mAccessibilityWindowId = AccessibilityNodeInfo.UNDEFINED_ITEM_ID;
21840 
21841         /**
21842          * Flags related to accessibility processing.
21843          *
21844          * @see AccessibilityNodeInfo#FLAG_INCLUDE_NOT_IMPORTANT_VIEWS
21845          * @see AccessibilityNodeInfo#FLAG_REPORT_VIEW_IDS
21846          */
21847         int mAccessibilityFetchFlags;
21848 
21849         /**
21850          * The drawable for highlighting accessibility focus.
21851          */
21852         Drawable mAccessibilityFocusDrawable;
21853 
21854         /**
21855          * Show where the margins, bounds and layout bounds are for each view.
21856          */
21857         boolean mDebugLayout = SystemProperties.getBoolean(DEBUG_LAYOUT_PROPERTY, false);
21858 
21859         /**
21860          * Point used to compute visible regions.
21861          */
21862         final Point mPoint = new Point();
21863 
21864         /**
21865          * Used to track which View originated a requestLayout() call, used when
21866          * requestLayout() is called during layout.
21867          */
21868         View mViewRequestingLayout;
21869 
21870         /**
21871          * Creates a new set of attachment information with the specified
21872          * events handler and thread.
21873          *
21874          * @param handler the events handler the view must use
21875          */
21876         AttachInfo(IWindowSession session, IWindow window, Display display,
21877                 ViewRootImpl viewRootImpl, Handler handler, Callbacks effectPlayer) {
21878             mSession = session;
21879             mWindow = window;
21880             mWindowToken = window.asBinder();
21881             mDisplay = display;
21882             mViewRootImpl = viewRootImpl;
21883             mHandler = handler;
21884             mRootCallbacks = effectPlayer;
21885         }
21886     }
21887 
21888     /**
21889      * <p>ScrollabilityCache holds various fields used by a View when scrolling
21890      * is supported. This avoids keeping too many unused fields in most
21891      * instances of View.</p>
21892      */
21893     private static class ScrollabilityCache implements Runnable {
21894 
21895         /**
21896          * Scrollbars are not visible
21897          */
21898         public static final int OFF = 0;
21899 
21900         /**
21901          * Scrollbars are visible
21902          */
21903         public static final int ON = 1;
21904 
21905         /**
21906          * Scrollbars are fading away
21907          */
21908         public static final int FADING = 2;
21909 
21910         public boolean fadeScrollBars;
21911 
21912         public int fadingEdgeLength;
21913         public int scrollBarDefaultDelayBeforeFade;
21914         public int scrollBarFadeDuration;
21915 
21916         public int scrollBarSize;
21917         public ScrollBarDrawable scrollBar;
21918         public float[] interpolatorValues;
21919         public View host;
21920 
21921         public final Paint paint;
21922         public final Matrix matrix;
21923         public Shader shader;
21924 
21925         public final Interpolator scrollBarInterpolator = new Interpolator(1, 2);
21926 
21927         private static final float[] OPAQUE = { 255 };
21928         private static final float[] TRANSPARENT = { 0.0f };
21929 
21930         /**
21931          * When fading should start. This time moves into the future every time
21932          * a new scroll happens. Measured based on SystemClock.uptimeMillis()
21933          */
21934         public long fadeStartTime;
21935 
21936 
21937         /**
21938          * The current state of the scrollbars: ON, OFF, or FADING
21939          */
21940         public int state = OFF;
21941 
21942         private int mLastColor;
21943 
21944         public ScrollabilityCache(ViewConfiguration configuration, View host) {
21945             fadingEdgeLength = configuration.getScaledFadingEdgeLength();
21946             scrollBarSize = configuration.getScaledScrollBarSize();
21947             scrollBarDefaultDelayBeforeFade = ViewConfiguration.getScrollDefaultDelay();
21948             scrollBarFadeDuration = ViewConfiguration.getScrollBarFadeDuration();
21949 
21950             paint = new Paint();
21951             matrix = new Matrix();
21952             // use use a height of 1, and then wack the matrix each time we
21953             // actually use it.
21954             shader = new LinearGradient(0, 0, 0, 1, 0xFF000000, 0, Shader.TileMode.CLAMP);
21955             paint.setShader(shader);
21956             paint.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.DST_OUT));
21957 
21958             this.host = host;
21959         }
21960 
21961         public void setFadeColor(int color) {
21962             if (color != mLastColor) {
21963                 mLastColor = color;
21964 
21965                 if (color != 0) {
21966                     shader = new LinearGradient(0, 0, 0, 1, color | 0xFF000000,
21967                             color & 0x00FFFFFF, Shader.TileMode.CLAMP);
21968                     paint.setShader(shader);
21969                     // Restore the default transfer mode (src_over)
21970                     paint.setXfermode(null);
21971                 } else {
21972                     shader = new LinearGradient(0, 0, 0, 1, 0xFF000000, 0, Shader.TileMode.CLAMP);
21973                     paint.setShader(shader);
21974                     paint.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.DST_OUT));
21975                 }
21976             }
21977         }
21978 
21979         public void run() {
21980             long now = AnimationUtils.currentAnimationTimeMillis();
21981             if (now >= fadeStartTime) {
21982 
21983                 // the animation fades the scrollbars out by changing
21984                 // the opacity (alpha) from fully opaque to fully
21985                 // transparent
21986                 int nextFrame = (int) now;
21987                 int framesCount = 0;
21988 
21989                 Interpolator interpolator = scrollBarInterpolator;
21990 
21991                 // Start opaque
21992                 interpolator.setKeyFrame(framesCount++, nextFrame, OPAQUE);
21993 
21994                 // End transparent
21995                 nextFrame += scrollBarFadeDuration;
21996                 interpolator.setKeyFrame(framesCount, nextFrame, TRANSPARENT);
21997 
21998                 state = FADING;
21999 
22000                 // Kick off the fade animation
22001                 host.invalidate(true);
22002             }
22003         }
22004     }
22005 
22006     /**
22007      * Resuable callback for sending
22008      * {@link AccessibilityEvent#TYPE_VIEW_SCROLLED} accessibility event.
22009      */
22010     private class SendViewScrolledAccessibilityEvent implements Runnable {
22011         public volatile boolean mIsPending;
22012 
22013         public void run() {
22014             sendAccessibilityEvent(AccessibilityEvent.TYPE_VIEW_SCROLLED);
22015             mIsPending = false;
22016         }
22017     }
22018 
22019     /**
22020      * <p>
22021      * This class represents a delegate that can be registered in a {@link View}
22022      * to enhance accessibility support via composition rather via inheritance.
22023      * It is specifically targeted to widget developers that extend basic View
22024      * classes i.e. classes in package android.view, that would like their
22025      * applications to be backwards compatible.
22026      * </p>
22027      * <div class="special reference">
22028      * <h3>Developer Guides</h3>
22029      * <p>For more information about making applications accessible, read the
22030      * <a href="{@docRoot}guide/topics/ui/accessibility/index.html">Accessibility</a>
22031      * developer guide.</p>
22032      * </div>
22033      * <p>
22034      * A scenario in which a developer would like to use an accessibility delegate
22035      * is overriding a method introduced in a later API version then the minimal API
22036      * version supported by the application. For example, the method
22037      * {@link View#onInitializeAccessibilityNodeInfo(AccessibilityNodeInfo)} is not available
22038      * in API version 4 when the accessibility APIs were first introduced. If a
22039      * developer would like his application to run on API version 4 devices (assuming
22040      * all other APIs used by the application are version 4 or lower) and take advantage
22041      * of this method, instead of overriding the method which would break the application's
22042      * backwards compatibility, he can override the corresponding method in this
22043      * delegate and register the delegate in the target View if the API version of
22044      * the system is high enough i.e. the API version is same or higher to the API
22045      * version that introduced
22046      * {@link View#onInitializeAccessibilityNodeInfo(AccessibilityNodeInfo)}.
22047      * </p>
22048      * <p>
22049      * Here is an example implementation:
22050      * </p>
22051      * <code><pre><p>
22052      * if (Build.VERSION.SDK_INT >= 14) {
22053      *     // If the API version is equal of higher than the version in
22054      *     // which onInitializeAccessibilityNodeInfo was introduced we
22055      *     // register a delegate with a customized implementation.
22056      *     View view = findViewById(R.id.view_id);
22057      *     view.setAccessibilityDelegate(new AccessibilityDelegate() {
22058      *         public void onInitializeAccessibilityNodeInfo(View host,
22059      *                 AccessibilityNodeInfo info) {
22060      *             // Let the default implementation populate the info.
22061      *             super.onInitializeAccessibilityNodeInfo(host, info);
22062      *             // Set some other information.
22063      *             info.setEnabled(host.isEnabled());
22064      *         }
22065      *     });
22066      * }
22067      * </code></pre></p>
22068      * <p>
22069      * This delegate contains methods that correspond to the accessibility methods
22070      * in View. If a delegate has been specified the implementation in View hands
22071      * off handling to the corresponding method in this delegate. The default
22072      * implementation the delegate methods behaves exactly as the corresponding
22073      * method in View for the case of no accessibility delegate been set. Hence,
22074      * to customize the behavior of a View method, clients can override only the
22075      * corresponding delegate method without altering the behavior of the rest
22076      * accessibility related methods of the host view.
22077      * </p>
22078      */
22079     public static class AccessibilityDelegate {
22080 
22081         /**
22082          * Sends an accessibility event of the given type. If accessibility is not
22083          * enabled this method has no effect.
22084          * <p>
22085          * The default implementation behaves as {@link View#sendAccessibilityEvent(int)
22086          *  View#sendAccessibilityEvent(int)} for the case of no accessibility delegate
22087          * been set.
22088          * </p>
22089          *
22090          * @param host The View hosting the delegate.
22091          * @param eventType The type of the event to send.
22092          *
22093          * @see View#sendAccessibilityEvent(int) View#sendAccessibilityEvent(int)
22094          */
22095         public void sendAccessibilityEvent(View host, int eventType) {
22096             host.sendAccessibilityEventInternal(eventType);
22097         }
22098 
22099         /**
22100          * Performs the specified accessibility action on the view. For
22101          * possible accessibility actions look at {@link AccessibilityNodeInfo}.
22102          * <p>
22103          * The default implementation behaves as
22104          * {@link View#performAccessibilityAction(int, Bundle)
22105          *  View#performAccessibilityAction(int, Bundle)} for the case of
22106          *  no accessibility delegate been set.
22107          * </p>
22108          *
22109          * @param action The action to perform.
22110          * @return Whether the action was performed.
22111          *
22112          * @see View#performAccessibilityAction(int, Bundle)
22113          *      View#performAccessibilityAction(int, Bundle)
22114          */
22115         public boolean performAccessibilityAction(View host, int action, Bundle args) {
22116             return host.performAccessibilityActionInternal(action, args);
22117         }
22118 
22119         /**
22120          * Sends an accessibility event. This method behaves exactly as
22121          * {@link #sendAccessibilityEvent(View, int)} but takes as an argument an
22122          * empty {@link AccessibilityEvent} and does not perform a check whether
22123          * accessibility is enabled.
22124          * <p>
22125          * The default implementation behaves as
22126          * {@link View#sendAccessibilityEventUnchecked(AccessibilityEvent)
22127          *  View#sendAccessibilityEventUnchecked(AccessibilityEvent)} for
22128          * the case of no accessibility delegate been set.
22129          * </p>
22130          *
22131          * @param host The View hosting the delegate.
22132          * @param event The event to send.
22133          *
22134          * @see View#sendAccessibilityEventUnchecked(AccessibilityEvent)
22135          *      View#sendAccessibilityEventUnchecked(AccessibilityEvent)
22136          */
22137         public void sendAccessibilityEventUnchecked(View host, AccessibilityEvent event) {
22138             host.sendAccessibilityEventUncheckedInternal(event);
22139         }
22140 
22141         /**
22142          * Dispatches an {@link AccessibilityEvent} to the host {@link View} first and then
22143          * to its children for adding their text content to the event.
22144          * <p>
22145          * The default implementation behaves as
22146          * {@link View#dispatchPopulateAccessibilityEvent(AccessibilityEvent)
22147          *  View#dispatchPopulateAccessibilityEvent(AccessibilityEvent)} for
22148          * the case of no accessibility delegate been set.
22149          * </p>
22150          *
22151          * @param host The View hosting the delegate.
22152          * @param event The event.
22153          * @return True if the event population was completed.
22154          *
22155          * @see View#dispatchPopulateAccessibilityEvent(AccessibilityEvent)
22156          *      View#dispatchPopulateAccessibilityEvent(AccessibilityEvent)
22157          */
22158         public boolean dispatchPopulateAccessibilityEvent(View host, AccessibilityEvent event) {
22159             return host.dispatchPopulateAccessibilityEventInternal(event);
22160         }
22161 
22162         /**
22163          * Gives a chance to the host View to populate the accessibility event with its
22164          * text content.
22165          * <p>
22166          * The default implementation behaves as
22167          * {@link View#onPopulateAccessibilityEvent(AccessibilityEvent)
22168          *  View#onPopulateAccessibilityEvent(AccessibilityEvent)} for
22169          * the case of no accessibility delegate been set.
22170          * </p>
22171          *
22172          * @param host The View hosting the delegate.
22173          * @param event The accessibility event which to populate.
22174          *
22175          * @see View#onPopulateAccessibilityEvent(AccessibilityEvent)
22176          *      View#onPopulateAccessibilityEvent(AccessibilityEvent)
22177          */
22178         public void onPopulateAccessibilityEvent(View host, AccessibilityEvent event) {
22179             host.onPopulateAccessibilityEventInternal(event);
22180         }
22181 
22182         /**
22183          * Initializes an {@link AccessibilityEvent} with information about the
22184          * the host View which is the event source.
22185          * <p>
22186          * The default implementation behaves as
22187          * {@link View#onInitializeAccessibilityEvent(AccessibilityEvent)
22188          *  View#onInitializeAccessibilityEvent(AccessibilityEvent)} for
22189          * the case of no accessibility delegate been set.
22190          * </p>
22191          *
22192          * @param host The View hosting the delegate.
22193          * @param event The event to initialize.
22194          *
22195          * @see View#onInitializeAccessibilityEvent(AccessibilityEvent)
22196          *      View#onInitializeAccessibilityEvent(AccessibilityEvent)
22197          */
22198         public void onInitializeAccessibilityEvent(View host, AccessibilityEvent event) {
22199             host.onInitializeAccessibilityEventInternal(event);
22200         }
22201 
22202         /**
22203          * Initializes an {@link AccessibilityNodeInfo} with information about the host view.
22204          * <p>
22205          * The default implementation behaves as
22206          * {@link View#onInitializeAccessibilityNodeInfo(AccessibilityNodeInfo)
22207          *  View#onInitializeAccessibilityNodeInfo(AccessibilityNodeInfo)} for
22208          * the case of no accessibility delegate been set.
22209          * </p>
22210          *
22211          * @param host The View hosting the delegate.
22212          * @param info The instance to initialize.
22213          *
22214          * @see View#onInitializeAccessibilityNodeInfo(AccessibilityNodeInfo)
22215          *      View#onInitializeAccessibilityNodeInfo(AccessibilityNodeInfo)
22216          */
22217         public void onInitializeAccessibilityNodeInfo(View host, AccessibilityNodeInfo info) {
22218             host.onInitializeAccessibilityNodeInfoInternal(info);
22219         }
22220 
22221         /**
22222          * Called when a child of the host View has requested sending an
22223          * {@link AccessibilityEvent} and gives an opportunity to the parent (the host)
22224          * to augment the event.
22225          * <p>
22226          * The default implementation behaves as
22227          * {@link ViewGroup#onRequestSendAccessibilityEvent(View, AccessibilityEvent)
22228          *  ViewGroup#onRequestSendAccessibilityEvent(View, AccessibilityEvent)} for
22229          * the case of no accessibility delegate been set.
22230          * </p>
22231          *
22232          * @param host The View hosting the delegate.
22233          * @param child The child which requests sending the event.
22234          * @param event The event to be sent.
22235          * @return True if the event should be sent
22236          *
22237          * @see ViewGroup#onRequestSendAccessibilityEvent(View, AccessibilityEvent)
22238          *      ViewGroup#onRequestSendAccessibilityEvent(View, AccessibilityEvent)
22239          */
22240         public boolean onRequestSendAccessibilityEvent(ViewGroup host, View child,
22241                 AccessibilityEvent event) {
22242             return host.onRequestSendAccessibilityEventInternal(child, event);
22243         }
22244 
22245         /**
22246          * Gets the provider for managing a virtual view hierarchy rooted at this View
22247          * and reported to {@link android.accessibilityservice.AccessibilityService}s
22248          * that explore the window content.
22249          * <p>
22250          * The default implementation behaves as
22251          * {@link View#getAccessibilityNodeProvider() View#getAccessibilityNodeProvider()} for
22252          * the case of no accessibility delegate been set.
22253          * </p>
22254          *
22255          * @return The provider.
22256          *
22257          * @see AccessibilityNodeProvider
22258          */
22259         public AccessibilityNodeProvider getAccessibilityNodeProvider(View host) {
22260             return null;
22261         }
22262 
22263         /**
22264          * Returns an {@link AccessibilityNodeInfo} representing the host view from the
22265          * point of view of an {@link android.accessibilityservice.AccessibilityService}.
22266          * This method is responsible for obtaining an accessibility node info from a
22267          * pool of reusable instances and calling
22268          * {@link #onInitializeAccessibilityNodeInfo(AccessibilityNodeInfo)} on the host
22269          * view to initialize the former.
22270          * <p>
22271          * <strong>Note:</strong> The client is responsible for recycling the obtained
22272          * instance by calling {@link AccessibilityNodeInfo#recycle()} to minimize object
22273          * creation.
22274          * </p>
22275          * <p>
22276          * The default implementation behaves as
22277          * {@link View#createAccessibilityNodeInfo() View#createAccessibilityNodeInfo()} for
22278          * the case of no accessibility delegate been set.
22279          * </p>
22280          * @return A populated {@link AccessibilityNodeInfo}.
22281          *
22282          * @see AccessibilityNodeInfo
22283          *
22284          * @hide
22285          */
22286         public AccessibilityNodeInfo createAccessibilityNodeInfo(View host) {
22287             return host.createAccessibilityNodeInfoInternal();
22288         }
22289     }
22290 
22291     private class MatchIdPredicate implements Predicate<View> {
22292         public int mId;
22293 
22294         @Override
22295         public boolean apply(View view) {
22296             return (view.mID == mId);
22297         }
22298     }
22299 
22300     private class MatchLabelForPredicate implements Predicate<View> {
22301         private int mLabeledId;
22302 
22303         @Override
22304         public boolean apply(View view) {
22305             return (view.mLabelForId == mLabeledId);
22306         }
22307     }
22308 
22309     private class SendViewStateChangedAccessibilityEvent implements Runnable {
22310         private int mChangeTypes = 0;
22311         private boolean mPosted;
22312         private boolean mPostedWithDelay;
22313         private long mLastEventTimeMillis;
22314 
22315         @Override
22316         public void run() {
22317             mPosted = false;
22318             mPostedWithDelay = false;
22319             mLastEventTimeMillis = SystemClock.uptimeMillis();
22320             if (AccessibilityManager.getInstance(mContext).isEnabled()) {
22321                 final AccessibilityEvent event = AccessibilityEvent.obtain();
22322                 event.setEventType(AccessibilityEvent.TYPE_WINDOW_CONTENT_CHANGED);
22323                 event.setContentChangeTypes(mChangeTypes);
22324                 sendAccessibilityEventUnchecked(event);
22325             }
22326             mChangeTypes = 0;
22327         }
22328 
22329         public void runOrPost(int changeType) {
22330             mChangeTypes |= changeType;
22331 
22332             // If this is a live region or the child of a live region, collect
22333             // all events from this frame and send them on the next frame.
22334             if (inLiveRegion()) {
22335                 // If we're already posted with a delay, remove that.
22336                 if (mPostedWithDelay) {
22337                     removeCallbacks(this);
22338                     mPostedWithDelay = false;
22339                 }
22340                 // Only post if we're not already posted.
22341                 if (!mPosted) {
22342                     post(this);
22343                     mPosted = true;
22344                 }
22345                 return;
22346             }
22347 
22348             if (mPosted) {
22349                 return;
22350             }
22351 
22352             final long timeSinceLastMillis = SystemClock.uptimeMillis() - mLastEventTimeMillis;
22353             final long minEventIntevalMillis =
22354                     ViewConfiguration.getSendRecurringAccessibilityEventsInterval();
22355             if (timeSinceLastMillis >= minEventIntevalMillis) {
22356                 removeCallbacks(this);
22357                 run();
22358             } else {
22359                 postDelayed(this, minEventIntevalMillis - timeSinceLastMillis);
22360                 mPostedWithDelay = true;
22361             }
22362         }
22363     }
22364 
22365     private boolean inLiveRegion() {
22366         if (getAccessibilityLiveRegion() != View.ACCESSIBILITY_LIVE_REGION_NONE) {
22367             return true;
22368         }
22369 
22370         ViewParent parent = getParent();
22371         while (parent instanceof View) {
22372             if (((View) parent).getAccessibilityLiveRegion()
22373                     != View.ACCESSIBILITY_LIVE_REGION_NONE) {
22374                 return true;
22375             }
22376             parent = parent.getParent();
22377         }
22378 
22379         return false;
22380     }
22381 
22382     /**
22383      * Dump all private flags in readable format, useful for documentation and
22384      * sanity checking.
22385      */
22386     private static void dumpFlags() {
22387         final HashMap<String, String> found = Maps.newHashMap();
22388         try {
22389             for (Field field : View.class.getDeclaredFields()) {
22390                 final int modifiers = field.getModifiers();
22391                 if (Modifier.isStatic(modifiers) && Modifier.isFinal(modifiers)) {
22392                     if (field.getType().equals(int.class)) {
22393                         final int value = field.getInt(null);
22394                         dumpFlag(found, field.getName(), value);
22395                     } else if (field.getType().equals(int[].class)) {
22396                         final int[] values = (int[]) field.get(null);
22397                         for (int i = 0; i < values.length; i++) {
22398                             dumpFlag(found, field.getName() + "[" + i + "]", values[i]);
22399                         }
22400                     }
22401                 }
22402             }
22403         } catch (IllegalAccessException e) {
22404             throw new RuntimeException(e);
22405         }
22406 
22407         final ArrayList<String> keys = Lists.newArrayList();
22408         keys.addAll(found.keySet());
22409         Collections.sort(keys);
22410         for (String key : keys) {
22411             Log.d(VIEW_LOG_TAG, found.get(key));
22412         }
22413     }
22414 
22415     private static void dumpFlag(HashMap<String, String> found, String name, int value) {
22416         // Sort flags by prefix, then by bits, always keeping unique keys
22417         final String bits = String.format("%32s", Integer.toBinaryString(value)).replace('0', ' ');
22418         final int prefix = name.indexOf('_');
22419         final String key = (prefix > 0 ? name.substring(0, prefix) : name) + bits + name;
22420         final String output = bits + " " + name;
22421         found.put(key, output);
22422     }
22423 
22424     /** {@hide} */
22425     public void encode(@NonNull ViewHierarchyEncoder stream) {
22426         stream.beginObject(this);
22427         encodeProperties(stream);
22428         stream.endObject();
22429     }
22430 
22431     /** {@hide} */
22432     @CallSuper
22433     protected void encodeProperties(@NonNull ViewHierarchyEncoder stream) {
22434         Object resolveId = ViewDebug.resolveId(getContext(), mID);
22435         if (resolveId instanceof String) {
22436             stream.addProperty("id", (String) resolveId);
22437         } else {
22438             stream.addProperty("id", mID);
22439         }
22440 
22441         stream.addProperty("misc:transformation.alpha",
22442                 mTransformationInfo != null ? mTransformationInfo.mAlpha : 0);
22443         stream.addProperty("misc:transitionName", getTransitionName());
22444 
22445         // layout
22446         stream.addProperty("layout:left", mLeft);
22447         stream.addProperty("layout:right", mRight);
22448         stream.addProperty("layout:top", mTop);
22449         stream.addProperty("layout:bottom", mBottom);
22450         stream.addProperty("layout:width", getWidth());
22451         stream.addProperty("layout:height", getHeight());
22452         stream.addProperty("layout:layoutDirection", getLayoutDirection());
22453         stream.addProperty("layout:layoutRtl", isLayoutRtl());
22454         stream.addProperty("layout:hasTransientState", hasTransientState());
22455         stream.addProperty("layout:baseline", getBaseline());
22456 
22457         // layout params
22458         ViewGroup.LayoutParams layoutParams = getLayoutParams();
22459         if (layoutParams != null) {
22460             stream.addPropertyKey("layoutParams");
22461             layoutParams.encode(stream);
22462         }
22463 
22464         // scrolling
22465         stream.addProperty("scrolling:scrollX", mScrollX);
22466         stream.addProperty("scrolling:scrollY", mScrollY);
22467 
22468         // padding
22469         stream.addProperty("padding:paddingLeft", mPaddingLeft);
22470         stream.addProperty("padding:paddingRight", mPaddingRight);
22471         stream.addProperty("padding:paddingTop", mPaddingTop);
22472         stream.addProperty("padding:paddingBottom", mPaddingBottom);
22473         stream.addProperty("padding:userPaddingRight", mUserPaddingRight);
22474         stream.addProperty("padding:userPaddingLeft", mUserPaddingLeft);
22475         stream.addProperty("padding:userPaddingBottom", mUserPaddingBottom);
22476         stream.addProperty("padding:userPaddingStart", mUserPaddingStart);
22477         stream.addProperty("padding:userPaddingEnd", mUserPaddingEnd);
22478 
22479         // measurement
22480         stream.addProperty("measurement:minHeight", mMinHeight);
22481         stream.addProperty("measurement:minWidth", mMinWidth);
22482         stream.addProperty("measurement:measuredWidth", mMeasuredWidth);
22483         stream.addProperty("measurement:measuredHeight", mMeasuredHeight);
22484 
22485         // drawing
22486         stream.addProperty("drawing:elevation", getElevation());
22487         stream.addProperty("drawing:translationX", getTranslationX());
22488         stream.addProperty("drawing:translationY", getTranslationY());
22489         stream.addProperty("drawing:translationZ", getTranslationZ());
22490         stream.addProperty("drawing:rotation", getRotation());
22491         stream.addProperty("drawing:rotationX", getRotationX());
22492         stream.addProperty("drawing:rotationY", getRotationY());
22493         stream.addProperty("drawing:scaleX", getScaleX());
22494         stream.addProperty("drawing:scaleY", getScaleY());
22495         stream.addProperty("drawing:pivotX", getPivotX());
22496         stream.addProperty("drawing:pivotY", getPivotY());
22497         stream.addProperty("drawing:opaque", isOpaque());
22498         stream.addProperty("drawing:alpha", getAlpha());
22499         stream.addProperty("drawing:transitionAlpha", getTransitionAlpha());
22500         stream.addProperty("drawing:shadow", hasShadow());
22501         stream.addProperty("drawing:solidColor", getSolidColor());
22502         stream.addProperty("drawing:layerType", mLayerType);
22503         stream.addProperty("drawing:willNotDraw", willNotDraw());
22504         stream.addProperty("drawing:hardwareAccelerated", isHardwareAccelerated());
22505         stream.addProperty("drawing:willNotCacheDrawing", willNotCacheDrawing());
22506         stream.addProperty("drawing:drawingCacheEnabled", isDrawingCacheEnabled());
22507         stream.addProperty("drawing:overlappingRendering", hasOverlappingRendering());
22508 
22509         // focus
22510         stream.addProperty("focus:hasFocus", hasFocus());
22511         stream.addProperty("focus:isFocused", isFocused());
22512         stream.addProperty("focus:isFocusable", isFocusable());
22513         stream.addProperty("focus:isFocusableInTouchMode", isFocusableInTouchMode());
22514 
22515         stream.addProperty("misc:clickable", isClickable());
22516         stream.addProperty("misc:pressed", isPressed());
22517         stream.addProperty("misc:selected", isSelected());
22518         stream.addProperty("misc:touchMode", isInTouchMode());
22519         stream.addProperty("misc:hovered", isHovered());
22520         stream.addProperty("misc:activated", isActivated());
22521 
22522         stream.addProperty("misc:visibility", getVisibility());
22523         stream.addProperty("misc:fitsSystemWindows", getFitsSystemWindows());
22524         stream.addProperty("misc:filterTouchesWhenObscured", getFilterTouchesWhenObscured());
22525 
22526         stream.addProperty("misc:enabled", isEnabled());
22527         stream.addProperty("misc:soundEffectsEnabled", isSoundEffectsEnabled());
22528         stream.addProperty("misc:hapticFeedbackEnabled", isHapticFeedbackEnabled());
22529 
22530         // theme attributes
22531         Resources.Theme theme = getContext().getTheme();
22532         if (theme != null) {
22533             stream.addPropertyKey("theme");
22534             theme.encode(stream);
22535         }
22536 
22537         // view attribute information
22538         int n = mAttributes != null ? mAttributes.length : 0;
22539         stream.addProperty("meta:__attrCount__", n/2);
22540         for (int i = 0; i < n; i += 2) {
22541             stream.addProperty("meta:__attr__" + mAttributes[i], mAttributes[i+1]);
22542         }
22543 
22544         stream.addProperty("misc:scrollBarStyle", getScrollBarStyle());
22545 
22546         // text
22547         stream.addProperty("text:textDirection", getTextDirection());
22548         stream.addProperty("text:textAlignment", getTextAlignment());
22549 
22550         // accessibility
22551         CharSequence contentDescription = getContentDescription();
22552         stream.addProperty("accessibility:contentDescription",
22553                 contentDescription == null ? "" : contentDescription.toString());
22554         stream.addProperty("accessibility:labelFor", getLabelFor());
22555         stream.addProperty("accessibility:importantForAccessibility", getImportantForAccessibility());
22556     }
22557 }
22558