View.java revision 3bef5e9f3aa90465ee3ab66ef33d7a88d1b0c5c1
1/*
2 * Copyright (C) 2006 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 *      http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17package android.view;
18
19import android.content.ClipData;
20import android.content.Context;
21import android.content.res.Configuration;
22import android.content.res.Resources;
23import android.content.res.TypedArray;
24import android.graphics.Bitmap;
25import android.graphics.Camera;
26import android.graphics.Canvas;
27import android.graphics.Interpolator;
28import android.graphics.LinearGradient;
29import android.graphics.Matrix;
30import android.graphics.Paint;
31import android.graphics.PixelFormat;
32import android.graphics.Point;
33import android.graphics.PorterDuff;
34import android.graphics.PorterDuffXfermode;
35import android.graphics.Rect;
36import android.graphics.RectF;
37import android.graphics.Region;
38import android.graphics.Shader;
39import android.graphics.drawable.ColorDrawable;
40import android.graphics.drawable.Drawable;
41import android.os.Handler;
42import android.os.IBinder;
43import android.os.Parcel;
44import android.os.Parcelable;
45import android.os.RemoteException;
46import android.os.SystemClock;
47import android.text.TextUtils;
48import android.util.AttributeSet;
49import android.util.FloatProperty;
50import android.util.LocaleUtil;
51import android.util.Log;
52import android.util.Pool;
53import android.util.Poolable;
54import android.util.PoolableManager;
55import android.util.Pools;
56import android.util.Property;
57import android.util.SparseArray;
58import android.util.TypedValue;
59import android.view.ContextMenu.ContextMenuInfo;
60import android.view.accessibility.AccessibilityEvent;
61import android.view.accessibility.AccessibilityEventSource;
62import android.view.accessibility.AccessibilityManager;
63import android.view.accessibility.AccessibilityNodeInfo;
64import android.view.accessibility.AccessibilityNodeProvider;
65import android.view.animation.Animation;
66import android.view.animation.AnimationUtils;
67import android.view.animation.Transformation;
68import android.view.inputmethod.EditorInfo;
69import android.view.inputmethod.InputConnection;
70import android.view.inputmethod.InputMethodManager;
71import android.widget.ScrollBarDrawable;
72
73import static android.os.Build.VERSION_CODES.*;
74
75import com.android.internal.R;
76import com.android.internal.util.Predicate;
77import com.android.internal.view.menu.MenuBuilder;
78
79import java.lang.ref.WeakReference;
80import java.lang.reflect.InvocationTargetException;
81import java.lang.reflect.Method;
82import java.util.ArrayList;
83import java.util.Arrays;
84import java.util.Locale;
85import java.util.concurrent.CopyOnWriteArrayList;
86
87/**
88 * <p>
89 * This class represents the basic building block for user interface components. A View
90 * occupies a rectangular area on the screen and is responsible for drawing and
91 * event handling. View is the base class for <em>widgets</em>, which are
92 * used to create interactive UI components (buttons, text fields, etc.). The
93 * {@link android.view.ViewGroup} subclass is the base class for <em>layouts</em>, which
94 * are invisible containers that hold other Views (or other ViewGroups) and define
95 * their layout properties.
96 * </p>
97 *
98 * <div class="special reference">
99 * <h3>Developer Guides</h3>
100 * <p>For information about using this class to develop your application's user interface,
101 * read the <a href="{@docRoot}guide/topics/ui/index.html">User Interface</a> developer guide.
102 * </div>
103 *
104 * <a name="Using"></a>
105 * <h3>Using Views</h3>
106 * <p>
107 * All of the views in a window are arranged in a single tree. You can add views
108 * either from code or by specifying a tree of views in one or more XML layout
109 * files. There are many specialized subclasses of views that act as controls or
110 * are capable of displaying text, images, or other content.
111 * </p>
112 * <p>
113 * Once you have created a tree of views, there are typically a few types of
114 * common operations you may wish to perform:
115 * <ul>
116 * <li><strong>Set properties:</strong> for example setting the text of a
117 * {@link android.widget.TextView}. The available properties and the methods
118 * that set them will vary among the different subclasses of views. Note that
119 * properties that are known at build time can be set in the XML layout
120 * files.</li>
121 * <li><strong>Set focus:</strong> The framework will handled moving focus in
122 * response to user input. To force focus to a specific view, call
123 * {@link #requestFocus}.</li>
124 * <li><strong>Set up listeners:</strong> Views allow clients to set listeners
125 * that will be notified when something interesting happens to the view. For
126 * example, all views will let you set a listener to be notified when the view
127 * gains or loses focus. You can register such a listener using
128 * {@link #setOnFocusChangeListener(android.view.View.OnFocusChangeListener)}.
129 * Other view subclasses offer more specialized listeners. For example, a Button
130 * exposes a listener to notify clients when the button is clicked.</li>
131 * <li><strong>Set visibility:</strong> You can hide or show views using
132 * {@link #setVisibility(int)}.</li>
133 * </ul>
134 * </p>
135 * <p><em>
136 * Note: The Android framework is responsible for measuring, laying out and
137 * drawing views. You should not call methods that perform these actions on
138 * views yourself unless you are actually implementing a
139 * {@link android.view.ViewGroup}.
140 * </em></p>
141 *
142 * <a name="Lifecycle"></a>
143 * <h3>Implementing a Custom View</h3>
144 *
145 * <p>
146 * To implement a custom view, you will usually begin by providing overrides for
147 * some of the standard methods that the framework calls on all views. You do
148 * not need to override all of these methods. In fact, you can start by just
149 * overriding {@link #onDraw(android.graphics.Canvas)}.
150 * <table border="2" width="85%" align="center" cellpadding="5">
151 *     <thead>
152 *         <tr><th>Category</th> <th>Methods</th> <th>Description</th></tr>
153 *     </thead>
154 *
155 *     <tbody>
156 *     <tr>
157 *         <td rowspan="2">Creation</td>
158 *         <td>Constructors</td>
159 *         <td>There is a form of the constructor that are called when the view
160 *         is created from code and a form that is called when the view is
161 *         inflated from a layout file. The second form should parse and apply
162 *         any attributes defined in the layout file.
163 *         </td>
164 *     </tr>
165 *     <tr>
166 *         <td><code>{@link #onFinishInflate()}</code></td>
167 *         <td>Called after a view and all of its children has been inflated
168 *         from XML.</td>
169 *     </tr>
170 *
171 *     <tr>
172 *         <td rowspan="3">Layout</td>
173 *         <td><code>{@link #onMeasure(int, int)}</code></td>
174 *         <td>Called to determine the size requirements for this view and all
175 *         of its children.
176 *         </td>
177 *     </tr>
178 *     <tr>
179 *         <td><code>{@link #onLayout(boolean, int, int, int, int)}</code></td>
180 *         <td>Called when this view should assign a size and position to all
181 *         of its children.
182 *         </td>
183 *     </tr>
184 *     <tr>
185 *         <td><code>{@link #onSizeChanged(int, int, int, int)}</code></td>
186 *         <td>Called when the size of this view has changed.
187 *         </td>
188 *     </tr>
189 *
190 *     <tr>
191 *         <td>Drawing</td>
192 *         <td><code>{@link #onDraw(android.graphics.Canvas)}</code></td>
193 *         <td>Called when the view should render its content.
194 *         </td>
195 *     </tr>
196 *
197 *     <tr>
198 *         <td rowspan="4">Event processing</td>
199 *         <td><code>{@link #onKeyDown(int, KeyEvent)}</code></td>
200 *         <td>Called when a new key event occurs.
201 *         </td>
202 *     </tr>
203 *     <tr>
204 *         <td><code>{@link #onKeyUp(int, KeyEvent)}</code></td>
205 *         <td>Called when a key up event occurs.
206 *         </td>
207 *     </tr>
208 *     <tr>
209 *         <td><code>{@link #onTrackballEvent(MotionEvent)}</code></td>
210 *         <td>Called when a trackball motion event occurs.
211 *         </td>
212 *     </tr>
213 *     <tr>
214 *         <td><code>{@link #onTouchEvent(MotionEvent)}</code></td>
215 *         <td>Called when a touch screen motion event occurs.
216 *         </td>
217 *     </tr>
218 *
219 *     <tr>
220 *         <td rowspan="2">Focus</td>
221 *         <td><code>{@link #onFocusChanged(boolean, int, android.graphics.Rect)}</code></td>
222 *         <td>Called when the view gains or loses focus.
223 *         </td>
224 *     </tr>
225 *
226 *     <tr>
227 *         <td><code>{@link #onWindowFocusChanged(boolean)}</code></td>
228 *         <td>Called when the window containing the view gains or loses focus.
229 *         </td>
230 *     </tr>
231 *
232 *     <tr>
233 *         <td rowspan="3">Attaching</td>
234 *         <td><code>{@link #onAttachedToWindow()}</code></td>
235 *         <td>Called when the view is attached to a window.
236 *         </td>
237 *     </tr>
238 *
239 *     <tr>
240 *         <td><code>{@link #onDetachedFromWindow}</code></td>
241 *         <td>Called when the view is detached from its window.
242 *         </td>
243 *     </tr>
244 *
245 *     <tr>
246 *         <td><code>{@link #onWindowVisibilityChanged(int)}</code></td>
247 *         <td>Called when the visibility of the window containing the view
248 *         has changed.
249 *         </td>
250 *     </tr>
251 *     </tbody>
252 *
253 * </table>
254 * </p>
255 *
256 * <a name="IDs"></a>
257 * <h3>IDs</h3>
258 * Views may have an integer id associated with them. These ids are typically
259 * assigned in the layout XML files, and are used to find specific views within
260 * the view tree. A common pattern is to:
261 * <ul>
262 * <li>Define a Button in the layout file and assign it a unique ID.
263 * <pre>
264 * &lt;Button
265 *     android:id="@+id/my_button"
266 *     android:layout_width="wrap_content"
267 *     android:layout_height="wrap_content"
268 *     android:text="@string/my_button_text"/&gt;
269 * </pre></li>
270 * <li>From the onCreate method of an Activity, find the Button
271 * <pre class="prettyprint">
272 *      Button myButton = (Button) findViewById(R.id.my_button);
273 * </pre></li>
274 * </ul>
275 * <p>
276 * View IDs need not be unique throughout the tree, but it is good practice to
277 * ensure that they are at least unique within the part of the tree you are
278 * searching.
279 * </p>
280 *
281 * <a name="Position"></a>
282 * <h3>Position</h3>
283 * <p>
284 * The geometry of a view is that of a rectangle. A view has a location,
285 * expressed as a pair of <em>left</em> and <em>top</em> coordinates, and
286 * two dimensions, expressed as a width and a height. The unit for location
287 * and dimensions is the pixel.
288 * </p>
289 *
290 * <p>
291 * It is possible to retrieve the location of a view by invoking the methods
292 * {@link #getLeft()} and {@link #getTop()}. The former returns the left, or X,
293 * coordinate of the rectangle representing the view. The latter returns the
294 * top, or Y, coordinate of the rectangle representing the view. These methods
295 * both return the location of the view relative to its parent. For instance,
296 * when getLeft() returns 20, that means the view is located 20 pixels to the
297 * right of the left edge of its direct parent.
298 * </p>
299 *
300 * <p>
301 * In addition, several convenience methods are offered to avoid unnecessary
302 * computations, namely {@link #getRight()} and {@link #getBottom()}.
303 * These methods return the coordinates of the right and bottom edges of the
304 * rectangle representing the view. For instance, calling {@link #getRight()}
305 * is similar to the following computation: <code>getLeft() + getWidth()</code>
306 * (see <a href="#SizePaddingMargins">Size</a> for more information about the width.)
307 * </p>
308 *
309 * <a name="SizePaddingMargins"></a>
310 * <h3>Size, padding and margins</h3>
311 * <p>
312 * The size of a view is expressed with a width and a height. A view actually
313 * possess two pairs of width and height values.
314 * </p>
315 *
316 * <p>
317 * The first pair is known as <em>measured width</em> and
318 * <em>measured height</em>. These dimensions define how big a view wants to be
319 * within its parent (see <a href="#Layout">Layout</a> for more details.) The
320 * measured dimensions can be obtained by calling {@link #getMeasuredWidth()}
321 * and {@link #getMeasuredHeight()}.
322 * </p>
323 *
324 * <p>
325 * The second pair is simply known as <em>width</em> and <em>height</em>, or
326 * sometimes <em>drawing width</em> and <em>drawing height</em>. These
327 * dimensions define the actual size of the view on screen, at drawing time and
328 * after layout. These values may, but do not have to, be different from the
329 * measured width and height. The width and height can be obtained by calling
330 * {@link #getWidth()} and {@link #getHeight()}.
331 * </p>
332 *
333 * <p>
334 * To measure its dimensions, a view takes into account its padding. The padding
335 * is expressed in pixels for the left, top, right and bottom parts of the view.
336 * Padding can be used to offset the content of the view by a specific amount of
337 * pixels. For instance, a left padding of 2 will push the view's content by
338 * 2 pixels to the right of the left edge. Padding can be set using the
339 * {@link #setPadding(int, int, int, int)} method and queried by calling
340 * {@link #getPaddingLeft()}, {@link #getPaddingTop()},
341 * {@link #getPaddingRight()}, {@link #getPaddingBottom()}.
342 * </p>
343 *
344 * <p>
345 * Even though a view can define a padding, it does not provide any support for
346 * margins. However, view groups provide such a support. Refer to
347 * {@link android.view.ViewGroup} and
348 * {@link android.view.ViewGroup.MarginLayoutParams} for further information.
349 * </p>
350 *
351 * <a name="Layout"></a>
352 * <h3>Layout</h3>
353 * <p>
354 * Layout is a two pass process: a measure pass and a layout pass. The measuring
355 * pass is implemented in {@link #measure(int, int)} and is a top-down traversal
356 * of the view tree. Each view pushes dimension specifications down the tree
357 * during the recursion. At the end of the measure pass, every view has stored
358 * its measurements. The second pass happens in
359 * {@link #layout(int,int,int,int)} and is also top-down. During
360 * this pass each parent is responsible for positioning all of its children
361 * using the sizes computed in the measure pass.
362 * </p>
363 *
364 * <p>
365 * When a view's measure() method returns, its {@link #getMeasuredWidth()} and
366 * {@link #getMeasuredHeight()} values must be set, along with those for all of
367 * that view's descendants. A view's measured width and measured height values
368 * must respect the constraints imposed by the view's parents. This guarantees
369 * that at the end of the measure pass, all parents accept all of their
370 * children's measurements. A parent view may call measure() more than once on
371 * its children. For example, the parent may measure each child once with
372 * unspecified dimensions to find out how big they want to be, then call
373 * measure() on them again with actual numbers if the sum of all the children's
374 * unconstrained sizes is too big or too small.
375 * </p>
376 *
377 * <p>
378 * The measure pass uses two classes to communicate dimensions. The
379 * {@link MeasureSpec} class is used by views to tell their parents how they
380 * want to be measured and positioned. The base LayoutParams class just
381 * describes how big the view wants to be for both width and height. For each
382 * dimension, it can specify one of:
383 * <ul>
384 * <li> an exact number
385 * <li>MATCH_PARENT, which means the view wants to be as big as its parent
386 * (minus padding)
387 * <li> WRAP_CONTENT, which means that the view wants to be just big enough to
388 * enclose its content (plus padding).
389 * </ul>
390 * There are subclasses of LayoutParams for different subclasses of ViewGroup.
391 * For example, AbsoluteLayout has its own subclass of LayoutParams which adds
392 * an X and Y value.
393 * </p>
394 *
395 * <p>
396 * MeasureSpecs are used to push requirements down the tree from parent to
397 * child. A MeasureSpec can be in one of three modes:
398 * <ul>
399 * <li>UNSPECIFIED: This is used by a parent to determine the desired dimension
400 * of a child view. For example, a LinearLayout may call measure() on its child
401 * with the height set to UNSPECIFIED and a width of EXACTLY 240 to find out how
402 * tall the child view wants to be given a width of 240 pixels.
403 * <li>EXACTLY: This is used by the parent to impose an exact size on the
404 * child. The child must use this size, and guarantee that all of its
405 * descendants will fit within this size.
406 * <li>AT_MOST: This is used by the parent to impose a maximum size on the
407 * child. The child must gurantee that it and all of its descendants will fit
408 * within this size.
409 * </ul>
410 * </p>
411 *
412 * <p>
413 * To intiate a layout, call {@link #requestLayout}. This method is typically
414 * called by a view on itself when it believes that is can no longer fit within
415 * its current bounds.
416 * </p>
417 *
418 * <a name="Drawing"></a>
419 * <h3>Drawing</h3>
420 * <p>
421 * Drawing is handled by walking the tree and rendering each view that
422 * intersects the invalid region. Because the tree is traversed in-order,
423 * this means that parents will draw before (i.e., behind) their children, with
424 * siblings drawn in the order they appear in the tree.
425 * If you set a background drawable for a View, then the View will draw it for you
426 * before calling back to its <code>onDraw()</code> method.
427 * </p>
428 *
429 * <p>
430 * Note that the framework will not draw views that are not in the invalid region.
431 * </p>
432 *
433 * <p>
434 * To force a view to draw, call {@link #invalidate()}.
435 * </p>
436 *
437 * <a name="EventHandlingThreading"></a>
438 * <h3>Event Handling and Threading</h3>
439 * <p>
440 * The basic cycle of a view is as follows:
441 * <ol>
442 * <li>An event comes in and is dispatched to the appropriate view. The view
443 * handles the event and notifies any listeners.</li>
444 * <li>If in the course of processing the event, the view's bounds may need
445 * to be changed, the view will call {@link #requestLayout()}.</li>
446 * <li>Similarly, if in the course of processing the event the view's appearance
447 * may need to be changed, the view will call {@link #invalidate()}.</li>
448 * <li>If either {@link #requestLayout()} or {@link #invalidate()} were called,
449 * the framework will take care of measuring, laying out, and drawing the tree
450 * as appropriate.</li>
451 * </ol>
452 * </p>
453 *
454 * <p><em>Note: The entire view tree is single threaded. You must always be on
455 * the UI thread when calling any method on any view.</em>
456 * If you are doing work on other threads and want to update the state of a view
457 * from that thread, you should use a {@link Handler}.
458 * </p>
459 *
460 * <a name="FocusHandling"></a>
461 * <h3>Focus Handling</h3>
462 * <p>
463 * The framework will handle routine focus movement in response to user input.
464 * This includes changing the focus as views are removed or hidden, or as new
465 * views become available. Views indicate their willingness to take focus
466 * through the {@link #isFocusable} method. To change whether a view can take
467 * focus, call {@link #setFocusable(boolean)}.  When in touch mode (see notes below)
468 * views indicate whether they still would like focus via {@link #isFocusableInTouchMode}
469 * and can change this via {@link #setFocusableInTouchMode(boolean)}.
470 * </p>
471 * <p>
472 * Focus movement is based on an algorithm which finds the nearest neighbor in a
473 * given direction. In rare cases, the default algorithm may not match the
474 * intended behavior of the developer. In these situations, you can provide
475 * explicit overrides by using these XML attributes in the layout file:
476 * <pre>
477 * nextFocusDown
478 * nextFocusLeft
479 * nextFocusRight
480 * nextFocusUp
481 * </pre>
482 * </p>
483 *
484 *
485 * <p>
486 * To get a particular view to take focus, call {@link #requestFocus()}.
487 * </p>
488 *
489 * <a name="TouchMode"></a>
490 * <h3>Touch Mode</h3>
491 * <p>
492 * When a user is navigating a user interface via directional keys such as a D-pad, it is
493 * necessary to give focus to actionable items such as buttons so the user can see
494 * what will take input.  If the device has touch capabilities, however, and the user
495 * begins interacting with the interface by touching it, it is no longer necessary to
496 * always highlight, or give focus to, a particular view.  This motivates a mode
497 * for interaction named 'touch mode'.
498 * </p>
499 * <p>
500 * For a touch capable device, once the user touches the screen, the device
501 * will enter touch mode.  From this point onward, only views for which
502 * {@link #isFocusableInTouchMode} is true will be focusable, such as text editing widgets.
503 * Other views that are touchable, like buttons, will not take focus when touched; they will
504 * only fire the on click listeners.
505 * </p>
506 * <p>
507 * Any time a user hits a directional key, such as a D-pad direction, the view device will
508 * exit touch mode, and find a view to take focus, so that the user may resume interacting
509 * with the user interface without touching the screen again.
510 * </p>
511 * <p>
512 * The touch mode state is maintained across {@link android.app.Activity}s.  Call
513 * {@link #isInTouchMode} to see whether the device is currently in touch mode.
514 * </p>
515 *
516 * <a name="Scrolling"></a>
517 * <h3>Scrolling</h3>
518 * <p>
519 * The framework provides basic support for views that wish to internally
520 * scroll their content. This includes keeping track of the X and Y scroll
521 * offset as well as mechanisms for drawing scrollbars. See
522 * {@link #scrollBy(int, int)}, {@link #scrollTo(int, int)}, and
523 * {@link #awakenScrollBars()} for more details.
524 * </p>
525 *
526 * <a name="Tags"></a>
527 * <h3>Tags</h3>
528 * <p>
529 * Unlike IDs, tags are not used to identify views. Tags are essentially an
530 * extra piece of information that can be associated with a view. They are most
531 * often used as a convenience to store data related to views in the views
532 * themselves rather than by putting them in a separate structure.
533 * </p>
534 *
535 * <a name="Animation"></a>
536 * <h3>Animation</h3>
537 * <p>
538 * You can attach an {@link Animation} object to a view using
539 * {@link #setAnimation(Animation)} or
540 * {@link #startAnimation(Animation)}. The animation can alter the scale,
541 * rotation, translation and alpha of a view over time. If the animation is
542 * attached to a view that has children, the animation will affect the entire
543 * subtree rooted by that node. When an animation is started, the framework will
544 * take care of redrawing the appropriate views until the animation completes.
545 * </p>
546 * <p>
547 * Starting with Android 3.0, the preferred way of animating views is to use the
548 * {@link android.animation} package APIs.
549 * </p>
550 *
551 * <a name="Security"></a>
552 * <h3>Security</h3>
553 * <p>
554 * Sometimes it is essential that an application be able to verify that an action
555 * is being performed with the full knowledge and consent of the user, such as
556 * granting a permission request, making a purchase or clicking on an advertisement.
557 * Unfortunately, a malicious application could try to spoof the user into
558 * performing these actions, unaware, by concealing the intended purpose of the view.
559 * As a remedy, the framework offers a touch filtering mechanism that can be used to
560 * improve the security of views that provide access to sensitive functionality.
561 * </p><p>
562 * To enable touch filtering, call {@link #setFilterTouchesWhenObscured(boolean)} or set the
563 * android:filterTouchesWhenObscured layout attribute to true.  When enabled, the framework
564 * will discard touches that are received whenever the view's window is obscured by
565 * another visible window.  As a result, the view will not receive touches whenever a
566 * toast, dialog or other window appears above the view's window.
567 * </p><p>
568 * For more fine-grained control over security, consider overriding the
569 * {@link #onFilterTouchEventForSecurity(MotionEvent)} method to implement your own
570 * security policy. See also {@link MotionEvent#FLAG_WINDOW_IS_OBSCURED}.
571 * </p>
572 *
573 * @attr ref android.R.styleable#View_alpha
574 * @attr ref android.R.styleable#View_background
575 * @attr ref android.R.styleable#View_clickable
576 * @attr ref android.R.styleable#View_contentDescription
577 * @attr ref android.R.styleable#View_drawingCacheQuality
578 * @attr ref android.R.styleable#View_duplicateParentState
579 * @attr ref android.R.styleable#View_id
580 * @attr ref android.R.styleable#View_requiresFadingEdge
581 * @attr ref android.R.styleable#View_fadingEdgeLength
582 * @attr ref android.R.styleable#View_filterTouchesWhenObscured
583 * @attr ref android.R.styleable#View_fitsSystemWindows
584 * @attr ref android.R.styleable#View_isScrollContainer
585 * @attr ref android.R.styleable#View_focusable
586 * @attr ref android.R.styleable#View_focusableInTouchMode
587 * @attr ref android.R.styleable#View_hapticFeedbackEnabled
588 * @attr ref android.R.styleable#View_keepScreenOn
589 * @attr ref android.R.styleable#View_layerType
590 * @attr ref android.R.styleable#View_longClickable
591 * @attr ref android.R.styleable#View_minHeight
592 * @attr ref android.R.styleable#View_minWidth
593 * @attr ref android.R.styleable#View_nextFocusDown
594 * @attr ref android.R.styleable#View_nextFocusLeft
595 * @attr ref android.R.styleable#View_nextFocusRight
596 * @attr ref android.R.styleable#View_nextFocusUp
597 * @attr ref android.R.styleable#View_onClick
598 * @attr ref android.R.styleable#View_padding
599 * @attr ref android.R.styleable#View_paddingBottom
600 * @attr ref android.R.styleable#View_paddingLeft
601 * @attr ref android.R.styleable#View_paddingRight
602 * @attr ref android.R.styleable#View_paddingTop
603 * @attr ref android.R.styleable#View_paddingStart
604 * @attr ref android.R.styleable#View_paddingEnd
605 * @attr ref android.R.styleable#View_saveEnabled
606 * @attr ref android.R.styleable#View_rotation
607 * @attr ref android.R.styleable#View_rotationX
608 * @attr ref android.R.styleable#View_rotationY
609 * @attr ref android.R.styleable#View_scaleX
610 * @attr ref android.R.styleable#View_scaleY
611 * @attr ref android.R.styleable#View_scrollX
612 * @attr ref android.R.styleable#View_scrollY
613 * @attr ref android.R.styleable#View_scrollbarSize
614 * @attr ref android.R.styleable#View_scrollbarStyle
615 * @attr ref android.R.styleable#View_scrollbars
616 * @attr ref android.R.styleable#View_scrollbarDefaultDelayBeforeFade
617 * @attr ref android.R.styleable#View_scrollbarFadeDuration
618 * @attr ref android.R.styleable#View_scrollbarTrackHorizontal
619 * @attr ref android.R.styleable#View_scrollbarThumbHorizontal
620 * @attr ref android.R.styleable#View_scrollbarThumbVertical
621 * @attr ref android.R.styleable#View_scrollbarTrackVertical
622 * @attr ref android.R.styleable#View_scrollbarAlwaysDrawHorizontalTrack
623 * @attr ref android.R.styleable#View_scrollbarAlwaysDrawVerticalTrack
624 * @attr ref android.R.styleable#View_soundEffectsEnabled
625 * @attr ref android.R.styleable#View_tag
626 * @attr ref android.R.styleable#View_transformPivotX
627 * @attr ref android.R.styleable#View_transformPivotY
628 * @attr ref android.R.styleable#View_translationX
629 * @attr ref android.R.styleable#View_translationY
630 * @attr ref android.R.styleable#View_visibility
631 *
632 * @see android.view.ViewGroup
633 */
634public class View implements Drawable.Callback, Drawable.Callback2, KeyEvent.Callback,
635        AccessibilityEventSource {
636    private static final boolean DBG = false;
637
638    /**
639     * The logging tag used by this class with android.util.Log.
640     */
641    protected static final String VIEW_LOG_TAG = "View";
642
643    /**
644     * Used to mark a View that has no ID.
645     */
646    public static final int NO_ID = -1;
647
648    /**
649     * This view does not want keystrokes. Use with TAKES_FOCUS_MASK when
650     * calling setFlags.
651     */
652    private static final int NOT_FOCUSABLE = 0x00000000;
653
654    /**
655     * This view wants keystrokes. Use with TAKES_FOCUS_MASK when calling
656     * setFlags.
657     */
658    private static final int FOCUSABLE = 0x00000001;
659
660    /**
661     * Mask for use with setFlags indicating bits used for focus.
662     */
663    private static final int FOCUSABLE_MASK = 0x00000001;
664
665    /**
666     * This view will adjust its padding to fit sytem windows (e.g. status bar)
667     */
668    private static final int FITS_SYSTEM_WINDOWS = 0x00000002;
669
670    /**
671     * This view is visible.
672     * Use with {@link #setVisibility} and <a href="#attr_android:visibility">{@code
673     * android:visibility}.
674     */
675    public static final int VISIBLE = 0x00000000;
676
677    /**
678     * This view is invisible, but it still takes up space for layout purposes.
679     * Use with {@link #setVisibility} and <a href="#attr_android:visibility">{@code
680     * android:visibility}.
681     */
682    public static final int INVISIBLE = 0x00000004;
683
684    /**
685     * This view is invisible, and it doesn't take any space for layout
686     * purposes. Use with {@link #setVisibility} and <a href="#attr_android:visibility">{@code
687     * android:visibility}.
688     */
689    public static final int GONE = 0x00000008;
690
691    /**
692     * Mask for use with setFlags indicating bits used for visibility.
693     * {@hide}
694     */
695    static final int VISIBILITY_MASK = 0x0000000C;
696
697    private static final int[] VISIBILITY_FLAGS = {VISIBLE, INVISIBLE, GONE};
698
699    /**
700     * This view is enabled. Intrepretation varies by subclass.
701     * Use with ENABLED_MASK when calling setFlags.
702     * {@hide}
703     */
704    static final int ENABLED = 0x00000000;
705
706    /**
707     * This view is disabled. Intrepretation varies by subclass.
708     * Use with ENABLED_MASK when calling setFlags.
709     * {@hide}
710     */
711    static final int DISABLED = 0x00000020;
712
713   /**
714    * Mask for use with setFlags indicating bits used for indicating whether
715    * this view is enabled
716    * {@hide}
717    */
718    static final int ENABLED_MASK = 0x00000020;
719
720    /**
721     * This view won't draw. {@link #onDraw(android.graphics.Canvas)} won't be
722     * called and further optimizations will be performed. It is okay to have
723     * this flag set and a background. Use with DRAW_MASK when calling setFlags.
724     * {@hide}
725     */
726    static final int WILL_NOT_DRAW = 0x00000080;
727
728    /**
729     * Mask for use with setFlags indicating bits used for indicating whether
730     * this view is will draw
731     * {@hide}
732     */
733    static final int DRAW_MASK = 0x00000080;
734
735    /**
736     * <p>This view doesn't show scrollbars.</p>
737     * {@hide}
738     */
739    static final int SCROLLBARS_NONE = 0x00000000;
740
741    /**
742     * <p>This view shows horizontal scrollbars.</p>
743     * {@hide}
744     */
745    static final int SCROLLBARS_HORIZONTAL = 0x00000100;
746
747    /**
748     * <p>This view shows vertical scrollbars.</p>
749     * {@hide}
750     */
751    static final int SCROLLBARS_VERTICAL = 0x00000200;
752
753    /**
754     * <p>Mask for use with setFlags indicating bits used for indicating which
755     * scrollbars are enabled.</p>
756     * {@hide}
757     */
758    static final int SCROLLBARS_MASK = 0x00000300;
759
760    /**
761     * Indicates that the view should filter touches when its window is obscured.
762     * Refer to the class comments for more information about this security feature.
763     * {@hide}
764     */
765    static final int FILTER_TOUCHES_WHEN_OBSCURED = 0x00000400;
766
767    // note flag value 0x00000800 is now available for next flags...
768
769    /**
770     * <p>This view doesn't show fading edges.</p>
771     * {@hide}
772     */
773    static final int FADING_EDGE_NONE = 0x00000000;
774
775    /**
776     * <p>This view shows horizontal fading edges.</p>
777     * {@hide}
778     */
779    static final int FADING_EDGE_HORIZONTAL = 0x00001000;
780
781    /**
782     * <p>This view shows vertical fading edges.</p>
783     * {@hide}
784     */
785    static final int FADING_EDGE_VERTICAL = 0x00002000;
786
787    /**
788     * <p>Mask for use with setFlags indicating bits used for indicating which
789     * fading edges are enabled.</p>
790     * {@hide}
791     */
792    static final int FADING_EDGE_MASK = 0x00003000;
793
794    /**
795     * <p>Indicates this view can be clicked. When clickable, a View reacts
796     * to clicks by notifying the OnClickListener.<p>
797     * {@hide}
798     */
799    static final int CLICKABLE = 0x00004000;
800
801    /**
802     * <p>Indicates this view is caching its drawing into a bitmap.</p>
803     * {@hide}
804     */
805    static final int DRAWING_CACHE_ENABLED = 0x00008000;
806
807    /**
808     * <p>Indicates that no icicle should be saved for this view.<p>
809     * {@hide}
810     */
811    static final int SAVE_DISABLED = 0x000010000;
812
813    /**
814     * <p>Mask for use with setFlags indicating bits used for the saveEnabled
815     * property.</p>
816     * {@hide}
817     */
818    static final int SAVE_DISABLED_MASK = 0x000010000;
819
820    /**
821     * <p>Indicates that no drawing cache should ever be created for this view.<p>
822     * {@hide}
823     */
824    static final int WILL_NOT_CACHE_DRAWING = 0x000020000;
825
826    /**
827     * <p>Indicates this view can take / keep focus when int touch mode.</p>
828     * {@hide}
829     */
830    static final int FOCUSABLE_IN_TOUCH_MODE = 0x00040000;
831
832    /**
833     * <p>Enables low quality mode for the drawing cache.</p>
834     */
835    public static final int DRAWING_CACHE_QUALITY_LOW = 0x00080000;
836
837    /**
838     * <p>Enables high quality mode for the drawing cache.</p>
839     */
840    public static final int DRAWING_CACHE_QUALITY_HIGH = 0x00100000;
841
842    /**
843     * <p>Enables automatic quality mode for the drawing cache.</p>
844     */
845    public static final int DRAWING_CACHE_QUALITY_AUTO = 0x00000000;
846
847    private static final int[] DRAWING_CACHE_QUALITY_FLAGS = {
848            DRAWING_CACHE_QUALITY_AUTO, DRAWING_CACHE_QUALITY_LOW, DRAWING_CACHE_QUALITY_HIGH
849    };
850
851    /**
852     * <p>Mask for use with setFlags indicating bits used for the cache
853     * quality property.</p>
854     * {@hide}
855     */
856    static final int DRAWING_CACHE_QUALITY_MASK = 0x00180000;
857
858    /**
859     * <p>
860     * Indicates this view can be long clicked. When long clickable, a View
861     * reacts to long clicks by notifying the OnLongClickListener or showing a
862     * context menu.
863     * </p>
864     * {@hide}
865     */
866    static final int LONG_CLICKABLE = 0x00200000;
867
868    /**
869     * <p>Indicates that this view gets its drawable states from its direct parent
870     * and ignores its original internal states.</p>
871     *
872     * @hide
873     */
874    static final int DUPLICATE_PARENT_STATE = 0x00400000;
875
876    /**
877     * The scrollbar style to display the scrollbars inside the content area,
878     * without increasing the padding. The scrollbars will be overlaid with
879     * translucency on the view's content.
880     */
881    public static final int SCROLLBARS_INSIDE_OVERLAY = 0;
882
883    /**
884     * The scrollbar style to display the scrollbars inside the padded area,
885     * increasing the padding of the view. The scrollbars will not overlap the
886     * content area of the view.
887     */
888    public static final int SCROLLBARS_INSIDE_INSET = 0x01000000;
889
890    /**
891     * The scrollbar style to display the scrollbars at the edge of the view,
892     * without increasing the padding. The scrollbars will be overlaid with
893     * translucency.
894     */
895    public static final int SCROLLBARS_OUTSIDE_OVERLAY = 0x02000000;
896
897    /**
898     * The scrollbar style to display the scrollbars at the edge of the view,
899     * increasing the padding of the view. The scrollbars will only overlap the
900     * background, if any.
901     */
902    public static final int SCROLLBARS_OUTSIDE_INSET = 0x03000000;
903
904    /**
905     * Mask to check if the scrollbar style is overlay or inset.
906     * {@hide}
907     */
908    static final int SCROLLBARS_INSET_MASK = 0x01000000;
909
910    /**
911     * Mask to check if the scrollbar style is inside or outside.
912     * {@hide}
913     */
914    static final int SCROLLBARS_OUTSIDE_MASK = 0x02000000;
915
916    /**
917     * Mask for scrollbar style.
918     * {@hide}
919     */
920    static final int SCROLLBARS_STYLE_MASK = 0x03000000;
921
922    /**
923     * View flag indicating that the screen should remain on while the
924     * window containing this view is visible to the user.  This effectively
925     * takes care of automatically setting the WindowManager's
926     * {@link WindowManager.LayoutParams#FLAG_KEEP_SCREEN_ON}.
927     */
928    public static final int KEEP_SCREEN_ON = 0x04000000;
929
930    /**
931     * View flag indicating whether this view should have sound effects enabled
932     * for events such as clicking and touching.
933     */
934    public static final int SOUND_EFFECTS_ENABLED = 0x08000000;
935
936    /**
937     * View flag indicating whether this view should have haptic feedback
938     * enabled for events such as long presses.
939     */
940    public static final int HAPTIC_FEEDBACK_ENABLED = 0x10000000;
941
942    /**
943     * <p>Indicates that the view hierarchy should stop saving state when
944     * it reaches this view.  If state saving is initiated immediately at
945     * the view, it will be allowed.
946     * {@hide}
947     */
948    static final int PARENT_SAVE_DISABLED = 0x20000000;
949
950    /**
951     * <p>Mask for use with setFlags indicating bits used for PARENT_SAVE_DISABLED.</p>
952     * {@hide}
953     */
954    static final int PARENT_SAVE_DISABLED_MASK = 0x20000000;
955
956    /**
957     * Horizontal direction of this view is from Left to Right.
958     * Use with {@link #setLayoutDirection}.
959     */
960    public static final int LAYOUT_DIRECTION_LTR = 0x00000000;
961
962    /**
963     * Horizontal direction of this view is from Right to Left.
964     * Use with {@link #setLayoutDirection}.
965     */
966    public static final int LAYOUT_DIRECTION_RTL = 0x40000000;
967
968    /**
969     * Horizontal direction of this view is inherited from its parent.
970     * Use with {@link #setLayoutDirection}.
971     */
972    public static final int LAYOUT_DIRECTION_INHERIT = 0x80000000;
973
974    /**
975     * Horizontal direction of this view is from deduced from the default language
976     * script for the locale. Use with {@link #setLayoutDirection}.
977     */
978    public static final int LAYOUT_DIRECTION_LOCALE = 0xC0000000;
979
980    /**
981     * Mask for use with setFlags indicating bits used for horizontalDirection.
982     * {@hide}
983     */
984    static final int LAYOUT_DIRECTION_MASK = 0xC0000000;
985
986    /*
987     * Array of horizontal direction flags for mapping attribute "horizontalDirection" to correct
988     * flag value.
989     * {@hide}
990     */
991    private static final int[] LAYOUT_DIRECTION_FLAGS = {LAYOUT_DIRECTION_LTR,
992        LAYOUT_DIRECTION_RTL, LAYOUT_DIRECTION_INHERIT, LAYOUT_DIRECTION_LOCALE};
993
994    /**
995     * Default horizontalDirection.
996     * {@hide}
997     */
998    private static final int LAYOUT_DIRECTION_DEFAULT = LAYOUT_DIRECTION_INHERIT;
999
1000    /**
1001     * View flag indicating whether {@link #addFocusables(ArrayList, int, int)}
1002     * should add all focusable Views regardless if they are focusable in touch mode.
1003     */
1004    public static final int FOCUSABLES_ALL = 0x00000000;
1005
1006    /**
1007     * View flag indicating whether {@link #addFocusables(ArrayList, int, int)}
1008     * should add only Views focusable in touch mode.
1009     */
1010    public static final int FOCUSABLES_TOUCH_MODE = 0x00000001;
1011
1012    /**
1013     * Use with {@link #focusSearch(int)}. Move focus to the previous selectable
1014     * item.
1015     */
1016    public static final int FOCUS_BACKWARD = 0x00000001;
1017
1018    /**
1019     * Use with {@link #focusSearch(int)}. Move focus to the next selectable
1020     * item.
1021     */
1022    public static final int FOCUS_FORWARD = 0x00000002;
1023
1024    /**
1025     * Use with {@link #focusSearch(int)}. Move focus to the left.
1026     */
1027    public static final int FOCUS_LEFT = 0x00000011;
1028
1029    /**
1030     * Use with {@link #focusSearch(int)}. Move focus up.
1031     */
1032    public static final int FOCUS_UP = 0x00000021;
1033
1034    /**
1035     * Use with {@link #focusSearch(int)}. Move focus to the right.
1036     */
1037    public static final int FOCUS_RIGHT = 0x00000042;
1038
1039    /**
1040     * Use with {@link #focusSearch(int)}. Move focus down.
1041     */
1042    public static final int FOCUS_DOWN = 0x00000082;
1043
1044    /**
1045     * Bits of {@link #getMeasuredWidthAndState()} and
1046     * {@link #getMeasuredWidthAndState()} that provide the actual measured size.
1047     */
1048    public static final int MEASURED_SIZE_MASK = 0x00ffffff;
1049
1050    /**
1051     * Bits of {@link #getMeasuredWidthAndState()} and
1052     * {@link #getMeasuredWidthAndState()} that provide the additional state bits.
1053     */
1054    public static final int MEASURED_STATE_MASK = 0xff000000;
1055
1056    /**
1057     * Bit shift of {@link #MEASURED_STATE_MASK} to get to the height bits
1058     * for functions that combine both width and height into a single int,
1059     * such as {@link #getMeasuredState()} and the childState argument of
1060     * {@link #resolveSizeAndState(int, int, int)}.
1061     */
1062    public static final int MEASURED_HEIGHT_STATE_SHIFT = 16;
1063
1064    /**
1065     * Bit of {@link #getMeasuredWidthAndState()} and
1066     * {@link #getMeasuredWidthAndState()} that indicates the measured size
1067     * is smaller that the space the view would like to have.
1068     */
1069    public static final int MEASURED_STATE_TOO_SMALL = 0x01000000;
1070
1071    /**
1072     * Base View state sets
1073     */
1074    // Singles
1075    /**
1076     * Indicates the view has no states set. States are used with
1077     * {@link android.graphics.drawable.Drawable} to change the drawing of the
1078     * view depending on its state.
1079     *
1080     * @see android.graphics.drawable.Drawable
1081     * @see #getDrawableState()
1082     */
1083    protected static final int[] EMPTY_STATE_SET;
1084    /**
1085     * Indicates the view is enabled. States are used with
1086     * {@link android.graphics.drawable.Drawable} to change the drawing of the
1087     * view depending on its state.
1088     *
1089     * @see android.graphics.drawable.Drawable
1090     * @see #getDrawableState()
1091     */
1092    protected static final int[] ENABLED_STATE_SET;
1093    /**
1094     * Indicates the view is focused. States are used with
1095     * {@link android.graphics.drawable.Drawable} to change the drawing of the
1096     * view depending on its state.
1097     *
1098     * @see android.graphics.drawable.Drawable
1099     * @see #getDrawableState()
1100     */
1101    protected static final int[] FOCUSED_STATE_SET;
1102    /**
1103     * Indicates the view is selected. States are used with
1104     * {@link android.graphics.drawable.Drawable} to change the drawing of the
1105     * view depending on its state.
1106     *
1107     * @see android.graphics.drawable.Drawable
1108     * @see #getDrawableState()
1109     */
1110    protected static final int[] SELECTED_STATE_SET;
1111    /**
1112     * Indicates the view is pressed. States are used with
1113     * {@link android.graphics.drawable.Drawable} to change the drawing of the
1114     * view depending on its state.
1115     *
1116     * @see android.graphics.drawable.Drawable
1117     * @see #getDrawableState()
1118     * @hide
1119     */
1120    protected static final int[] PRESSED_STATE_SET;
1121    /**
1122     * Indicates the view's window has focus. States are used with
1123     * {@link android.graphics.drawable.Drawable} to change the drawing of the
1124     * view depending on its state.
1125     *
1126     * @see android.graphics.drawable.Drawable
1127     * @see #getDrawableState()
1128     */
1129    protected static final int[] WINDOW_FOCUSED_STATE_SET;
1130    // Doubles
1131    /**
1132     * Indicates the view is enabled and has the focus.
1133     *
1134     * @see #ENABLED_STATE_SET
1135     * @see #FOCUSED_STATE_SET
1136     */
1137    protected static final int[] ENABLED_FOCUSED_STATE_SET;
1138    /**
1139     * Indicates the view is enabled and selected.
1140     *
1141     * @see #ENABLED_STATE_SET
1142     * @see #SELECTED_STATE_SET
1143     */
1144    protected static final int[] ENABLED_SELECTED_STATE_SET;
1145    /**
1146     * Indicates the view is enabled and that its window has focus.
1147     *
1148     * @see #ENABLED_STATE_SET
1149     * @see #WINDOW_FOCUSED_STATE_SET
1150     */
1151    protected static final int[] ENABLED_WINDOW_FOCUSED_STATE_SET;
1152    /**
1153     * Indicates the view is focused and selected.
1154     *
1155     * @see #FOCUSED_STATE_SET
1156     * @see #SELECTED_STATE_SET
1157     */
1158    protected static final int[] FOCUSED_SELECTED_STATE_SET;
1159    /**
1160     * Indicates the view has the focus and that its window has the focus.
1161     *
1162     * @see #FOCUSED_STATE_SET
1163     * @see #WINDOW_FOCUSED_STATE_SET
1164     */
1165    protected static final int[] FOCUSED_WINDOW_FOCUSED_STATE_SET;
1166    /**
1167     * Indicates the view is selected and that its window has the focus.
1168     *
1169     * @see #SELECTED_STATE_SET
1170     * @see #WINDOW_FOCUSED_STATE_SET
1171     */
1172    protected static final int[] SELECTED_WINDOW_FOCUSED_STATE_SET;
1173    // Triples
1174    /**
1175     * Indicates the view is enabled, focused and selected.
1176     *
1177     * @see #ENABLED_STATE_SET
1178     * @see #FOCUSED_STATE_SET
1179     * @see #SELECTED_STATE_SET
1180     */
1181    protected static final int[] ENABLED_FOCUSED_SELECTED_STATE_SET;
1182    /**
1183     * Indicates the view is enabled, focused and its window has the focus.
1184     *
1185     * @see #ENABLED_STATE_SET
1186     * @see #FOCUSED_STATE_SET
1187     * @see #WINDOW_FOCUSED_STATE_SET
1188     */
1189    protected static final int[] ENABLED_FOCUSED_WINDOW_FOCUSED_STATE_SET;
1190    /**
1191     * Indicates the view is enabled, selected and its window has the focus.
1192     *
1193     * @see #ENABLED_STATE_SET
1194     * @see #SELECTED_STATE_SET
1195     * @see #WINDOW_FOCUSED_STATE_SET
1196     */
1197    protected static final int[] ENABLED_SELECTED_WINDOW_FOCUSED_STATE_SET;
1198    /**
1199     * Indicates the view is focused, selected and its window has the focus.
1200     *
1201     * @see #FOCUSED_STATE_SET
1202     * @see #SELECTED_STATE_SET
1203     * @see #WINDOW_FOCUSED_STATE_SET
1204     */
1205    protected static final int[] FOCUSED_SELECTED_WINDOW_FOCUSED_STATE_SET;
1206    /**
1207     * Indicates the view is enabled, focused, selected and its window
1208     * has the focus.
1209     *
1210     * @see #ENABLED_STATE_SET
1211     * @see #FOCUSED_STATE_SET
1212     * @see #SELECTED_STATE_SET
1213     * @see #WINDOW_FOCUSED_STATE_SET
1214     */
1215    protected static final int[] ENABLED_FOCUSED_SELECTED_WINDOW_FOCUSED_STATE_SET;
1216    /**
1217     * Indicates the view is pressed and its window has the focus.
1218     *
1219     * @see #PRESSED_STATE_SET
1220     * @see #WINDOW_FOCUSED_STATE_SET
1221     */
1222    protected static final int[] PRESSED_WINDOW_FOCUSED_STATE_SET;
1223    /**
1224     * Indicates the view is pressed and selected.
1225     *
1226     * @see #PRESSED_STATE_SET
1227     * @see #SELECTED_STATE_SET
1228     */
1229    protected static final int[] PRESSED_SELECTED_STATE_SET;
1230    /**
1231     * Indicates the view is pressed, selected and its window has the focus.
1232     *
1233     * @see #PRESSED_STATE_SET
1234     * @see #SELECTED_STATE_SET
1235     * @see #WINDOW_FOCUSED_STATE_SET
1236     */
1237    protected static final int[] PRESSED_SELECTED_WINDOW_FOCUSED_STATE_SET;
1238    /**
1239     * Indicates the view is pressed and focused.
1240     *
1241     * @see #PRESSED_STATE_SET
1242     * @see #FOCUSED_STATE_SET
1243     */
1244    protected static final int[] PRESSED_FOCUSED_STATE_SET;
1245    /**
1246     * Indicates the view is pressed, focused and its window has the focus.
1247     *
1248     * @see #PRESSED_STATE_SET
1249     * @see #FOCUSED_STATE_SET
1250     * @see #WINDOW_FOCUSED_STATE_SET
1251     */
1252    protected static final int[] PRESSED_FOCUSED_WINDOW_FOCUSED_STATE_SET;
1253    /**
1254     * Indicates the view is pressed, focused and selected.
1255     *
1256     * @see #PRESSED_STATE_SET
1257     * @see #SELECTED_STATE_SET
1258     * @see #FOCUSED_STATE_SET
1259     */
1260    protected static final int[] PRESSED_FOCUSED_SELECTED_STATE_SET;
1261    /**
1262     * Indicates the view is pressed, focused, selected and its window has the focus.
1263     *
1264     * @see #PRESSED_STATE_SET
1265     * @see #FOCUSED_STATE_SET
1266     * @see #SELECTED_STATE_SET
1267     * @see #WINDOW_FOCUSED_STATE_SET
1268     */
1269    protected static final int[] PRESSED_FOCUSED_SELECTED_WINDOW_FOCUSED_STATE_SET;
1270    /**
1271     * Indicates the view is pressed and enabled.
1272     *
1273     * @see #PRESSED_STATE_SET
1274     * @see #ENABLED_STATE_SET
1275     */
1276    protected static final int[] PRESSED_ENABLED_STATE_SET;
1277    /**
1278     * Indicates the view is pressed, enabled and its window has the focus.
1279     *
1280     * @see #PRESSED_STATE_SET
1281     * @see #ENABLED_STATE_SET
1282     * @see #WINDOW_FOCUSED_STATE_SET
1283     */
1284    protected static final int[] PRESSED_ENABLED_WINDOW_FOCUSED_STATE_SET;
1285    /**
1286     * Indicates the view is pressed, enabled and selected.
1287     *
1288     * @see #PRESSED_STATE_SET
1289     * @see #ENABLED_STATE_SET
1290     * @see #SELECTED_STATE_SET
1291     */
1292    protected static final int[] PRESSED_ENABLED_SELECTED_STATE_SET;
1293    /**
1294     * Indicates the view is pressed, enabled, selected and its window has the
1295     * focus.
1296     *
1297     * @see #PRESSED_STATE_SET
1298     * @see #ENABLED_STATE_SET
1299     * @see #SELECTED_STATE_SET
1300     * @see #WINDOW_FOCUSED_STATE_SET
1301     */
1302    protected static final int[] PRESSED_ENABLED_SELECTED_WINDOW_FOCUSED_STATE_SET;
1303    /**
1304     * Indicates the view is pressed, enabled and focused.
1305     *
1306     * @see #PRESSED_STATE_SET
1307     * @see #ENABLED_STATE_SET
1308     * @see #FOCUSED_STATE_SET
1309     */
1310    protected static final int[] PRESSED_ENABLED_FOCUSED_STATE_SET;
1311    /**
1312     * Indicates the view is pressed, enabled, focused and its window has the
1313     * focus.
1314     *
1315     * @see #PRESSED_STATE_SET
1316     * @see #ENABLED_STATE_SET
1317     * @see #FOCUSED_STATE_SET
1318     * @see #WINDOW_FOCUSED_STATE_SET
1319     */
1320    protected static final int[] PRESSED_ENABLED_FOCUSED_WINDOW_FOCUSED_STATE_SET;
1321    /**
1322     * Indicates the view is pressed, enabled, focused and selected.
1323     *
1324     * @see #PRESSED_STATE_SET
1325     * @see #ENABLED_STATE_SET
1326     * @see #SELECTED_STATE_SET
1327     * @see #FOCUSED_STATE_SET
1328     */
1329    protected static final int[] PRESSED_ENABLED_FOCUSED_SELECTED_STATE_SET;
1330    /**
1331     * Indicates the view is pressed, enabled, focused, selected and its window
1332     * has the focus.
1333     *
1334     * @see #PRESSED_STATE_SET
1335     * @see #ENABLED_STATE_SET
1336     * @see #SELECTED_STATE_SET
1337     * @see #FOCUSED_STATE_SET
1338     * @see #WINDOW_FOCUSED_STATE_SET
1339     */
1340    protected static final int[] PRESSED_ENABLED_FOCUSED_SELECTED_WINDOW_FOCUSED_STATE_SET;
1341
1342    /**
1343     * The order here is very important to {@link #getDrawableState()}
1344     */
1345    private static final int[][] VIEW_STATE_SETS;
1346
1347    static final int VIEW_STATE_WINDOW_FOCUSED = 1;
1348    static final int VIEW_STATE_SELECTED = 1 << 1;
1349    static final int VIEW_STATE_FOCUSED = 1 << 2;
1350    static final int VIEW_STATE_ENABLED = 1 << 3;
1351    static final int VIEW_STATE_PRESSED = 1 << 4;
1352    static final int VIEW_STATE_ACTIVATED = 1 << 5;
1353    static final int VIEW_STATE_ACCELERATED = 1 << 6;
1354    static final int VIEW_STATE_HOVERED = 1 << 7;
1355    static final int VIEW_STATE_DRAG_CAN_ACCEPT = 1 << 8;
1356    static final int VIEW_STATE_DRAG_HOVERED = 1 << 9;
1357
1358    static final int[] VIEW_STATE_IDS = new int[] {
1359        R.attr.state_window_focused,    VIEW_STATE_WINDOW_FOCUSED,
1360        R.attr.state_selected,          VIEW_STATE_SELECTED,
1361        R.attr.state_focused,           VIEW_STATE_FOCUSED,
1362        R.attr.state_enabled,           VIEW_STATE_ENABLED,
1363        R.attr.state_pressed,           VIEW_STATE_PRESSED,
1364        R.attr.state_activated,         VIEW_STATE_ACTIVATED,
1365        R.attr.state_accelerated,       VIEW_STATE_ACCELERATED,
1366        R.attr.state_hovered,           VIEW_STATE_HOVERED,
1367        R.attr.state_drag_can_accept,   VIEW_STATE_DRAG_CAN_ACCEPT,
1368        R.attr.state_drag_hovered,      VIEW_STATE_DRAG_HOVERED,
1369    };
1370
1371    static {
1372        if ((VIEW_STATE_IDS.length/2) != R.styleable.ViewDrawableStates.length) {
1373            throw new IllegalStateException(
1374                    "VIEW_STATE_IDs array length does not match ViewDrawableStates style array");
1375        }
1376        int[] orderedIds = new int[VIEW_STATE_IDS.length];
1377        for (int i = 0; i < R.styleable.ViewDrawableStates.length; i++) {
1378            int viewState = R.styleable.ViewDrawableStates[i];
1379            for (int j = 0; j<VIEW_STATE_IDS.length; j += 2) {
1380                if (VIEW_STATE_IDS[j] == viewState) {
1381                    orderedIds[i * 2] = viewState;
1382                    orderedIds[i * 2 + 1] = VIEW_STATE_IDS[j + 1];
1383                }
1384            }
1385        }
1386        final int NUM_BITS = VIEW_STATE_IDS.length / 2;
1387        VIEW_STATE_SETS = new int[1 << NUM_BITS][];
1388        for (int i = 0; i < VIEW_STATE_SETS.length; i++) {
1389            int numBits = Integer.bitCount(i);
1390            int[] set = new int[numBits];
1391            int pos = 0;
1392            for (int j = 0; j < orderedIds.length; j += 2) {
1393                if ((i & orderedIds[j+1]) != 0) {
1394                    set[pos++] = orderedIds[j];
1395                }
1396            }
1397            VIEW_STATE_SETS[i] = set;
1398        }
1399
1400        EMPTY_STATE_SET = VIEW_STATE_SETS[0];
1401        WINDOW_FOCUSED_STATE_SET = VIEW_STATE_SETS[VIEW_STATE_WINDOW_FOCUSED];
1402        SELECTED_STATE_SET = VIEW_STATE_SETS[VIEW_STATE_SELECTED];
1403        SELECTED_WINDOW_FOCUSED_STATE_SET = VIEW_STATE_SETS[
1404                VIEW_STATE_WINDOW_FOCUSED | VIEW_STATE_SELECTED];
1405        FOCUSED_STATE_SET = VIEW_STATE_SETS[VIEW_STATE_FOCUSED];
1406        FOCUSED_WINDOW_FOCUSED_STATE_SET = VIEW_STATE_SETS[
1407                VIEW_STATE_WINDOW_FOCUSED | VIEW_STATE_FOCUSED];
1408        FOCUSED_SELECTED_STATE_SET = VIEW_STATE_SETS[
1409                VIEW_STATE_SELECTED | VIEW_STATE_FOCUSED];
1410        FOCUSED_SELECTED_WINDOW_FOCUSED_STATE_SET = VIEW_STATE_SETS[
1411                VIEW_STATE_WINDOW_FOCUSED | VIEW_STATE_SELECTED
1412                | VIEW_STATE_FOCUSED];
1413        ENABLED_STATE_SET = VIEW_STATE_SETS[VIEW_STATE_ENABLED];
1414        ENABLED_WINDOW_FOCUSED_STATE_SET = VIEW_STATE_SETS[
1415                VIEW_STATE_WINDOW_FOCUSED | VIEW_STATE_ENABLED];
1416        ENABLED_SELECTED_STATE_SET = VIEW_STATE_SETS[
1417                VIEW_STATE_SELECTED | VIEW_STATE_ENABLED];
1418        ENABLED_SELECTED_WINDOW_FOCUSED_STATE_SET = VIEW_STATE_SETS[
1419                VIEW_STATE_WINDOW_FOCUSED | VIEW_STATE_SELECTED
1420                | VIEW_STATE_ENABLED];
1421        ENABLED_FOCUSED_STATE_SET = VIEW_STATE_SETS[
1422                VIEW_STATE_FOCUSED | VIEW_STATE_ENABLED];
1423        ENABLED_FOCUSED_WINDOW_FOCUSED_STATE_SET = VIEW_STATE_SETS[
1424                VIEW_STATE_WINDOW_FOCUSED | VIEW_STATE_FOCUSED
1425                | VIEW_STATE_ENABLED];
1426        ENABLED_FOCUSED_SELECTED_STATE_SET = VIEW_STATE_SETS[
1427                VIEW_STATE_SELECTED | VIEW_STATE_FOCUSED
1428                | VIEW_STATE_ENABLED];
1429        ENABLED_FOCUSED_SELECTED_WINDOW_FOCUSED_STATE_SET = VIEW_STATE_SETS[
1430                VIEW_STATE_WINDOW_FOCUSED | VIEW_STATE_SELECTED
1431                | VIEW_STATE_FOCUSED| VIEW_STATE_ENABLED];
1432
1433        PRESSED_STATE_SET = VIEW_STATE_SETS[VIEW_STATE_PRESSED];
1434        PRESSED_WINDOW_FOCUSED_STATE_SET = VIEW_STATE_SETS[
1435                VIEW_STATE_WINDOW_FOCUSED | VIEW_STATE_PRESSED];
1436        PRESSED_SELECTED_STATE_SET = VIEW_STATE_SETS[
1437                VIEW_STATE_SELECTED | VIEW_STATE_PRESSED];
1438        PRESSED_SELECTED_WINDOW_FOCUSED_STATE_SET = VIEW_STATE_SETS[
1439                VIEW_STATE_WINDOW_FOCUSED | VIEW_STATE_SELECTED
1440                | VIEW_STATE_PRESSED];
1441        PRESSED_FOCUSED_STATE_SET = VIEW_STATE_SETS[
1442                VIEW_STATE_FOCUSED | VIEW_STATE_PRESSED];
1443        PRESSED_FOCUSED_WINDOW_FOCUSED_STATE_SET = VIEW_STATE_SETS[
1444                VIEW_STATE_WINDOW_FOCUSED | VIEW_STATE_FOCUSED
1445                | VIEW_STATE_PRESSED];
1446        PRESSED_FOCUSED_SELECTED_STATE_SET = VIEW_STATE_SETS[
1447                VIEW_STATE_SELECTED | VIEW_STATE_FOCUSED
1448                | VIEW_STATE_PRESSED];
1449        PRESSED_FOCUSED_SELECTED_WINDOW_FOCUSED_STATE_SET = VIEW_STATE_SETS[
1450                VIEW_STATE_WINDOW_FOCUSED | VIEW_STATE_SELECTED
1451                | VIEW_STATE_FOCUSED | VIEW_STATE_PRESSED];
1452        PRESSED_ENABLED_STATE_SET = VIEW_STATE_SETS[
1453                VIEW_STATE_ENABLED | VIEW_STATE_PRESSED];
1454        PRESSED_ENABLED_WINDOW_FOCUSED_STATE_SET = VIEW_STATE_SETS[
1455                VIEW_STATE_WINDOW_FOCUSED | VIEW_STATE_ENABLED
1456                | VIEW_STATE_PRESSED];
1457        PRESSED_ENABLED_SELECTED_STATE_SET = VIEW_STATE_SETS[
1458                VIEW_STATE_SELECTED | VIEW_STATE_ENABLED
1459                | VIEW_STATE_PRESSED];
1460        PRESSED_ENABLED_SELECTED_WINDOW_FOCUSED_STATE_SET = VIEW_STATE_SETS[
1461                VIEW_STATE_WINDOW_FOCUSED | VIEW_STATE_SELECTED
1462                | VIEW_STATE_ENABLED | VIEW_STATE_PRESSED];
1463        PRESSED_ENABLED_FOCUSED_STATE_SET = VIEW_STATE_SETS[
1464                VIEW_STATE_FOCUSED | VIEW_STATE_ENABLED
1465                | VIEW_STATE_PRESSED];
1466        PRESSED_ENABLED_FOCUSED_WINDOW_FOCUSED_STATE_SET = VIEW_STATE_SETS[
1467                VIEW_STATE_WINDOW_FOCUSED | VIEW_STATE_FOCUSED
1468                | VIEW_STATE_ENABLED | VIEW_STATE_PRESSED];
1469        PRESSED_ENABLED_FOCUSED_SELECTED_STATE_SET = VIEW_STATE_SETS[
1470                VIEW_STATE_SELECTED | VIEW_STATE_FOCUSED
1471                | VIEW_STATE_ENABLED | VIEW_STATE_PRESSED];
1472        PRESSED_ENABLED_FOCUSED_SELECTED_WINDOW_FOCUSED_STATE_SET = VIEW_STATE_SETS[
1473                VIEW_STATE_WINDOW_FOCUSED | VIEW_STATE_SELECTED
1474                | VIEW_STATE_FOCUSED| VIEW_STATE_ENABLED
1475                | VIEW_STATE_PRESSED];
1476    }
1477
1478    /**
1479     * Accessibility event types that are dispatched for text population.
1480     */
1481    private static final int POPULATING_ACCESSIBILITY_EVENT_TYPES =
1482            AccessibilityEvent.TYPE_VIEW_CLICKED
1483            | AccessibilityEvent.TYPE_VIEW_LONG_CLICKED
1484            | AccessibilityEvent.TYPE_VIEW_SELECTED
1485            | AccessibilityEvent.TYPE_VIEW_FOCUSED
1486            | AccessibilityEvent.TYPE_WINDOW_STATE_CHANGED
1487            | AccessibilityEvent.TYPE_VIEW_HOVER_ENTER
1488            | AccessibilityEvent.TYPE_VIEW_HOVER_EXIT
1489            | AccessibilityEvent.TYPE_VIEW_TEXT_CHANGED
1490            | AccessibilityEvent.TYPE_VIEW_TEXT_SELECTION_CHANGED;
1491
1492    /**
1493     * Temporary Rect currently for use in setBackground().  This will probably
1494     * be extended in the future to hold our own class with more than just
1495     * a Rect. :)
1496     */
1497    static final ThreadLocal<Rect> sThreadLocal = new ThreadLocal<Rect>();
1498
1499    /**
1500     * Map used to store views' tags.
1501     */
1502    private SparseArray<Object> mKeyedTags;
1503
1504    /**
1505     * The next available accessiiblity id.
1506     */
1507    private static int sNextAccessibilityViewId;
1508
1509    /**
1510     * The animation currently associated with this view.
1511     * @hide
1512     */
1513    protected Animation mCurrentAnimation = null;
1514
1515    /**
1516     * Width as measured during measure pass.
1517     * {@hide}
1518     */
1519    @ViewDebug.ExportedProperty(category = "measurement")
1520    int mMeasuredWidth;
1521
1522    /**
1523     * Height as measured during measure pass.
1524     * {@hide}
1525     */
1526    @ViewDebug.ExportedProperty(category = "measurement")
1527    int mMeasuredHeight;
1528
1529    /**
1530     * Flag to indicate that this view was marked INVALIDATED, or had its display list
1531     * invalidated, prior to the current drawing iteration. If true, the view must re-draw
1532     * its display list. This flag, used only when hw accelerated, allows us to clear the
1533     * flag while retaining this information until it's needed (at getDisplayList() time and
1534     * in drawChild(), when we decide to draw a view's children's display lists into our own).
1535     *
1536     * {@hide}
1537     */
1538    boolean mRecreateDisplayList = false;
1539
1540    /**
1541     * The view's identifier.
1542     * {@hide}
1543     *
1544     * @see #setId(int)
1545     * @see #getId()
1546     */
1547    @ViewDebug.ExportedProperty(resolveId = true)
1548    int mID = NO_ID;
1549
1550    /**
1551     * The stable ID of this view for accessibility purposes.
1552     */
1553    int mAccessibilityViewId = NO_ID;
1554
1555    /**
1556     * The view's tag.
1557     * {@hide}
1558     *
1559     * @see #setTag(Object)
1560     * @see #getTag()
1561     */
1562    protected Object mTag;
1563
1564    // for mPrivateFlags:
1565    /** {@hide} */
1566    static final int WANTS_FOCUS                    = 0x00000001;
1567    /** {@hide} */
1568    static final int FOCUSED                        = 0x00000002;
1569    /** {@hide} */
1570    static final int SELECTED                       = 0x00000004;
1571    /** {@hide} */
1572    static final int IS_ROOT_NAMESPACE              = 0x00000008;
1573    /** {@hide} */
1574    static final int HAS_BOUNDS                     = 0x00000010;
1575    /** {@hide} */
1576    static final int DRAWN                          = 0x00000020;
1577    /**
1578     * When this flag is set, this view is running an animation on behalf of its
1579     * children and should therefore not cancel invalidate requests, even if they
1580     * lie outside of this view's bounds.
1581     *
1582     * {@hide}
1583     */
1584    static final int DRAW_ANIMATION                 = 0x00000040;
1585    /** {@hide} */
1586    static final int SKIP_DRAW                      = 0x00000080;
1587    /** {@hide} */
1588    static final int ONLY_DRAWS_BACKGROUND          = 0x00000100;
1589    /** {@hide} */
1590    static final int REQUEST_TRANSPARENT_REGIONS    = 0x00000200;
1591    /** {@hide} */
1592    static final int DRAWABLE_STATE_DIRTY           = 0x00000400;
1593    /** {@hide} */
1594    static final int MEASURED_DIMENSION_SET         = 0x00000800;
1595    /** {@hide} */
1596    static final int FORCE_LAYOUT                   = 0x00001000;
1597    /** {@hide} */
1598    static final int LAYOUT_REQUIRED                = 0x00002000;
1599
1600    private static final int PRESSED                = 0x00004000;
1601
1602    /** {@hide} */
1603    static final int DRAWING_CACHE_VALID            = 0x00008000;
1604    /**
1605     * Flag used to indicate that this view should be drawn once more (and only once
1606     * more) after its animation has completed.
1607     * {@hide}
1608     */
1609    static final int ANIMATION_STARTED              = 0x00010000;
1610
1611    private static final int SAVE_STATE_CALLED      = 0x00020000;
1612
1613    /**
1614     * Indicates that the View returned true when onSetAlpha() was called and that
1615     * the alpha must be restored.
1616     * {@hide}
1617     */
1618    static final int ALPHA_SET                      = 0x00040000;
1619
1620    /**
1621     * Set by {@link #setScrollContainer(boolean)}.
1622     */
1623    static final int SCROLL_CONTAINER               = 0x00080000;
1624
1625    /**
1626     * Set by {@link #setScrollContainer(boolean)}.
1627     */
1628    static final int SCROLL_CONTAINER_ADDED         = 0x00100000;
1629
1630    /**
1631     * View flag indicating whether this view was invalidated (fully or partially.)
1632     *
1633     * @hide
1634     */
1635    static final int DIRTY                          = 0x00200000;
1636
1637    /**
1638     * View flag indicating whether this view was invalidated by an opaque
1639     * invalidate request.
1640     *
1641     * @hide
1642     */
1643    static final int DIRTY_OPAQUE                   = 0x00400000;
1644
1645    /**
1646     * Mask for {@link #DIRTY} and {@link #DIRTY_OPAQUE}.
1647     *
1648     * @hide
1649     */
1650    static final int DIRTY_MASK                     = 0x00600000;
1651
1652    /**
1653     * Indicates whether the background is opaque.
1654     *
1655     * @hide
1656     */
1657    static final int OPAQUE_BACKGROUND              = 0x00800000;
1658
1659    /**
1660     * Indicates whether the scrollbars are opaque.
1661     *
1662     * @hide
1663     */
1664    static final int OPAQUE_SCROLLBARS              = 0x01000000;
1665
1666    /**
1667     * Indicates whether the view is opaque.
1668     *
1669     * @hide
1670     */
1671    static final int OPAQUE_MASK                    = 0x01800000;
1672
1673    /**
1674     * Indicates a prepressed state;
1675     * the short time between ACTION_DOWN and recognizing
1676     * a 'real' press. Prepressed is used to recognize quick taps
1677     * even when they are shorter than ViewConfiguration.getTapTimeout().
1678     *
1679     * @hide
1680     */
1681    private static final int PREPRESSED             = 0x02000000;
1682
1683    /**
1684     * Indicates whether the view is temporarily detached.
1685     *
1686     * @hide
1687     */
1688    static final int CANCEL_NEXT_UP_EVENT = 0x04000000;
1689
1690    /**
1691     * Indicates that we should awaken scroll bars once attached
1692     *
1693     * @hide
1694     */
1695    private static final int AWAKEN_SCROLL_BARS_ON_ATTACH = 0x08000000;
1696
1697    /**
1698     * Indicates that the view has received HOVER_ENTER.  Cleared on HOVER_EXIT.
1699     * @hide
1700     */
1701    private static final int HOVERED              = 0x10000000;
1702
1703    /**
1704     * Indicates that pivotX or pivotY were explicitly set and we should not assume the center
1705     * for transform operations
1706     *
1707     * @hide
1708     */
1709    private static final int PIVOT_EXPLICITLY_SET = 0x20000000;
1710
1711    /** {@hide} */
1712    static final int ACTIVATED                    = 0x40000000;
1713
1714    /**
1715     * Indicates that this view was specifically invalidated, not just dirtied because some
1716     * child view was invalidated. The flag is used to determine when we need to recreate
1717     * a view's display list (as opposed to just returning a reference to its existing
1718     * display list).
1719     *
1720     * @hide
1721     */
1722    static final int INVALIDATED                  = 0x80000000;
1723
1724    /* Masks for mPrivateFlags2 */
1725
1726    /**
1727     * Indicates that this view has reported that it can accept the current drag's content.
1728     * Cleared when the drag operation concludes.
1729     * @hide
1730     */
1731    static final int DRAG_CAN_ACCEPT              = 0x00000001;
1732
1733    /**
1734     * Indicates that this view is currently directly under the drag location in a
1735     * drag-and-drop operation involving content that it can accept.  Cleared when
1736     * the drag exits the view, or when the drag operation concludes.
1737     * @hide
1738     */
1739    static final int DRAG_HOVERED                 = 0x00000002;
1740
1741    /**
1742     * Indicates whether the view layout direction has been resolved and drawn to the
1743     * right-to-left direction.
1744     *
1745     * @hide
1746     */
1747    static final int LAYOUT_DIRECTION_RESOLVED_RTL = 0x00000004;
1748
1749    /**
1750     * Indicates whether the view layout direction has been resolved.
1751     *
1752     * @hide
1753     */
1754    static final int LAYOUT_DIRECTION_RESOLVED = 0x00000008;
1755
1756
1757    /**
1758     * Indicates that the view is tracking some sort of transient state
1759     * that the app should not need to be aware of, but that the framework
1760     * should take special care to preserve.
1761     *
1762     * @hide
1763     */
1764    static final int HAS_TRANSIENT_STATE = 0x00000010;
1765
1766
1767    /* End of masks for mPrivateFlags2 */
1768
1769    static final int DRAG_MASK = DRAG_CAN_ACCEPT | DRAG_HOVERED;
1770
1771    /**
1772     * Always allow a user to over-scroll this view, provided it is a
1773     * view that can scroll.
1774     *
1775     * @see #getOverScrollMode()
1776     * @see #setOverScrollMode(int)
1777     */
1778    public static final int OVER_SCROLL_ALWAYS = 0;
1779
1780    /**
1781     * Allow a user to over-scroll this view only if the content is large
1782     * enough to meaningfully scroll, provided it is a view that can scroll.
1783     *
1784     * @see #getOverScrollMode()
1785     * @see #setOverScrollMode(int)
1786     */
1787    public static final int OVER_SCROLL_IF_CONTENT_SCROLLS = 1;
1788
1789    /**
1790     * Never allow a user to over-scroll this view.
1791     *
1792     * @see #getOverScrollMode()
1793     * @see #setOverScrollMode(int)
1794     */
1795    public static final int OVER_SCROLL_NEVER = 2;
1796
1797    /**
1798     * View has requested the system UI (status bar) to be visible (the default).
1799     *
1800     * @see #setSystemUiVisibility(int)
1801     */
1802    public static final int SYSTEM_UI_FLAG_VISIBLE = 0;
1803
1804    /**
1805     * View has requested the system UI to enter an unobtrusive "low profile" mode.
1806     *
1807     * This is for use in games, book readers, video players, or any other "immersive" application
1808     * where the usual system chrome is deemed too distracting.
1809     *
1810     * In low profile mode, the status bar and/or navigation icons may dim.
1811     *
1812     * @see #setSystemUiVisibility(int)
1813     */
1814    public static final int SYSTEM_UI_FLAG_LOW_PROFILE = 0x00000001;
1815
1816    /**
1817     * View has requested that the system navigation be temporarily hidden.
1818     *
1819     * This is an even less obtrusive state than that called for by
1820     * {@link #SYSTEM_UI_FLAG_LOW_PROFILE}; on devices that draw essential navigation controls
1821     * (Home, Back, and the like) on screen, <code>SYSTEM_UI_FLAG_HIDE_NAVIGATION</code> will cause
1822     * those to disappear. This is useful (in conjunction with the
1823     * {@link android.view.WindowManager.LayoutParams#FLAG_FULLSCREEN FLAG_FULLSCREEN} and
1824     * {@link android.view.WindowManager.LayoutParams#FLAG_LAYOUT_IN_SCREEN FLAG_LAYOUT_IN_SCREEN}
1825     * window flags) for displaying content using every last pixel on the display.
1826     *
1827     * There is a limitation: because navigation controls are so important, the least user
1828     * interaction will cause them to reappear immediately.
1829     *
1830     * @see #setSystemUiVisibility(int)
1831     */
1832    public static final int SYSTEM_UI_FLAG_HIDE_NAVIGATION = 0x00000002;
1833
1834    /**
1835     * @deprecated Use {@link #SYSTEM_UI_FLAG_LOW_PROFILE} instead.
1836     */
1837    public static final int STATUS_BAR_HIDDEN = SYSTEM_UI_FLAG_LOW_PROFILE;
1838
1839    /**
1840     * @deprecated Use {@link #SYSTEM_UI_FLAG_VISIBLE} instead.
1841     */
1842    public static final int STATUS_BAR_VISIBLE = SYSTEM_UI_FLAG_VISIBLE;
1843
1844    /**
1845     * @hide
1846     *
1847     * NOTE: This flag may only be used in subtreeSystemUiVisibility. It is masked
1848     * out of the public fields to keep the undefined bits out of the developer's way.
1849     *
1850     * Flag to make the status bar not expandable.  Unless you also
1851     * set {@link #STATUS_BAR_DISABLE_NOTIFICATION_ICONS}, new notifications will continue to show.
1852     */
1853    public static final int STATUS_BAR_DISABLE_EXPAND = 0x00010000;
1854
1855    /**
1856     * @hide
1857     *
1858     * NOTE: This flag may only be used in subtreeSystemUiVisibility. It is masked
1859     * out of the public fields to keep the undefined bits out of the developer's way.
1860     *
1861     * Flag to hide notification icons and scrolling ticker text.
1862     */
1863    public static final int STATUS_BAR_DISABLE_NOTIFICATION_ICONS = 0x00020000;
1864
1865    /**
1866     * @hide
1867     *
1868     * NOTE: This flag may only be used in subtreeSystemUiVisibility. It is masked
1869     * out of the public fields to keep the undefined bits out of the developer's way.
1870     *
1871     * Flag to disable incoming notification alerts.  This will not block
1872     * icons, but it will block sound, vibrating and other visual or aural notifications.
1873     */
1874    public static final int STATUS_BAR_DISABLE_NOTIFICATION_ALERTS = 0x00040000;
1875
1876    /**
1877     * @hide
1878     *
1879     * NOTE: This flag may only be used in subtreeSystemUiVisibility. It is masked
1880     * out of the public fields to keep the undefined bits out of the developer's way.
1881     *
1882     * Flag to hide only the scrolling ticker.  Note that
1883     * {@link #STATUS_BAR_DISABLE_NOTIFICATION_ICONS} implies
1884     * {@link #STATUS_BAR_DISABLE_NOTIFICATION_TICKER}.
1885     */
1886    public static final int STATUS_BAR_DISABLE_NOTIFICATION_TICKER = 0x00080000;
1887
1888    /**
1889     * @hide
1890     *
1891     * NOTE: This flag may only be used in subtreeSystemUiVisibility. It is masked
1892     * out of the public fields to keep the undefined bits out of the developer's way.
1893     *
1894     * Flag to hide the center system info area.
1895     */
1896    public static final int STATUS_BAR_DISABLE_SYSTEM_INFO = 0x00100000;
1897
1898    /**
1899     * @hide
1900     *
1901     * NOTE: This flag may only be used in subtreeSystemUiVisibility. It is masked
1902     * out of the public fields to keep the undefined bits out of the developer's way.
1903     *
1904     * Flag to hide only the home button.  Don't use this
1905     * unless you're a special part of the system UI (i.e., setup wizard, keyguard).
1906     */
1907    public static final int STATUS_BAR_DISABLE_HOME = 0x00200000;
1908
1909    /**
1910     * @hide
1911     *
1912     * NOTE: This flag may only be used in subtreeSystemUiVisibility. It is masked
1913     * out of the public fields to keep the undefined bits out of the developer's way.
1914     *
1915     * Flag to hide only the back button. Don't use this
1916     * unless you're a special part of the system UI (i.e., setup wizard, keyguard).
1917     */
1918    public static final int STATUS_BAR_DISABLE_BACK = 0x00400000;
1919
1920    /**
1921     * @hide
1922     *
1923     * NOTE: This flag may only be used in subtreeSystemUiVisibility. It is masked
1924     * out of the public fields to keep the undefined bits out of the developer's way.
1925     *
1926     * Flag to hide only the clock.  You might use this if your activity has
1927     * its own clock making the status bar's clock redundant.
1928     */
1929    public static final int STATUS_BAR_DISABLE_CLOCK = 0x00800000;
1930
1931    /**
1932     * @hide
1933     *
1934     * NOTE: This flag may only be used in subtreeSystemUiVisibility. It is masked
1935     * out of the public fields to keep the undefined bits out of the developer's way.
1936     *
1937     * Flag to hide only the recent apps button. Don't use this
1938     * unless you're a special part of the system UI (i.e., setup wizard, keyguard).
1939     */
1940    public static final int STATUS_BAR_DISABLE_RECENT = 0x01000000;
1941
1942    /**
1943     * @hide
1944     *
1945     * NOTE: This flag may only be used in subtreeSystemUiVisibility, etc. etc.
1946     *
1947     * This hides HOME and RECENT and is provided for compatibility with interim implementations.
1948     */
1949    @Deprecated
1950    public static final int STATUS_BAR_DISABLE_NAVIGATION =
1951            STATUS_BAR_DISABLE_HOME | STATUS_BAR_DISABLE_RECENT;
1952
1953    /**
1954     * @hide
1955     */
1956    public static final int PUBLIC_STATUS_BAR_VISIBILITY_MASK = 0x0000FFFF;
1957
1958    /**
1959     * These are the system UI flags that can be cleared by events outside
1960     * of an application.  Currently this is just the ability to tap on the
1961     * screen while hiding the navigation bar to have it return.
1962     * @hide
1963     */
1964    public static final int SYSTEM_UI_CLEARABLE_FLAGS =
1965            SYSTEM_UI_FLAG_LOW_PROFILE | SYSTEM_UI_FLAG_HIDE_NAVIGATION;
1966
1967    /**
1968     * Find views that render the specified text.
1969     *
1970     * @see #findViewsWithText(ArrayList, CharSequence, int)
1971     */
1972    public static final int FIND_VIEWS_WITH_TEXT = 0x00000001;
1973
1974    /**
1975     * Find find views that contain the specified content description.
1976     *
1977     * @see #findViewsWithText(ArrayList, CharSequence, int)
1978     */
1979    public static final int FIND_VIEWS_WITH_CONTENT_DESCRIPTION = 0x00000002;
1980
1981    /**
1982     * Find views that contain {@link AccessibilityNodeProvider}. Such
1983     * a View is a root of virtual view hierarchy and may contain the searched
1984     * text. If this flag is set Views with providers are automatically
1985     * added and it is a responsibility of the client to call the APIs of
1986     * the provider to determine whether the virtual tree rooted at this View
1987     * contains the text, i.e. getting the list of {@link AccessibilityNodeInfo}s
1988     * represeting the virtual views with this text.
1989     *
1990     * @see #findViewsWithText(ArrayList, CharSequence, int)
1991     *
1992     * @hide
1993     */
1994    public static final int FIND_VIEWS_WITH_ACCESSIBILITY_NODE_PROVIDERS = 0x00000004;
1995
1996    /**
1997     * Controls the over-scroll mode for this view.
1998     * See {@link #overScrollBy(int, int, int, int, int, int, int, int, boolean)},
1999     * {@link #OVER_SCROLL_ALWAYS}, {@link #OVER_SCROLL_IF_CONTENT_SCROLLS},
2000     * and {@link #OVER_SCROLL_NEVER}.
2001     */
2002    private int mOverScrollMode;
2003
2004    /**
2005     * The parent this view is attached to.
2006     * {@hide}
2007     *
2008     * @see #getParent()
2009     */
2010    protected ViewParent mParent;
2011
2012    /**
2013     * {@hide}
2014     */
2015    AttachInfo mAttachInfo;
2016
2017    /**
2018     * {@hide}
2019     */
2020    @ViewDebug.ExportedProperty(flagMapping = {
2021        @ViewDebug.FlagToString(mask = FORCE_LAYOUT, equals = FORCE_LAYOUT,
2022                name = "FORCE_LAYOUT"),
2023        @ViewDebug.FlagToString(mask = LAYOUT_REQUIRED, equals = LAYOUT_REQUIRED,
2024                name = "LAYOUT_REQUIRED"),
2025        @ViewDebug.FlagToString(mask = DRAWING_CACHE_VALID, equals = DRAWING_CACHE_VALID,
2026            name = "DRAWING_CACHE_INVALID", outputIf = false),
2027        @ViewDebug.FlagToString(mask = DRAWN, equals = DRAWN, name = "DRAWN", outputIf = true),
2028        @ViewDebug.FlagToString(mask = DRAWN, equals = DRAWN, name = "NOT_DRAWN", outputIf = false),
2029        @ViewDebug.FlagToString(mask = DIRTY_MASK, equals = DIRTY_OPAQUE, name = "DIRTY_OPAQUE"),
2030        @ViewDebug.FlagToString(mask = DIRTY_MASK, equals = DIRTY, name = "DIRTY")
2031    })
2032    int mPrivateFlags;
2033    int mPrivateFlags2;
2034
2035    /**
2036     * This view's request for the visibility of the status bar.
2037     * @hide
2038     */
2039    @ViewDebug.ExportedProperty(flagMapping = {
2040        @ViewDebug.FlagToString(mask = SYSTEM_UI_FLAG_LOW_PROFILE,
2041                                equals = SYSTEM_UI_FLAG_LOW_PROFILE,
2042                                name = "SYSTEM_UI_FLAG_LOW_PROFILE", outputIf = true),
2043        @ViewDebug.FlagToString(mask = SYSTEM_UI_FLAG_HIDE_NAVIGATION,
2044                                equals = SYSTEM_UI_FLAG_HIDE_NAVIGATION,
2045                                name = "SYSTEM_UI_FLAG_HIDE_NAVIGATION", outputIf = true),
2046        @ViewDebug.FlagToString(mask = PUBLIC_STATUS_BAR_VISIBILITY_MASK,
2047                                equals = SYSTEM_UI_FLAG_VISIBLE,
2048                                name = "SYSTEM_UI_FLAG_VISIBLE", outputIf = true)
2049    })
2050    int mSystemUiVisibility;
2051
2052    /**
2053     * Count of how many windows this view has been attached to.
2054     */
2055    int mWindowAttachCount;
2056
2057    /**
2058     * The layout parameters associated with this view and used by the parent
2059     * {@link android.view.ViewGroup} to determine how this view should be
2060     * laid out.
2061     * {@hide}
2062     */
2063    protected ViewGroup.LayoutParams mLayoutParams;
2064
2065    /**
2066     * The view flags hold various views states.
2067     * {@hide}
2068     */
2069    @ViewDebug.ExportedProperty
2070    int mViewFlags;
2071
2072    static class TransformationInfo {
2073        /**
2074         * The transform matrix for the View. This transform is calculated internally
2075         * based on the rotation, scaleX, and scaleY properties. The identity matrix
2076         * is used by default. Do *not* use this variable directly; instead call
2077         * getMatrix(), which will automatically recalculate the matrix if necessary
2078         * to get the correct matrix based on the latest rotation and scale properties.
2079         */
2080        private final Matrix mMatrix = new Matrix();
2081
2082        /**
2083         * The transform matrix for the View. This transform is calculated internally
2084         * based on the rotation, scaleX, and scaleY properties. The identity matrix
2085         * is used by default. Do *not* use this variable directly; instead call
2086         * getInverseMatrix(), which will automatically recalculate the matrix if necessary
2087         * to get the correct matrix based on the latest rotation and scale properties.
2088         */
2089        private Matrix mInverseMatrix;
2090
2091        /**
2092         * An internal variable that tracks whether we need to recalculate the
2093         * transform matrix, based on whether the rotation or scaleX/Y properties
2094         * have changed since the matrix was last calculated.
2095         */
2096        boolean mMatrixDirty = false;
2097
2098        /**
2099         * An internal variable that tracks whether we need to recalculate the
2100         * transform matrix, based on whether the rotation or scaleX/Y properties
2101         * have changed since the matrix was last calculated.
2102         */
2103        private boolean mInverseMatrixDirty = true;
2104
2105        /**
2106         * A variable that tracks whether we need to recalculate the
2107         * transform matrix, based on whether the rotation or scaleX/Y properties
2108         * have changed since the matrix was last calculated. This variable
2109         * is only valid after a call to updateMatrix() or to a function that
2110         * calls it such as getMatrix(), hasIdentityMatrix() and getInverseMatrix().
2111         */
2112        private boolean mMatrixIsIdentity = true;
2113
2114        /**
2115         * The Camera object is used to compute a 3D matrix when rotationX or rotationY are set.
2116         */
2117        private Camera mCamera = null;
2118
2119        /**
2120         * This matrix is used when computing the matrix for 3D rotations.
2121         */
2122        private Matrix matrix3D = null;
2123
2124        /**
2125         * These prev values are used to recalculate a centered pivot point when necessary. The
2126         * pivot point is only used in matrix operations (when rotation, scale, or translation are
2127         * set), so thes values are only used then as well.
2128         */
2129        private int mPrevWidth = -1;
2130        private int mPrevHeight = -1;
2131
2132        /**
2133         * The degrees rotation around the vertical axis through the pivot point.
2134         */
2135        @ViewDebug.ExportedProperty
2136        float mRotationY = 0f;
2137
2138        /**
2139         * The degrees rotation around the horizontal axis through the pivot point.
2140         */
2141        @ViewDebug.ExportedProperty
2142        float mRotationX = 0f;
2143
2144        /**
2145         * The degrees rotation around the pivot point.
2146         */
2147        @ViewDebug.ExportedProperty
2148        float mRotation = 0f;
2149
2150        /**
2151         * The amount of translation of the object away from its left property (post-layout).
2152         */
2153        @ViewDebug.ExportedProperty
2154        float mTranslationX = 0f;
2155
2156        /**
2157         * The amount of translation of the object away from its top property (post-layout).
2158         */
2159        @ViewDebug.ExportedProperty
2160        float mTranslationY = 0f;
2161
2162        /**
2163         * The amount of scale in the x direction around the pivot point. A
2164         * value of 1 means no scaling is applied.
2165         */
2166        @ViewDebug.ExportedProperty
2167        float mScaleX = 1f;
2168
2169        /**
2170         * The amount of scale in the y direction around the pivot point. A
2171         * value of 1 means no scaling is applied.
2172         */
2173        @ViewDebug.ExportedProperty
2174        float mScaleY = 1f;
2175
2176        /**
2177         * The x location of the point around which the view is rotated and scaled.
2178         */
2179        @ViewDebug.ExportedProperty
2180        float mPivotX = 0f;
2181
2182        /**
2183         * The y location of the point around which the view is rotated and scaled.
2184         */
2185        @ViewDebug.ExportedProperty
2186        float mPivotY = 0f;
2187
2188        /**
2189         * The opacity of the View. This is a value from 0 to 1, where 0 means
2190         * completely transparent and 1 means completely opaque.
2191         */
2192        @ViewDebug.ExportedProperty
2193        float mAlpha = 1f;
2194    }
2195
2196    TransformationInfo mTransformationInfo;
2197
2198    private boolean mLastIsOpaque;
2199
2200    /**
2201     * Convenience value to check for float values that are close enough to zero to be considered
2202     * zero.
2203     */
2204    private static final float NONZERO_EPSILON = .001f;
2205
2206    /**
2207     * The distance in pixels from the left edge of this view's parent
2208     * to the left edge of this view.
2209     * {@hide}
2210     */
2211    @ViewDebug.ExportedProperty(category = "layout")
2212    protected int mLeft;
2213    /**
2214     * The distance in pixels from the left edge of this view's parent
2215     * to the right edge of this view.
2216     * {@hide}
2217     */
2218    @ViewDebug.ExportedProperty(category = "layout")
2219    protected int mRight;
2220    /**
2221     * The distance in pixels from the top edge of this view's parent
2222     * to the top edge of this view.
2223     * {@hide}
2224     */
2225    @ViewDebug.ExportedProperty(category = "layout")
2226    protected int mTop;
2227    /**
2228     * The distance in pixels from the top edge of this view's parent
2229     * to the bottom edge of this view.
2230     * {@hide}
2231     */
2232    @ViewDebug.ExportedProperty(category = "layout")
2233    protected int mBottom;
2234
2235    /**
2236     * The offset, in pixels, by which the content of this view is scrolled
2237     * horizontally.
2238     * {@hide}
2239     */
2240    @ViewDebug.ExportedProperty(category = "scrolling")
2241    protected int mScrollX;
2242    /**
2243     * The offset, in pixels, by which the content of this view is scrolled
2244     * vertically.
2245     * {@hide}
2246     */
2247    @ViewDebug.ExportedProperty(category = "scrolling")
2248    protected int mScrollY;
2249
2250    /**
2251     * The left padding in pixels, that is the distance in pixels between the
2252     * left edge of this view and the left edge of its content.
2253     * {@hide}
2254     */
2255    @ViewDebug.ExportedProperty(category = "padding")
2256    protected int mPaddingLeft;
2257    /**
2258     * The right padding in pixels, that is the distance in pixels between the
2259     * right edge of this view and the right edge of its content.
2260     * {@hide}
2261     */
2262    @ViewDebug.ExportedProperty(category = "padding")
2263    protected int mPaddingRight;
2264    /**
2265     * The top padding in pixels, that is the distance in pixels between the
2266     * top edge of this view and the top edge of its content.
2267     * {@hide}
2268     */
2269    @ViewDebug.ExportedProperty(category = "padding")
2270    protected int mPaddingTop;
2271    /**
2272     * The bottom padding in pixels, that is the distance in pixels between the
2273     * bottom edge of this view and the bottom edge of its content.
2274     * {@hide}
2275     */
2276    @ViewDebug.ExportedProperty(category = "padding")
2277    protected int mPaddingBottom;
2278
2279    /**
2280     * Briefly describes the view and is primarily used for accessibility support.
2281     */
2282    private CharSequence mContentDescription;
2283
2284    /**
2285     * Cache the paddingRight set by the user to append to the scrollbar's size.
2286     *
2287     * @hide
2288     */
2289    @ViewDebug.ExportedProperty(category = "padding")
2290    protected int mUserPaddingRight;
2291
2292    /**
2293     * Cache the paddingBottom set by the user to append to the scrollbar's size.
2294     *
2295     * @hide
2296     */
2297    @ViewDebug.ExportedProperty(category = "padding")
2298    protected int mUserPaddingBottom;
2299
2300    /**
2301     * Cache the paddingLeft set by the user to append to the scrollbar's size.
2302     *
2303     * @hide
2304     */
2305    @ViewDebug.ExportedProperty(category = "padding")
2306    protected int mUserPaddingLeft;
2307
2308    /**
2309     * Cache if the user padding is relative.
2310     *
2311     */
2312    @ViewDebug.ExportedProperty(category = "padding")
2313    boolean mUserPaddingRelative;
2314
2315    /**
2316     * Cache the paddingStart set by the user to append to the scrollbar's size.
2317     *
2318     */
2319    @ViewDebug.ExportedProperty(category = "padding")
2320    int mUserPaddingStart;
2321
2322    /**
2323     * Cache the paddingEnd set by the user to append to the scrollbar's size.
2324     *
2325     */
2326    @ViewDebug.ExportedProperty(category = "padding")
2327    int mUserPaddingEnd;
2328
2329    /**
2330     * @hide
2331     */
2332    int mOldWidthMeasureSpec = Integer.MIN_VALUE;
2333    /**
2334     * @hide
2335     */
2336    int mOldHeightMeasureSpec = Integer.MIN_VALUE;
2337
2338    private Drawable mBGDrawable;
2339
2340    private int mBackgroundResource;
2341    private boolean mBackgroundSizeChanged;
2342
2343    static class ListenerInfo {
2344        /**
2345         * Listener used to dispatch focus change events.
2346         * This field should be made private, so it is hidden from the SDK.
2347         * {@hide}
2348         */
2349        protected OnFocusChangeListener mOnFocusChangeListener;
2350
2351        /**
2352         * Listeners for layout change events.
2353         */
2354        private ArrayList<OnLayoutChangeListener> mOnLayoutChangeListeners;
2355
2356        /**
2357         * Listeners for attach events.
2358         */
2359        private CopyOnWriteArrayList<OnAttachStateChangeListener> mOnAttachStateChangeListeners;
2360
2361        /**
2362         * Listener used to dispatch click events.
2363         * This field should be made private, so it is hidden from the SDK.
2364         * {@hide}
2365         */
2366        public OnClickListener mOnClickListener;
2367
2368        /**
2369         * Listener used to dispatch long click events.
2370         * This field should be made private, so it is hidden from the SDK.
2371         * {@hide}
2372         */
2373        protected OnLongClickListener mOnLongClickListener;
2374
2375        /**
2376         * Listener used to build the context menu.
2377         * This field should be made private, so it is hidden from the SDK.
2378         * {@hide}
2379         */
2380        protected OnCreateContextMenuListener mOnCreateContextMenuListener;
2381
2382        private OnKeyListener mOnKeyListener;
2383
2384        private OnTouchListener mOnTouchListener;
2385
2386        private OnHoverListener mOnHoverListener;
2387
2388        private OnGenericMotionListener mOnGenericMotionListener;
2389
2390        private OnDragListener mOnDragListener;
2391
2392        private OnSystemUiVisibilityChangeListener mOnSystemUiVisibilityChangeListener;
2393    }
2394
2395    ListenerInfo mListenerInfo;
2396
2397    /**
2398     * The application environment this view lives in.
2399     * This field should be made private, so it is hidden from the SDK.
2400     * {@hide}
2401     */
2402    protected Context mContext;
2403
2404    private final Resources mResources;
2405
2406    private ScrollabilityCache mScrollCache;
2407
2408    private int[] mDrawableState = null;
2409
2410    /**
2411     * Set to true when drawing cache is enabled and cannot be created.
2412     *
2413     * @hide
2414     */
2415    public boolean mCachingFailed;
2416
2417    private Bitmap mDrawingCache;
2418    private Bitmap mUnscaledDrawingCache;
2419    private HardwareLayer mHardwareLayer;
2420    DisplayList mDisplayList;
2421
2422    /**
2423     * When this view has focus and the next focus is {@link #FOCUS_LEFT},
2424     * the user may specify which view to go to next.
2425     */
2426    private int mNextFocusLeftId = View.NO_ID;
2427
2428    /**
2429     * When this view has focus and the next focus is {@link #FOCUS_RIGHT},
2430     * the user may specify which view to go to next.
2431     */
2432    private int mNextFocusRightId = View.NO_ID;
2433
2434    /**
2435     * When this view has focus and the next focus is {@link #FOCUS_UP},
2436     * the user may specify which view to go to next.
2437     */
2438    private int mNextFocusUpId = View.NO_ID;
2439
2440    /**
2441     * When this view has focus and the next focus is {@link #FOCUS_DOWN},
2442     * the user may specify which view to go to next.
2443     */
2444    private int mNextFocusDownId = View.NO_ID;
2445
2446    /**
2447     * When this view has focus and the next focus is {@link #FOCUS_FORWARD},
2448     * the user may specify which view to go to next.
2449     */
2450    int mNextFocusForwardId = View.NO_ID;
2451
2452    private CheckForLongPress mPendingCheckForLongPress;
2453    private CheckForTap mPendingCheckForTap = null;
2454    private PerformClick mPerformClick;
2455    private SendViewScrolledAccessibilityEvent mSendViewScrolledAccessibilityEvent;
2456
2457    private UnsetPressedState mUnsetPressedState;
2458
2459    /**
2460     * Whether the long press's action has been invoked.  The tap's action is invoked on the
2461     * up event while a long press is invoked as soon as the long press duration is reached, so
2462     * a long press could be performed before the tap is checked, in which case the tap's action
2463     * should not be invoked.
2464     */
2465    private boolean mHasPerformedLongPress;
2466
2467    /**
2468     * The minimum height of the view. We'll try our best to have the height
2469     * of this view to at least this amount.
2470     */
2471    @ViewDebug.ExportedProperty(category = "measurement")
2472    private int mMinHeight;
2473
2474    /**
2475     * The minimum width of the view. We'll try our best to have the width
2476     * of this view to at least this amount.
2477     */
2478    @ViewDebug.ExportedProperty(category = "measurement")
2479    private int mMinWidth;
2480
2481    /**
2482     * The delegate to handle touch events that are physically in this view
2483     * but should be handled by another view.
2484     */
2485    private TouchDelegate mTouchDelegate = null;
2486
2487    /**
2488     * Solid color to use as a background when creating the drawing cache. Enables
2489     * the cache to use 16 bit bitmaps instead of 32 bit.
2490     */
2491    private int mDrawingCacheBackgroundColor = 0;
2492
2493    /**
2494     * Special tree observer used when mAttachInfo is null.
2495     */
2496    private ViewTreeObserver mFloatingTreeObserver;
2497
2498    /**
2499     * Cache the touch slop from the context that created the view.
2500     */
2501    private int mTouchSlop;
2502
2503    /**
2504     * Object that handles automatic animation of view properties.
2505     */
2506    private ViewPropertyAnimator mAnimator = null;
2507
2508    /**
2509     * Flag indicating that a drag can cross window boundaries.  When
2510     * {@link #startDrag(ClipData, DragShadowBuilder, Object, int)} is called
2511     * with this flag set, all visible applications will be able to participate
2512     * in the drag operation and receive the dragged content.
2513     *
2514     * @hide
2515     */
2516    public static final int DRAG_FLAG_GLOBAL = 1;
2517
2518    /**
2519     * Vertical scroll factor cached by {@link #getVerticalScrollFactor}.
2520     */
2521    private float mVerticalScrollFactor;
2522
2523    /**
2524     * Position of the vertical scroll bar.
2525     */
2526    private int mVerticalScrollbarPosition;
2527
2528    /**
2529     * Position the scroll bar at the default position as determined by the system.
2530     */
2531    public static final int SCROLLBAR_POSITION_DEFAULT = 0;
2532
2533    /**
2534     * Position the scroll bar along the left edge.
2535     */
2536    public static final int SCROLLBAR_POSITION_LEFT = 1;
2537
2538    /**
2539     * Position the scroll bar along the right edge.
2540     */
2541    public static final int SCROLLBAR_POSITION_RIGHT = 2;
2542
2543    /**
2544     * Indicates that the view does not have a layer.
2545     *
2546     * @see #getLayerType()
2547     * @see #setLayerType(int, android.graphics.Paint)
2548     * @see #LAYER_TYPE_SOFTWARE
2549     * @see #LAYER_TYPE_HARDWARE
2550     */
2551    public static final int LAYER_TYPE_NONE = 0;
2552
2553    /**
2554     * <p>Indicates that the view has a software layer. A software layer is backed
2555     * by a bitmap and causes the view to be rendered using Android's software
2556     * rendering pipeline, even if hardware acceleration is enabled.</p>
2557     *
2558     * <p>Software layers have various usages:</p>
2559     * <p>When the application is not using hardware acceleration, a software layer
2560     * is useful to apply a specific color filter and/or blending mode and/or
2561     * translucency to a view and all its children.</p>
2562     * <p>When the application is using hardware acceleration, a software layer
2563     * is useful to render drawing primitives not supported by the hardware
2564     * accelerated pipeline. It can also be used to cache a complex view tree
2565     * into a texture and reduce the complexity of drawing operations. For instance,
2566     * when animating a complex view tree with a translation, a software layer can
2567     * be used to render the view tree only once.</p>
2568     * <p>Software layers should be avoided when the affected view tree updates
2569     * often. Every update will require to re-render the software layer, which can
2570     * potentially be slow (particularly when hardware acceleration is turned on
2571     * since the layer will have to be uploaded into a hardware texture after every
2572     * update.)</p>
2573     *
2574     * @see #getLayerType()
2575     * @see #setLayerType(int, android.graphics.Paint)
2576     * @see #LAYER_TYPE_NONE
2577     * @see #LAYER_TYPE_HARDWARE
2578     */
2579    public static final int LAYER_TYPE_SOFTWARE = 1;
2580
2581    /**
2582     * <p>Indicates that the view has a hardware layer. A hardware layer is backed
2583     * by a hardware specific texture (generally Frame Buffer Objects or FBO on
2584     * OpenGL hardware) and causes the view to be rendered using Android's hardware
2585     * rendering pipeline, but only if hardware acceleration is turned on for the
2586     * view hierarchy. When hardware acceleration is turned off, hardware layers
2587     * behave exactly as {@link #LAYER_TYPE_SOFTWARE software layers}.</p>
2588     *
2589     * <p>A hardware layer is useful to apply a specific color filter and/or
2590     * blending mode and/or translucency to a view and all its children.</p>
2591     * <p>A hardware layer can be used to cache a complex view tree into a
2592     * texture and reduce the complexity of drawing operations. For instance,
2593     * when animating a complex view tree with a translation, a hardware layer can
2594     * be used to render the view tree only once.</p>
2595     * <p>A hardware layer can also be used to increase the rendering quality when
2596     * rotation transformations are applied on a view. It can also be used to
2597     * prevent potential clipping issues when applying 3D transforms on a view.</p>
2598     *
2599     * @see #getLayerType()
2600     * @see #setLayerType(int, android.graphics.Paint)
2601     * @see #LAYER_TYPE_NONE
2602     * @see #LAYER_TYPE_SOFTWARE
2603     */
2604    public static final int LAYER_TYPE_HARDWARE = 2;
2605
2606    @ViewDebug.ExportedProperty(category = "drawing", mapping = {
2607            @ViewDebug.IntToString(from = LAYER_TYPE_NONE, to = "NONE"),
2608            @ViewDebug.IntToString(from = LAYER_TYPE_SOFTWARE, to = "SOFTWARE"),
2609            @ViewDebug.IntToString(from = LAYER_TYPE_HARDWARE, to = "HARDWARE")
2610    })
2611    int mLayerType = LAYER_TYPE_NONE;
2612    Paint mLayerPaint;
2613    Rect mLocalDirtyRect;
2614
2615    /**
2616     * Set to true when the view is sending hover accessibility events because it
2617     * is the innermost hovered view.
2618     */
2619    private boolean mSendingHoverAccessibilityEvents;
2620
2621    /**
2622     * Delegate for injecting accessiblity functionality.
2623     */
2624    AccessibilityDelegate mAccessibilityDelegate;
2625
2626    /**
2627     * Text direction is inherited thru {@link ViewGroup}
2628     */
2629    public static final int TEXT_DIRECTION_INHERIT = 0;
2630
2631    /**
2632     * Text direction is using "first strong algorithm". The first strong directional character
2633     * determines the paragraph direction. If there is no strong directional character, the
2634     * paragraph direction is the view's resolved layout direction.
2635     *
2636     */
2637    public static final int TEXT_DIRECTION_FIRST_STRONG = 1;
2638
2639    /**
2640     * Text direction is using "any-RTL" algorithm. The paragraph direction is RTL if it contains
2641     * any strong RTL character, otherwise it is LTR if it contains any strong LTR characters.
2642     * If there are neither, the paragraph direction is the view's resolved layout direction.
2643     *
2644     */
2645    public static final int TEXT_DIRECTION_ANY_RTL = 2;
2646
2647    /**
2648     * Text direction is forced to LTR.
2649     *
2650     */
2651    public static final int TEXT_DIRECTION_LTR = 3;
2652
2653    /**
2654     * Text direction is forced to RTL.
2655     *
2656     */
2657    public static final int TEXT_DIRECTION_RTL = 4;
2658
2659    /**
2660     * Text direction is coming from the system Locale.
2661     *
2662     */
2663    public static final int TEXT_DIRECTION_LOCALE = 5;
2664
2665    /**
2666     * Default text direction is inherited
2667     *
2668     */
2669    protected static int DEFAULT_TEXT_DIRECTION = TEXT_DIRECTION_INHERIT;
2670
2671    /**
2672     * The text direction that has been defined by {@link #setTextDirection(int)}.
2673     *
2674     */
2675    @ViewDebug.ExportedProperty(category = "text", mapping = {
2676            @ViewDebug.IntToString(from = TEXT_DIRECTION_INHERIT, to = "INHERIT"),
2677            @ViewDebug.IntToString(from = TEXT_DIRECTION_FIRST_STRONG, to = "FIRST_STRONG"),
2678            @ViewDebug.IntToString(from = TEXT_DIRECTION_ANY_RTL, to = "ANY_RTL"),
2679            @ViewDebug.IntToString(from = TEXT_DIRECTION_LTR, to = "LTR"),
2680            @ViewDebug.IntToString(from = TEXT_DIRECTION_RTL, to = "RTL"),
2681            @ViewDebug.IntToString(from = TEXT_DIRECTION_LOCALE, to = "LOCALE")
2682    })
2683    private int mTextDirection = DEFAULT_TEXT_DIRECTION;
2684
2685    /**
2686     * The resolved text direction.  This needs resolution if the value is
2687     * TEXT_DIRECTION_INHERIT.  The resolution matches mTextDirection if it is
2688     * not TEXT_DIRECTION_INHERIT, otherwise resolution proceeds up the parent
2689     * chain of the view.
2690     *
2691     */
2692    @ViewDebug.ExportedProperty(category = "text", mapping = {
2693            @ViewDebug.IntToString(from = TEXT_DIRECTION_INHERIT, to = "INHERIT"),
2694            @ViewDebug.IntToString(from = TEXT_DIRECTION_FIRST_STRONG, to = "FIRST_STRONG"),
2695            @ViewDebug.IntToString(from = TEXT_DIRECTION_ANY_RTL, to = "ANY_RTL"),
2696            @ViewDebug.IntToString(from = TEXT_DIRECTION_LTR, to = "LTR"),
2697            @ViewDebug.IntToString(from = TEXT_DIRECTION_RTL, to = "RTL"),
2698            @ViewDebug.IntToString(from = TEXT_DIRECTION_LOCALE, to = "LOCALE")
2699    })
2700    private int mResolvedTextDirection = TEXT_DIRECTION_INHERIT;
2701
2702    /**
2703     * Consistency verifier for debugging purposes.
2704     * @hide
2705     */
2706    protected final InputEventConsistencyVerifier mInputEventConsistencyVerifier =
2707            InputEventConsistencyVerifier.isInstrumentationEnabled() ?
2708                    new InputEventConsistencyVerifier(this, 0) : null;
2709
2710    /**
2711     * Simple constructor to use when creating a view from code.
2712     *
2713     * @param context The Context the view is running in, through which it can
2714     *        access the current theme, resources, etc.
2715     */
2716    public View(Context context) {
2717        mContext = context;
2718        mResources = context != null ? context.getResources() : null;
2719        mViewFlags = SOUND_EFFECTS_ENABLED | HAPTIC_FEEDBACK_ENABLED | LAYOUT_DIRECTION_INHERIT;
2720        mTouchSlop = ViewConfiguration.get(context).getScaledTouchSlop();
2721        setOverScrollMode(OVER_SCROLL_IF_CONTENT_SCROLLS);
2722        mUserPaddingStart = -1;
2723        mUserPaddingEnd = -1;
2724        mUserPaddingRelative = false;
2725    }
2726
2727    /**
2728     * Constructor that is called when inflating a view from XML. This is called
2729     * when a view is being constructed from an XML file, supplying attributes
2730     * that were specified in the XML file. This version uses a default style of
2731     * 0, so the only attribute values applied are those in the Context's Theme
2732     * and the given AttributeSet.
2733     *
2734     * <p>
2735     * The method onFinishInflate() will be called after all children have been
2736     * added.
2737     *
2738     * @param context The Context the view is running in, through which it can
2739     *        access the current theme, resources, etc.
2740     * @param attrs The attributes of the XML tag that is inflating the view.
2741     * @see #View(Context, AttributeSet, int)
2742     */
2743    public View(Context context, AttributeSet attrs) {
2744        this(context, attrs, 0);
2745    }
2746
2747    /**
2748     * Perform inflation from XML and apply a class-specific base style. This
2749     * constructor of View allows subclasses to use their own base style when
2750     * they are inflating. For example, a Button class's constructor would call
2751     * this version of the super class constructor and supply
2752     * <code>R.attr.buttonStyle</code> for <var>defStyle</var>; this allows
2753     * the theme's button style to modify all of the base view attributes (in
2754     * particular its background) as well as the Button class's attributes.
2755     *
2756     * @param context The Context the view is running in, through which it can
2757     *        access the current theme, resources, etc.
2758     * @param attrs The attributes of the XML tag that is inflating the view.
2759     * @param defStyle The default style to apply to this view. If 0, no style
2760     *        will be applied (beyond what is included in the theme). This may
2761     *        either be an attribute resource, whose value will be retrieved
2762     *        from the current theme, or an explicit style resource.
2763     * @see #View(Context, AttributeSet)
2764     */
2765    public View(Context context, AttributeSet attrs, int defStyle) {
2766        this(context);
2767
2768        TypedArray a = context.obtainStyledAttributes(attrs, com.android.internal.R.styleable.View,
2769                defStyle, 0);
2770
2771        Drawable background = null;
2772
2773        int leftPadding = -1;
2774        int topPadding = -1;
2775        int rightPadding = -1;
2776        int bottomPadding = -1;
2777        int startPadding = -1;
2778        int endPadding = -1;
2779
2780        int padding = -1;
2781
2782        int viewFlagValues = 0;
2783        int viewFlagMasks = 0;
2784
2785        boolean setScrollContainer = false;
2786
2787        int x = 0;
2788        int y = 0;
2789
2790        float tx = 0;
2791        float ty = 0;
2792        float rotation = 0;
2793        float rotationX = 0;
2794        float rotationY = 0;
2795        float sx = 1f;
2796        float sy = 1f;
2797        boolean transformSet = false;
2798
2799        int scrollbarStyle = SCROLLBARS_INSIDE_OVERLAY;
2800
2801        int overScrollMode = mOverScrollMode;
2802        final int N = a.getIndexCount();
2803        for (int i = 0; i < N; i++) {
2804            int attr = a.getIndex(i);
2805            switch (attr) {
2806                case com.android.internal.R.styleable.View_background:
2807                    background = a.getDrawable(attr);
2808                    break;
2809                case com.android.internal.R.styleable.View_padding:
2810                    padding = a.getDimensionPixelSize(attr, -1);
2811                    break;
2812                 case com.android.internal.R.styleable.View_paddingLeft:
2813                    leftPadding = a.getDimensionPixelSize(attr, -1);
2814                    break;
2815                case com.android.internal.R.styleable.View_paddingTop:
2816                    topPadding = a.getDimensionPixelSize(attr, -1);
2817                    break;
2818                case com.android.internal.R.styleable.View_paddingRight:
2819                    rightPadding = a.getDimensionPixelSize(attr, -1);
2820                    break;
2821                case com.android.internal.R.styleable.View_paddingBottom:
2822                    bottomPadding = a.getDimensionPixelSize(attr, -1);
2823                    break;
2824                case com.android.internal.R.styleable.View_paddingStart:
2825                    startPadding = a.getDimensionPixelSize(attr, -1);
2826                    break;
2827                case com.android.internal.R.styleable.View_paddingEnd:
2828                    endPadding = a.getDimensionPixelSize(attr, -1);
2829                    break;
2830                case com.android.internal.R.styleable.View_scrollX:
2831                    x = a.getDimensionPixelOffset(attr, 0);
2832                    break;
2833                case com.android.internal.R.styleable.View_scrollY:
2834                    y = a.getDimensionPixelOffset(attr, 0);
2835                    break;
2836                case com.android.internal.R.styleable.View_alpha:
2837                    setAlpha(a.getFloat(attr, 1f));
2838                    break;
2839                case com.android.internal.R.styleable.View_transformPivotX:
2840                    setPivotX(a.getDimensionPixelOffset(attr, 0));
2841                    break;
2842                case com.android.internal.R.styleable.View_transformPivotY:
2843                    setPivotY(a.getDimensionPixelOffset(attr, 0));
2844                    break;
2845                case com.android.internal.R.styleable.View_translationX:
2846                    tx = a.getDimensionPixelOffset(attr, 0);
2847                    transformSet = true;
2848                    break;
2849                case com.android.internal.R.styleable.View_translationY:
2850                    ty = a.getDimensionPixelOffset(attr, 0);
2851                    transformSet = true;
2852                    break;
2853                case com.android.internal.R.styleable.View_rotation:
2854                    rotation = a.getFloat(attr, 0);
2855                    transformSet = true;
2856                    break;
2857                case com.android.internal.R.styleable.View_rotationX:
2858                    rotationX = a.getFloat(attr, 0);
2859                    transformSet = true;
2860                    break;
2861                case com.android.internal.R.styleable.View_rotationY:
2862                    rotationY = a.getFloat(attr, 0);
2863                    transformSet = true;
2864                    break;
2865                case com.android.internal.R.styleable.View_scaleX:
2866                    sx = a.getFloat(attr, 1f);
2867                    transformSet = true;
2868                    break;
2869                case com.android.internal.R.styleable.View_scaleY:
2870                    sy = a.getFloat(attr, 1f);
2871                    transformSet = true;
2872                    break;
2873                case com.android.internal.R.styleable.View_id:
2874                    mID = a.getResourceId(attr, NO_ID);
2875                    break;
2876                case com.android.internal.R.styleable.View_tag:
2877                    mTag = a.getText(attr);
2878                    break;
2879                case com.android.internal.R.styleable.View_fitsSystemWindows:
2880                    if (a.getBoolean(attr, false)) {
2881                        viewFlagValues |= FITS_SYSTEM_WINDOWS;
2882                        viewFlagMasks |= FITS_SYSTEM_WINDOWS;
2883                    }
2884                    break;
2885                case com.android.internal.R.styleable.View_focusable:
2886                    if (a.getBoolean(attr, false)) {
2887                        viewFlagValues |= FOCUSABLE;
2888                        viewFlagMasks |= FOCUSABLE_MASK;
2889                    }
2890                    break;
2891                case com.android.internal.R.styleable.View_focusableInTouchMode:
2892                    if (a.getBoolean(attr, false)) {
2893                        viewFlagValues |= FOCUSABLE_IN_TOUCH_MODE | FOCUSABLE;
2894                        viewFlagMasks |= FOCUSABLE_IN_TOUCH_MODE | FOCUSABLE_MASK;
2895                    }
2896                    break;
2897                case com.android.internal.R.styleable.View_clickable:
2898                    if (a.getBoolean(attr, false)) {
2899                        viewFlagValues |= CLICKABLE;
2900                        viewFlagMasks |= CLICKABLE;
2901                    }
2902                    break;
2903                case com.android.internal.R.styleable.View_longClickable:
2904                    if (a.getBoolean(attr, false)) {
2905                        viewFlagValues |= LONG_CLICKABLE;
2906                        viewFlagMasks |= LONG_CLICKABLE;
2907                    }
2908                    break;
2909                case com.android.internal.R.styleable.View_saveEnabled:
2910                    if (!a.getBoolean(attr, true)) {
2911                        viewFlagValues |= SAVE_DISABLED;
2912                        viewFlagMasks |= SAVE_DISABLED_MASK;
2913                    }
2914                    break;
2915                case com.android.internal.R.styleable.View_duplicateParentState:
2916                    if (a.getBoolean(attr, false)) {
2917                        viewFlagValues |= DUPLICATE_PARENT_STATE;
2918                        viewFlagMasks |= DUPLICATE_PARENT_STATE;
2919                    }
2920                    break;
2921                case com.android.internal.R.styleable.View_visibility:
2922                    final int visibility = a.getInt(attr, 0);
2923                    if (visibility != 0) {
2924                        viewFlagValues |= VISIBILITY_FLAGS[visibility];
2925                        viewFlagMasks |= VISIBILITY_MASK;
2926                    }
2927                    break;
2928                case com.android.internal.R.styleable.View_layoutDirection:
2929                    // Clear any HORIZONTAL_DIRECTION flag already set
2930                    viewFlagValues &= ~LAYOUT_DIRECTION_MASK;
2931                    // Set the HORIZONTAL_DIRECTION flags depending on the value of the attribute
2932                    final int layoutDirection = a.getInt(attr, -1);
2933                    if (layoutDirection != -1) {
2934                        viewFlagValues |= LAYOUT_DIRECTION_FLAGS[layoutDirection];
2935                    } else {
2936                        // Set to default (LAYOUT_DIRECTION_INHERIT)
2937                        viewFlagValues |= LAYOUT_DIRECTION_DEFAULT;
2938                    }
2939                    viewFlagMasks |= LAYOUT_DIRECTION_MASK;
2940                    break;
2941                case com.android.internal.R.styleable.View_drawingCacheQuality:
2942                    final int cacheQuality = a.getInt(attr, 0);
2943                    if (cacheQuality != 0) {
2944                        viewFlagValues |= DRAWING_CACHE_QUALITY_FLAGS[cacheQuality];
2945                        viewFlagMasks |= DRAWING_CACHE_QUALITY_MASK;
2946                    }
2947                    break;
2948                case com.android.internal.R.styleable.View_contentDescription:
2949                    mContentDescription = a.getString(attr);
2950                    break;
2951                case com.android.internal.R.styleable.View_soundEffectsEnabled:
2952                    if (!a.getBoolean(attr, true)) {
2953                        viewFlagValues &= ~SOUND_EFFECTS_ENABLED;
2954                        viewFlagMasks |= SOUND_EFFECTS_ENABLED;
2955                    }
2956                    break;
2957                case com.android.internal.R.styleable.View_hapticFeedbackEnabled:
2958                    if (!a.getBoolean(attr, true)) {
2959                        viewFlagValues &= ~HAPTIC_FEEDBACK_ENABLED;
2960                        viewFlagMasks |= HAPTIC_FEEDBACK_ENABLED;
2961                    }
2962                    break;
2963                case R.styleable.View_scrollbars:
2964                    final int scrollbars = a.getInt(attr, SCROLLBARS_NONE);
2965                    if (scrollbars != SCROLLBARS_NONE) {
2966                        viewFlagValues |= scrollbars;
2967                        viewFlagMasks |= SCROLLBARS_MASK;
2968                        initializeScrollbars(a);
2969                    }
2970                    break;
2971                //noinspection deprecation
2972                case R.styleable.View_fadingEdge:
2973                    if (context.getApplicationInfo().targetSdkVersion >= ICE_CREAM_SANDWICH) {
2974                        // Ignore the attribute starting with ICS
2975                        break;
2976                    }
2977                    // With builds < ICS, fall through and apply fading edges
2978                case R.styleable.View_requiresFadingEdge:
2979                    final int fadingEdge = a.getInt(attr, FADING_EDGE_NONE);
2980                    if (fadingEdge != FADING_EDGE_NONE) {
2981                        viewFlagValues |= fadingEdge;
2982                        viewFlagMasks |= FADING_EDGE_MASK;
2983                        initializeFadingEdge(a);
2984                    }
2985                    break;
2986                case R.styleable.View_scrollbarStyle:
2987                    scrollbarStyle = a.getInt(attr, SCROLLBARS_INSIDE_OVERLAY);
2988                    if (scrollbarStyle != SCROLLBARS_INSIDE_OVERLAY) {
2989                        viewFlagValues |= scrollbarStyle & SCROLLBARS_STYLE_MASK;
2990                        viewFlagMasks |= SCROLLBARS_STYLE_MASK;
2991                    }
2992                    break;
2993                case R.styleable.View_isScrollContainer:
2994                    setScrollContainer = true;
2995                    if (a.getBoolean(attr, false)) {
2996                        setScrollContainer(true);
2997                    }
2998                    break;
2999                case com.android.internal.R.styleable.View_keepScreenOn:
3000                    if (a.getBoolean(attr, false)) {
3001                        viewFlagValues |= KEEP_SCREEN_ON;
3002                        viewFlagMasks |= KEEP_SCREEN_ON;
3003                    }
3004                    break;
3005                case R.styleable.View_filterTouchesWhenObscured:
3006                    if (a.getBoolean(attr, false)) {
3007                        viewFlagValues |= FILTER_TOUCHES_WHEN_OBSCURED;
3008                        viewFlagMasks |= FILTER_TOUCHES_WHEN_OBSCURED;
3009                    }
3010                    break;
3011                case R.styleable.View_nextFocusLeft:
3012                    mNextFocusLeftId = a.getResourceId(attr, View.NO_ID);
3013                    break;
3014                case R.styleable.View_nextFocusRight:
3015                    mNextFocusRightId = a.getResourceId(attr, View.NO_ID);
3016                    break;
3017                case R.styleable.View_nextFocusUp:
3018                    mNextFocusUpId = a.getResourceId(attr, View.NO_ID);
3019                    break;
3020                case R.styleable.View_nextFocusDown:
3021                    mNextFocusDownId = a.getResourceId(attr, View.NO_ID);
3022                    break;
3023                case R.styleable.View_nextFocusForward:
3024                    mNextFocusForwardId = a.getResourceId(attr, View.NO_ID);
3025                    break;
3026                case R.styleable.View_minWidth:
3027                    mMinWidth = a.getDimensionPixelSize(attr, 0);
3028                    break;
3029                case R.styleable.View_minHeight:
3030                    mMinHeight = a.getDimensionPixelSize(attr, 0);
3031                    break;
3032                case R.styleable.View_onClick:
3033                    if (context.isRestricted()) {
3034                        throw new IllegalStateException("The android:onClick attribute cannot "
3035                                + "be used within a restricted context");
3036                    }
3037
3038                    final String handlerName = a.getString(attr);
3039                    if (handlerName != null) {
3040                        setOnClickListener(new OnClickListener() {
3041                            private Method mHandler;
3042
3043                            public void onClick(View v) {
3044                                if (mHandler == null) {
3045                                    try {
3046                                        mHandler = getContext().getClass().getMethod(handlerName,
3047                                                View.class);
3048                                    } catch (NoSuchMethodException e) {
3049                                        int id = getId();
3050                                        String idText = id == NO_ID ? "" : " with id '"
3051                                                + getContext().getResources().getResourceEntryName(
3052                                                    id) + "'";
3053                                        throw new IllegalStateException("Could not find a method " +
3054                                                handlerName + "(View) in the activity "
3055                                                + getContext().getClass() + " for onClick handler"
3056                                                + " on view " + View.this.getClass() + idText, e);
3057                                    }
3058                                }
3059
3060                                try {
3061                                    mHandler.invoke(getContext(), View.this);
3062                                } catch (IllegalAccessException e) {
3063                                    throw new IllegalStateException("Could not execute non "
3064                                            + "public method of the activity", e);
3065                                } catch (InvocationTargetException e) {
3066                                    throw new IllegalStateException("Could not execute "
3067                                            + "method of the activity", e);
3068                                }
3069                            }
3070                        });
3071                    }
3072                    break;
3073                case R.styleable.View_overScrollMode:
3074                    overScrollMode = a.getInt(attr, OVER_SCROLL_IF_CONTENT_SCROLLS);
3075                    break;
3076                case R.styleable.View_verticalScrollbarPosition:
3077                    mVerticalScrollbarPosition = a.getInt(attr, SCROLLBAR_POSITION_DEFAULT);
3078                    break;
3079                case R.styleable.View_layerType:
3080                    setLayerType(a.getInt(attr, LAYER_TYPE_NONE), null);
3081                    break;
3082                case R.styleable.View_textDirection:
3083                    mTextDirection = a.getInt(attr, DEFAULT_TEXT_DIRECTION);
3084                    break;
3085            }
3086        }
3087
3088        a.recycle();
3089
3090        setOverScrollMode(overScrollMode);
3091
3092        if (background != null) {
3093            setBackgroundDrawable(background);
3094        }
3095
3096        // Cache user padding as we cannot fully resolve padding here (we dont have yet the resolved
3097        // layout direction). Those cached values will be used later during padding resolution.
3098        mUserPaddingStart = startPadding;
3099        mUserPaddingEnd = endPadding;
3100
3101        updateUserPaddingRelative();
3102
3103        if (padding >= 0) {
3104            leftPadding = padding;
3105            topPadding = padding;
3106            rightPadding = padding;
3107            bottomPadding = padding;
3108        }
3109
3110        // If the user specified the padding (either with android:padding or
3111        // android:paddingLeft/Top/Right/Bottom), use this padding, otherwise
3112        // use the default padding or the padding from the background drawable
3113        // (stored at this point in mPadding*)
3114        setPadding(leftPadding >= 0 ? leftPadding : mPaddingLeft,
3115                topPadding >= 0 ? topPadding : mPaddingTop,
3116                rightPadding >= 0 ? rightPadding : mPaddingRight,
3117                bottomPadding >= 0 ? bottomPadding : mPaddingBottom);
3118
3119        if (viewFlagMasks != 0) {
3120            setFlags(viewFlagValues, viewFlagMasks);
3121        }
3122
3123        // Needs to be called after mViewFlags is set
3124        if (scrollbarStyle != SCROLLBARS_INSIDE_OVERLAY) {
3125            recomputePadding();
3126        }
3127
3128        if (x != 0 || y != 0) {
3129            scrollTo(x, y);
3130        }
3131
3132        if (transformSet) {
3133            setTranslationX(tx);
3134            setTranslationY(ty);
3135            setRotation(rotation);
3136            setRotationX(rotationX);
3137            setRotationY(rotationY);
3138            setScaleX(sx);
3139            setScaleY(sy);
3140        }
3141
3142        if (!setScrollContainer && (viewFlagValues&SCROLLBARS_VERTICAL) != 0) {
3143            setScrollContainer(true);
3144        }
3145
3146        computeOpaqueFlags();
3147    }
3148
3149    private void updateUserPaddingRelative() {
3150        mUserPaddingRelative = (mUserPaddingStart >= 0 || mUserPaddingEnd >= 0);
3151    }
3152
3153    /**
3154     * Non-public constructor for use in testing
3155     */
3156    View() {
3157        mResources = null;
3158    }
3159
3160    /**
3161     * <p>
3162     * Initializes the fading edges from a given set of styled attributes. This
3163     * method should be called by subclasses that need fading edges and when an
3164     * instance of these subclasses is created programmatically rather than
3165     * being inflated from XML. This method is automatically called when the XML
3166     * is inflated.
3167     * </p>
3168     *
3169     * @param a the styled attributes set to initialize the fading edges from
3170     */
3171    protected void initializeFadingEdge(TypedArray a) {
3172        initScrollCache();
3173
3174        mScrollCache.fadingEdgeLength = a.getDimensionPixelSize(
3175                R.styleable.View_fadingEdgeLength,
3176                ViewConfiguration.get(mContext).getScaledFadingEdgeLength());
3177    }
3178
3179    /**
3180     * Returns the size of the vertical faded edges used to indicate that more
3181     * content in this view is visible.
3182     *
3183     * @return The size in pixels of the vertical faded edge or 0 if vertical
3184     *         faded edges are not enabled for this view.
3185     * @attr ref android.R.styleable#View_fadingEdgeLength
3186     */
3187    public int getVerticalFadingEdgeLength() {
3188        if (isVerticalFadingEdgeEnabled()) {
3189            ScrollabilityCache cache = mScrollCache;
3190            if (cache != null) {
3191                return cache.fadingEdgeLength;
3192            }
3193        }
3194        return 0;
3195    }
3196
3197    /**
3198     * Set the size of the faded edge used to indicate that more content in this
3199     * view is available.  Will not change whether the fading edge is enabled; use
3200     * {@link #setVerticalFadingEdgeEnabled(boolean)} or
3201     * {@link #setHorizontalFadingEdgeEnabled(boolean)} to enable the fading edge
3202     * for the vertical or horizontal fading edges.
3203     *
3204     * @param length The size in pixels of the faded edge used to indicate that more
3205     *        content in this view is visible.
3206     */
3207    public void setFadingEdgeLength(int length) {
3208        initScrollCache();
3209        mScrollCache.fadingEdgeLength = length;
3210    }
3211
3212    /**
3213     * Returns the size of the horizontal faded edges used to indicate that more
3214     * content in this view is visible.
3215     *
3216     * @return The size in pixels of the horizontal faded edge or 0 if horizontal
3217     *         faded edges are not enabled for this view.
3218     * @attr ref android.R.styleable#View_fadingEdgeLength
3219     */
3220    public int getHorizontalFadingEdgeLength() {
3221        if (isHorizontalFadingEdgeEnabled()) {
3222            ScrollabilityCache cache = mScrollCache;
3223            if (cache != null) {
3224                return cache.fadingEdgeLength;
3225            }
3226        }
3227        return 0;
3228    }
3229
3230    /**
3231     * Returns the width of the vertical scrollbar.
3232     *
3233     * @return The width in pixels of the vertical scrollbar or 0 if there
3234     *         is no vertical scrollbar.
3235     */
3236    public int getVerticalScrollbarWidth() {
3237        ScrollabilityCache cache = mScrollCache;
3238        if (cache != null) {
3239            ScrollBarDrawable scrollBar = cache.scrollBar;
3240            if (scrollBar != null) {
3241                int size = scrollBar.getSize(true);
3242                if (size <= 0) {
3243                    size = cache.scrollBarSize;
3244                }
3245                return size;
3246            }
3247            return 0;
3248        }
3249        return 0;
3250    }
3251
3252    /**
3253     * Returns the height of the horizontal scrollbar.
3254     *
3255     * @return The height in pixels of the horizontal scrollbar or 0 if
3256     *         there is no horizontal scrollbar.
3257     */
3258    protected int getHorizontalScrollbarHeight() {
3259        ScrollabilityCache cache = mScrollCache;
3260        if (cache != null) {
3261            ScrollBarDrawable scrollBar = cache.scrollBar;
3262            if (scrollBar != null) {
3263                int size = scrollBar.getSize(false);
3264                if (size <= 0) {
3265                    size = cache.scrollBarSize;
3266                }
3267                return size;
3268            }
3269            return 0;
3270        }
3271        return 0;
3272    }
3273
3274    /**
3275     * <p>
3276     * Initializes the scrollbars from a given set of styled attributes. This
3277     * method should be called by subclasses that need scrollbars and when an
3278     * instance of these subclasses is created programmatically rather than
3279     * being inflated from XML. This method is automatically called when the XML
3280     * is inflated.
3281     * </p>
3282     *
3283     * @param a the styled attributes set to initialize the scrollbars from
3284     */
3285    protected void initializeScrollbars(TypedArray a) {
3286        initScrollCache();
3287
3288        final ScrollabilityCache scrollabilityCache = mScrollCache;
3289
3290        if (scrollabilityCache.scrollBar == null) {
3291            scrollabilityCache.scrollBar = new ScrollBarDrawable();
3292        }
3293
3294        final boolean fadeScrollbars = a.getBoolean(R.styleable.View_fadeScrollbars, true);
3295
3296        if (!fadeScrollbars) {
3297            scrollabilityCache.state = ScrollabilityCache.ON;
3298        }
3299        scrollabilityCache.fadeScrollBars = fadeScrollbars;
3300
3301
3302        scrollabilityCache.scrollBarFadeDuration = a.getInt(
3303                R.styleable.View_scrollbarFadeDuration, ViewConfiguration
3304                        .getScrollBarFadeDuration());
3305        scrollabilityCache.scrollBarDefaultDelayBeforeFade = a.getInt(
3306                R.styleable.View_scrollbarDefaultDelayBeforeFade,
3307                ViewConfiguration.getScrollDefaultDelay());
3308
3309
3310        scrollabilityCache.scrollBarSize = a.getDimensionPixelSize(
3311                com.android.internal.R.styleable.View_scrollbarSize,
3312                ViewConfiguration.get(mContext).getScaledScrollBarSize());
3313
3314        Drawable track = a.getDrawable(R.styleable.View_scrollbarTrackHorizontal);
3315        scrollabilityCache.scrollBar.setHorizontalTrackDrawable(track);
3316
3317        Drawable thumb = a.getDrawable(R.styleable.View_scrollbarThumbHorizontal);
3318        if (thumb != null) {
3319            scrollabilityCache.scrollBar.setHorizontalThumbDrawable(thumb);
3320        }
3321
3322        boolean alwaysDraw = a.getBoolean(R.styleable.View_scrollbarAlwaysDrawHorizontalTrack,
3323                false);
3324        if (alwaysDraw) {
3325            scrollabilityCache.scrollBar.setAlwaysDrawHorizontalTrack(true);
3326        }
3327
3328        track = a.getDrawable(R.styleable.View_scrollbarTrackVertical);
3329        scrollabilityCache.scrollBar.setVerticalTrackDrawable(track);
3330
3331        thumb = a.getDrawable(R.styleable.View_scrollbarThumbVertical);
3332        if (thumb != null) {
3333            scrollabilityCache.scrollBar.setVerticalThumbDrawable(thumb);
3334        }
3335
3336        alwaysDraw = a.getBoolean(R.styleable.View_scrollbarAlwaysDrawVerticalTrack,
3337                false);
3338        if (alwaysDraw) {
3339            scrollabilityCache.scrollBar.setAlwaysDrawVerticalTrack(true);
3340        }
3341
3342        // Re-apply user/background padding so that scrollbar(s) get added
3343        resolvePadding();
3344    }
3345
3346    /**
3347     * <p>
3348     * Initalizes the scrollability cache if necessary.
3349     * </p>
3350     */
3351    private void initScrollCache() {
3352        if (mScrollCache == null) {
3353            mScrollCache = new ScrollabilityCache(ViewConfiguration.get(mContext), this);
3354        }
3355    }
3356
3357    /**
3358     * Set the position of the vertical scroll bar. Should be one of
3359     * {@link #SCROLLBAR_POSITION_DEFAULT}, {@link #SCROLLBAR_POSITION_LEFT} or
3360     * {@link #SCROLLBAR_POSITION_RIGHT}.
3361     *
3362     * @param position Where the vertical scroll bar should be positioned.
3363     */
3364    public void setVerticalScrollbarPosition(int position) {
3365        if (mVerticalScrollbarPosition != position) {
3366            mVerticalScrollbarPosition = position;
3367            computeOpaqueFlags();
3368            resolvePadding();
3369        }
3370    }
3371
3372    /**
3373     * @return The position where the vertical scroll bar will show, if applicable.
3374     * @see #setVerticalScrollbarPosition(int)
3375     */
3376    public int getVerticalScrollbarPosition() {
3377        return mVerticalScrollbarPosition;
3378    }
3379
3380    ListenerInfo getListenerInfo() {
3381        if (mListenerInfo != null) {
3382            return mListenerInfo;
3383        }
3384        mListenerInfo = new ListenerInfo();
3385        return mListenerInfo;
3386    }
3387
3388    /**
3389     * Register a callback to be invoked when focus of this view changed.
3390     *
3391     * @param l The callback that will run.
3392     */
3393    public void setOnFocusChangeListener(OnFocusChangeListener l) {
3394        getListenerInfo().mOnFocusChangeListener = l;
3395    }
3396
3397    /**
3398     * Add a listener that will be called when the bounds of the view change due to
3399     * layout processing.
3400     *
3401     * @param listener The listener that will be called when layout bounds change.
3402     */
3403    public void addOnLayoutChangeListener(OnLayoutChangeListener listener) {
3404        ListenerInfo li = getListenerInfo();
3405        if (li.mOnLayoutChangeListeners == null) {
3406            li.mOnLayoutChangeListeners = new ArrayList<OnLayoutChangeListener>();
3407        }
3408        if (!li.mOnLayoutChangeListeners.contains(listener)) {
3409            li.mOnLayoutChangeListeners.add(listener);
3410        }
3411    }
3412
3413    /**
3414     * Remove a listener for layout changes.
3415     *
3416     * @param listener The listener for layout bounds change.
3417     */
3418    public void removeOnLayoutChangeListener(OnLayoutChangeListener listener) {
3419        ListenerInfo li = mListenerInfo;
3420        if (li == null || li.mOnLayoutChangeListeners == null) {
3421            return;
3422        }
3423        li.mOnLayoutChangeListeners.remove(listener);
3424    }
3425
3426    /**
3427     * Add a listener for attach state changes.
3428     *
3429     * This listener will be called whenever this view is attached or detached
3430     * from a window. Remove the listener using
3431     * {@link #removeOnAttachStateChangeListener(OnAttachStateChangeListener)}.
3432     *
3433     * @param listener Listener to attach
3434     * @see #removeOnAttachStateChangeListener(OnAttachStateChangeListener)
3435     */
3436    public void addOnAttachStateChangeListener(OnAttachStateChangeListener listener) {
3437        ListenerInfo li = getListenerInfo();
3438        if (li.mOnAttachStateChangeListeners == null) {
3439            li.mOnAttachStateChangeListeners
3440                    = new CopyOnWriteArrayList<OnAttachStateChangeListener>();
3441        }
3442        li.mOnAttachStateChangeListeners.add(listener);
3443    }
3444
3445    /**
3446     * Remove a listener for attach state changes. The listener will receive no further
3447     * notification of window attach/detach events.
3448     *
3449     * @param listener Listener to remove
3450     * @see #addOnAttachStateChangeListener(OnAttachStateChangeListener)
3451     */
3452    public void removeOnAttachStateChangeListener(OnAttachStateChangeListener listener) {
3453        ListenerInfo li = mListenerInfo;
3454        if (li == null || li.mOnAttachStateChangeListeners == null) {
3455            return;
3456        }
3457        li.mOnAttachStateChangeListeners.remove(listener);
3458    }
3459
3460    /**
3461     * Returns the focus-change callback registered for this view.
3462     *
3463     * @return The callback, or null if one is not registered.
3464     */
3465    public OnFocusChangeListener getOnFocusChangeListener() {
3466        ListenerInfo li = mListenerInfo;
3467        return li != null ? li.mOnFocusChangeListener : null;
3468    }
3469
3470    /**
3471     * Register a callback to be invoked when this view is clicked. If this view is not
3472     * clickable, it becomes clickable.
3473     *
3474     * @param l The callback that will run
3475     *
3476     * @see #setClickable(boolean)
3477     */
3478    public void setOnClickListener(OnClickListener l) {
3479        if (!isClickable()) {
3480            setClickable(true);
3481        }
3482        getListenerInfo().mOnClickListener = l;
3483    }
3484
3485    /**
3486     * Return whether this view has an attached OnClickListener.  Returns
3487     * true if there is a listener, false if there is none.
3488     */
3489    public boolean hasOnClickListeners() {
3490        ListenerInfo li = mListenerInfo;
3491        return (li != null && li.mOnClickListener != null);
3492    }
3493
3494    /**
3495     * Register a callback to be invoked when this view is clicked and held. If this view is not
3496     * long clickable, it becomes long clickable.
3497     *
3498     * @param l The callback that will run
3499     *
3500     * @see #setLongClickable(boolean)
3501     */
3502    public void setOnLongClickListener(OnLongClickListener l) {
3503        if (!isLongClickable()) {
3504            setLongClickable(true);
3505        }
3506        getListenerInfo().mOnLongClickListener = l;
3507    }
3508
3509    /**
3510     * Register a callback to be invoked when the context menu for this view is
3511     * being built. If this view is not long clickable, it becomes long clickable.
3512     *
3513     * @param l The callback that will run
3514     *
3515     */
3516    public void setOnCreateContextMenuListener(OnCreateContextMenuListener l) {
3517        if (!isLongClickable()) {
3518            setLongClickable(true);
3519        }
3520        getListenerInfo().mOnCreateContextMenuListener = l;
3521    }
3522
3523    /**
3524     * Call this view's OnClickListener, if it is defined.  Performs all normal
3525     * actions associated with clicking: reporting accessibility event, playing
3526     * a sound, etc.
3527     *
3528     * @return True there was an assigned OnClickListener that was called, false
3529     *         otherwise is returned.
3530     */
3531    public boolean performClick() {
3532        sendAccessibilityEvent(AccessibilityEvent.TYPE_VIEW_CLICKED);
3533
3534        ListenerInfo li = mListenerInfo;
3535        if (li != null && li.mOnClickListener != null) {
3536            playSoundEffect(SoundEffectConstants.CLICK);
3537            li.mOnClickListener.onClick(this);
3538            return true;
3539        }
3540
3541        return false;
3542    }
3543
3544    /**
3545     * Directly call any attached OnClickListener.  Unlike {@link #performClick()},
3546     * this only calls the listener, and does not do any associated clicking
3547     * actions like reporting an accessibility event.
3548     *
3549     * @return True there was an assigned OnClickListener that was called, false
3550     *         otherwise is returned.
3551     */
3552    public boolean callOnClick() {
3553        ListenerInfo li = mListenerInfo;
3554        if (li != null && li.mOnClickListener != null) {
3555            li.mOnClickListener.onClick(this);
3556            return true;
3557        }
3558        return false;
3559    }
3560
3561    /**
3562     * Call this view's OnLongClickListener, if it is defined. Invokes the context menu if the
3563     * OnLongClickListener did not consume the event.
3564     *
3565     * @return True if one of the above receivers consumed the event, false otherwise.
3566     */
3567    public boolean performLongClick() {
3568        sendAccessibilityEvent(AccessibilityEvent.TYPE_VIEW_LONG_CLICKED);
3569
3570        boolean handled = false;
3571        ListenerInfo li = mListenerInfo;
3572        if (li != null && li.mOnLongClickListener != null) {
3573            handled = li.mOnLongClickListener.onLongClick(View.this);
3574        }
3575        if (!handled) {
3576            handled = showContextMenu();
3577        }
3578        if (handled) {
3579            performHapticFeedback(HapticFeedbackConstants.LONG_PRESS);
3580        }
3581        return handled;
3582    }
3583
3584    /**
3585     * Performs button-related actions during a touch down event.
3586     *
3587     * @param event The event.
3588     * @return True if the down was consumed.
3589     *
3590     * @hide
3591     */
3592    protected boolean performButtonActionOnTouchDown(MotionEvent event) {
3593        if ((event.getButtonState() & MotionEvent.BUTTON_SECONDARY) != 0) {
3594            if (showContextMenu(event.getX(), event.getY(), event.getMetaState())) {
3595                return true;
3596            }
3597        }
3598        return false;
3599    }
3600
3601    /**
3602     * Bring up the context menu for this view.
3603     *
3604     * @return Whether a context menu was displayed.
3605     */
3606    public boolean showContextMenu() {
3607        return getParent().showContextMenuForChild(this);
3608    }
3609
3610    /**
3611     * Bring up the context menu for this view, referring to the item under the specified point.
3612     *
3613     * @param x The referenced x coordinate.
3614     * @param y The referenced y coordinate.
3615     * @param metaState The keyboard modifiers that were pressed.
3616     * @return Whether a context menu was displayed.
3617     *
3618     * @hide
3619     */
3620    public boolean showContextMenu(float x, float y, int metaState) {
3621        return showContextMenu();
3622    }
3623
3624    /**
3625     * Start an action mode.
3626     *
3627     * @param callback Callback that will control the lifecycle of the action mode
3628     * @return The new action mode if it is started, null otherwise
3629     *
3630     * @see ActionMode
3631     */
3632    public ActionMode startActionMode(ActionMode.Callback callback) {
3633        ViewParent parent = getParent();
3634        if (parent == null) return null;
3635        return parent.startActionModeForChild(this, callback);
3636    }
3637
3638    /**
3639     * Register a callback to be invoked when a key is pressed in this view.
3640     * @param l the key listener to attach to this view
3641     */
3642    public void setOnKeyListener(OnKeyListener l) {
3643        getListenerInfo().mOnKeyListener = l;
3644    }
3645
3646    /**
3647     * Register a callback to be invoked when a touch event is sent to this view.
3648     * @param l the touch listener to attach to this view
3649     */
3650    public void setOnTouchListener(OnTouchListener l) {
3651        getListenerInfo().mOnTouchListener = l;
3652    }
3653
3654    /**
3655     * Register a callback to be invoked when a generic motion event is sent to this view.
3656     * @param l the generic motion listener to attach to this view
3657     */
3658    public void setOnGenericMotionListener(OnGenericMotionListener l) {
3659        getListenerInfo().mOnGenericMotionListener = l;
3660    }
3661
3662    /**
3663     * Register a callback to be invoked when a hover event is sent to this view.
3664     * @param l the hover listener to attach to this view
3665     */
3666    public void setOnHoverListener(OnHoverListener l) {
3667        getListenerInfo().mOnHoverListener = l;
3668    }
3669
3670    /**
3671     * Register a drag event listener callback object for this View. The parameter is
3672     * an implementation of {@link android.view.View.OnDragListener}. To send a drag event to a
3673     * View, the system calls the
3674     * {@link android.view.View.OnDragListener#onDrag(View,DragEvent)} method.
3675     * @param l An implementation of {@link android.view.View.OnDragListener}.
3676     */
3677    public void setOnDragListener(OnDragListener l) {
3678        getListenerInfo().mOnDragListener = l;
3679    }
3680
3681    /**
3682     * Give this view focus. This will cause
3683     * {@link #onFocusChanged(boolean, int, android.graphics.Rect)} to be called.
3684     *
3685     * Note: this does not check whether this {@link View} should get focus, it just
3686     * gives it focus no matter what.  It should only be called internally by framework
3687     * code that knows what it is doing, namely {@link #requestFocus(int, Rect)}.
3688     *
3689     * @param direction values are {@link View#FOCUS_UP}, {@link View#FOCUS_DOWN},
3690     *        {@link View#FOCUS_LEFT} or {@link View#FOCUS_RIGHT}. This is the direction which
3691     *        focus moved when requestFocus() is called. It may not always
3692     *        apply, in which case use the default View.FOCUS_DOWN.
3693     * @param previouslyFocusedRect The rectangle of the view that had focus
3694     *        prior in this View's coordinate system.
3695     */
3696    void handleFocusGainInternal(int direction, Rect previouslyFocusedRect) {
3697        if (DBG) {
3698            System.out.println(this + " requestFocus()");
3699        }
3700
3701        if ((mPrivateFlags & FOCUSED) == 0) {
3702            mPrivateFlags |= FOCUSED;
3703
3704            if (mParent != null) {
3705                mParent.requestChildFocus(this, this);
3706            }
3707
3708            onFocusChanged(true, direction, previouslyFocusedRect);
3709            refreshDrawableState();
3710        }
3711    }
3712
3713    /**
3714     * Request that a rectangle of this view be visible on the screen,
3715     * scrolling if necessary just enough.
3716     *
3717     * <p>A View should call this if it maintains some notion of which part
3718     * of its content is interesting.  For example, a text editing view
3719     * should call this when its cursor moves.
3720     *
3721     * @param rectangle The rectangle.
3722     * @return Whether any parent scrolled.
3723     */
3724    public boolean requestRectangleOnScreen(Rect rectangle) {
3725        return requestRectangleOnScreen(rectangle, false);
3726    }
3727
3728    /**
3729     * Request that a rectangle of this view be visible on the screen,
3730     * scrolling if necessary just enough.
3731     *
3732     * <p>A View should call this if it maintains some notion of which part
3733     * of its content is interesting.  For example, a text editing view
3734     * should call this when its cursor moves.
3735     *
3736     * <p>When <code>immediate</code> is set to true, scrolling will not be
3737     * animated.
3738     *
3739     * @param rectangle The rectangle.
3740     * @param immediate True to forbid animated scrolling, false otherwise
3741     * @return Whether any parent scrolled.
3742     */
3743    public boolean requestRectangleOnScreen(Rect rectangle, boolean immediate) {
3744        View child = this;
3745        ViewParent parent = mParent;
3746        boolean scrolled = false;
3747        while (parent != null) {
3748            scrolled |= parent.requestChildRectangleOnScreen(child,
3749                    rectangle, immediate);
3750
3751            // offset rect so next call has the rectangle in the
3752            // coordinate system of its direct child.
3753            rectangle.offset(child.getLeft(), child.getTop());
3754            rectangle.offset(-child.getScrollX(), -child.getScrollY());
3755
3756            if (!(parent instanceof View)) {
3757                break;
3758            }
3759
3760            child = (View) parent;
3761            parent = child.getParent();
3762        }
3763        return scrolled;
3764    }
3765
3766    /**
3767     * Called when this view wants to give up focus. If focus is cleared
3768     * {@link #onFocusChanged(boolean, int, android.graphics.Rect)} is called.
3769     * <p>
3770     * <strong>Note:</strong> When a View clears focus the framework is trying
3771     * to give focus to the first focusable View from the top. Hence, if this
3772     * View is the first from the top that can take focus, then its focus will
3773     * not be cleared nor will the focus change callback be invoked.
3774     * </p>
3775     */
3776    public void clearFocus() {
3777        if (DBG) {
3778            System.out.println(this + " clearFocus()");
3779        }
3780
3781        if ((mPrivateFlags & FOCUSED) != 0) {
3782            mPrivateFlags &= ~FOCUSED;
3783
3784            if (mParent != null) {
3785                mParent.clearChildFocus(this);
3786            }
3787
3788            onFocusChanged(false, 0, null);
3789            refreshDrawableState();
3790        }
3791    }
3792
3793    /**
3794     * Called to clear the focus of a view that is about to be removed.
3795     * Doesn't call clearChildFocus, which prevents this view from taking
3796     * focus again before it has been removed from the parent
3797     */
3798    void clearFocusForRemoval() {
3799        if ((mPrivateFlags & FOCUSED) != 0) {
3800            mPrivateFlags &= ~FOCUSED;
3801
3802            onFocusChanged(false, 0, null);
3803            refreshDrawableState();
3804
3805            // The view cleared focus and invoked the callbacks, so  now is the
3806            // time to give focus to the the first focusable from the top to
3807            // ensure that the gain focus is announced after clear focus.
3808            getRootView().requestFocus(FOCUS_FORWARD);
3809        }
3810    }
3811
3812    /**
3813     * Called internally by the view system when a new view is getting focus.
3814     * This is what clears the old focus.
3815     */
3816    void unFocus() {
3817        if (DBG) {
3818            System.out.println(this + " unFocus()");
3819        }
3820
3821        if ((mPrivateFlags & FOCUSED) != 0) {
3822            mPrivateFlags &= ~FOCUSED;
3823
3824            onFocusChanged(false, 0, null);
3825            refreshDrawableState();
3826        }
3827    }
3828
3829    /**
3830     * Returns true if this view has focus iteself, or is the ancestor of the
3831     * view that has focus.
3832     *
3833     * @return True if this view has or contains focus, false otherwise.
3834     */
3835    @ViewDebug.ExportedProperty(category = "focus")
3836    public boolean hasFocus() {
3837        return (mPrivateFlags & FOCUSED) != 0;
3838    }
3839
3840    /**
3841     * Returns true if this view is focusable or if it contains a reachable View
3842     * for which {@link #hasFocusable()} returns true. A "reachable hasFocusable()"
3843     * is a View whose parents do not block descendants focus.
3844     *
3845     * Only {@link #VISIBLE} views are considered focusable.
3846     *
3847     * @return True if the view is focusable or if the view contains a focusable
3848     *         View, false otherwise.
3849     *
3850     * @see ViewGroup#FOCUS_BLOCK_DESCENDANTS
3851     */
3852    public boolean hasFocusable() {
3853        return (mViewFlags & VISIBILITY_MASK) == VISIBLE && isFocusable();
3854    }
3855
3856    /**
3857     * Called by the view system when the focus state of this view changes.
3858     * When the focus change event is caused by directional navigation, direction
3859     * and previouslyFocusedRect provide insight into where the focus is coming from.
3860     * When overriding, be sure to call up through to the super class so that
3861     * the standard focus handling will occur.
3862     *
3863     * @param gainFocus True if the View has focus; false otherwise.
3864     * @param direction The direction focus has moved when requestFocus()
3865     *                  is called to give this view focus. Values are
3866     *                  {@link #FOCUS_UP}, {@link #FOCUS_DOWN}, {@link #FOCUS_LEFT},
3867     *                  {@link #FOCUS_RIGHT}, {@link #FOCUS_FORWARD}, or {@link #FOCUS_BACKWARD}.
3868     *                  It may not always apply, in which case use the default.
3869     * @param previouslyFocusedRect The rectangle, in this view's coordinate
3870     *        system, of the previously focused view.  If applicable, this will be
3871     *        passed in as finer grained information about where the focus is coming
3872     *        from (in addition to direction).  Will be <code>null</code> otherwise.
3873     */
3874    protected void onFocusChanged(boolean gainFocus, int direction, Rect previouslyFocusedRect) {
3875        if (gainFocus) {
3876            sendAccessibilityEvent(AccessibilityEvent.TYPE_VIEW_FOCUSED);
3877        }
3878
3879        InputMethodManager imm = InputMethodManager.peekInstance();
3880        if (!gainFocus) {
3881            if (isPressed()) {
3882                setPressed(false);
3883            }
3884            if (imm != null && mAttachInfo != null
3885                    && mAttachInfo.mHasWindowFocus) {
3886                imm.focusOut(this);
3887            }
3888            onFocusLost();
3889        } else if (imm != null && mAttachInfo != null
3890                && mAttachInfo.mHasWindowFocus) {
3891            imm.focusIn(this);
3892        }
3893
3894        invalidate(true);
3895        ListenerInfo li = mListenerInfo;
3896        if (li != null && li.mOnFocusChangeListener != null) {
3897            li.mOnFocusChangeListener.onFocusChange(this, gainFocus);
3898        }
3899
3900        if (mAttachInfo != null) {
3901            mAttachInfo.mKeyDispatchState.reset(this);
3902        }
3903    }
3904
3905    /**
3906     * Sends an accessibility event of the given type. If accessiiblity is
3907     * not enabled this method has no effect. The default implementation calls
3908     * {@link #onInitializeAccessibilityEvent(AccessibilityEvent)} first
3909     * to populate information about the event source (this View), then calls
3910     * {@link #dispatchPopulateAccessibilityEvent(AccessibilityEvent)} to
3911     * populate the text content of the event source including its descendants,
3912     * and last calls
3913     * {@link ViewParent#requestSendAccessibilityEvent(View, AccessibilityEvent)}
3914     * on its parent to resuest sending of the event to interested parties.
3915     * <p>
3916     * If an {@link AccessibilityDelegate} has been specified via calling
3917     * {@link #setAccessibilityDelegate(AccessibilityDelegate)} its
3918     * {@link AccessibilityDelegate#sendAccessibilityEvent(View, int)} is
3919     * responsible for handling this call.
3920     * </p>
3921     *
3922     * @param eventType The type of the event to send, as defined by several types from
3923     * {@link android.view.accessibility.AccessibilityEvent}, such as
3924     * {@link android.view.accessibility.AccessibilityEvent#TYPE_VIEW_CLICKED} or
3925     * {@link android.view.accessibility.AccessibilityEvent#TYPE_VIEW_HOVER_ENTER}.
3926     *
3927     * @see #onInitializeAccessibilityEvent(AccessibilityEvent)
3928     * @see #dispatchPopulateAccessibilityEvent(AccessibilityEvent)
3929     * @see ViewParent#requestSendAccessibilityEvent(View, AccessibilityEvent)
3930     * @see AccessibilityDelegate
3931     */
3932    public void sendAccessibilityEvent(int eventType) {
3933        if (mAccessibilityDelegate != null) {
3934            mAccessibilityDelegate.sendAccessibilityEvent(this, eventType);
3935        } else {
3936            sendAccessibilityEventInternal(eventType);
3937        }
3938    }
3939
3940    /**
3941     * @see #sendAccessibilityEvent(int)
3942     *
3943     * Note: Called from the default {@link AccessibilityDelegate}.
3944     */
3945    void sendAccessibilityEventInternal(int eventType) {
3946        if (AccessibilityManager.getInstance(mContext).isEnabled()) {
3947            sendAccessibilityEventUnchecked(AccessibilityEvent.obtain(eventType));
3948        }
3949    }
3950
3951    /**
3952     * This method behaves exactly as {@link #sendAccessibilityEvent(int)} but
3953     * takes as an argument an empty {@link AccessibilityEvent} and does not
3954     * perform a check whether accessibility is enabled.
3955     * <p>
3956     * If an {@link AccessibilityDelegate} has been specified via calling
3957     * {@link #setAccessibilityDelegate(AccessibilityDelegate)} its
3958     * {@link AccessibilityDelegate#sendAccessibilityEventUnchecked(View, AccessibilityEvent)}
3959     * is responsible for handling this call.
3960     * </p>
3961     *
3962     * @param event The event to send.
3963     *
3964     * @see #sendAccessibilityEvent(int)
3965     */
3966    public void sendAccessibilityEventUnchecked(AccessibilityEvent event) {
3967        if (mAccessibilityDelegate != null) {
3968           mAccessibilityDelegate.sendAccessibilityEventUnchecked(this, event);
3969        } else {
3970            sendAccessibilityEventUncheckedInternal(event);
3971        }
3972    }
3973
3974    /**
3975     * @see #sendAccessibilityEventUnchecked(AccessibilityEvent)
3976     *
3977     * Note: Called from the default {@link AccessibilityDelegate}.
3978     */
3979    void sendAccessibilityEventUncheckedInternal(AccessibilityEvent event) {
3980        if (!isShown()) {
3981            return;
3982        }
3983        onInitializeAccessibilityEvent(event);
3984        // Only a subset of accessibility events populates text content.
3985        if ((event.getEventType() & POPULATING_ACCESSIBILITY_EVENT_TYPES) != 0) {
3986            dispatchPopulateAccessibilityEvent(event);
3987        }
3988        // In the beginning we called #isShown(), so we know that getParent() is not null.
3989        getParent().requestSendAccessibilityEvent(this, event);
3990    }
3991
3992    /**
3993     * Dispatches an {@link AccessibilityEvent} to the {@link View} first and then
3994     * to its children for adding their text content to the event. Note that the
3995     * event text is populated in a separate dispatch path since we add to the
3996     * event not only the text of the source but also the text of all its descendants.
3997     * A typical implementation will call
3998     * {@link #onPopulateAccessibilityEvent(AccessibilityEvent)} on the this view
3999     * and then call the {@link #dispatchPopulateAccessibilityEvent(AccessibilityEvent)}
4000     * on each child. Override this method if custom population of the event text
4001     * content is required.
4002     * <p>
4003     * If an {@link AccessibilityDelegate} has been specified via calling
4004     * {@link #setAccessibilityDelegate(AccessibilityDelegate)} its
4005     * {@link AccessibilityDelegate#dispatchPopulateAccessibilityEvent(View, AccessibilityEvent)}
4006     * is responsible for handling this call.
4007     * </p>
4008     * <p>
4009     * <em>Note:</em> Accessibility events of certain types are not dispatched for
4010     * populating the event text via this method. For details refer to {@link AccessibilityEvent}.
4011     * </p>
4012     *
4013     * @param event The event.
4014     *
4015     * @return True if the event population was completed.
4016     */
4017    public boolean dispatchPopulateAccessibilityEvent(AccessibilityEvent event) {
4018        if (mAccessibilityDelegate != null) {
4019            return mAccessibilityDelegate.dispatchPopulateAccessibilityEvent(this, event);
4020        } else {
4021            return dispatchPopulateAccessibilityEventInternal(event);
4022        }
4023    }
4024
4025    /**
4026     * @see #dispatchPopulateAccessibilityEvent(AccessibilityEvent)
4027     *
4028     * Note: Called from the default {@link AccessibilityDelegate}.
4029     */
4030    boolean dispatchPopulateAccessibilityEventInternal(AccessibilityEvent event) {
4031        onPopulateAccessibilityEvent(event);
4032        return false;
4033    }
4034
4035    /**
4036     * Called from {@link #dispatchPopulateAccessibilityEvent(AccessibilityEvent)}
4037     * giving a chance to this View to populate the accessibility event with its
4038     * text content. While this method is free to modify event
4039     * attributes other than text content, doing so should normally be performed in
4040     * {@link #onInitializeAccessibilityEvent(AccessibilityEvent)}.
4041     * <p>
4042     * Example: Adding formatted date string to an accessibility event in addition
4043     *          to the text added by the super implementation:
4044     * <pre> public void onPopulateAccessibilityEvent(AccessibilityEvent event) {
4045     *     super.onPopulateAccessibilityEvent(event);
4046     *     final int flags = DateUtils.FORMAT_SHOW_DATE | DateUtils.FORMAT_SHOW_WEEKDAY;
4047     *     String selectedDateUtterance = DateUtils.formatDateTime(mContext,
4048     *         mCurrentDate.getTimeInMillis(), flags);
4049     *     event.getText().add(selectedDateUtterance);
4050     * }</pre>
4051     * <p>
4052     * If an {@link AccessibilityDelegate} has been specified via calling
4053     * {@link #setAccessibilityDelegate(AccessibilityDelegate)} its
4054     * {@link AccessibilityDelegate#onPopulateAccessibilityEvent(View, AccessibilityEvent)}
4055     * is responsible for handling this call.
4056     * </p>
4057     * <p class="note"><strong>Note:</strong> Always call the super implementation before adding
4058     * information to the event, in case the default implementation has basic information to add.
4059     * </p>
4060     *
4061     * @param event The accessibility event which to populate.
4062     *
4063     * @see #sendAccessibilityEvent(int)
4064     * @see #dispatchPopulateAccessibilityEvent(AccessibilityEvent)
4065     */
4066    public void onPopulateAccessibilityEvent(AccessibilityEvent event) {
4067        if (mAccessibilityDelegate != null) {
4068            mAccessibilityDelegate.onPopulateAccessibilityEvent(this, event);
4069        } else {
4070            onPopulateAccessibilityEventInternal(event);
4071        }
4072    }
4073
4074    /**
4075     * @see #onPopulateAccessibilityEvent(AccessibilityEvent)
4076     *
4077     * Note: Called from the default {@link AccessibilityDelegate}.
4078     */
4079    void onPopulateAccessibilityEventInternal(AccessibilityEvent event) {
4080
4081    }
4082
4083    /**
4084     * Initializes an {@link AccessibilityEvent} with information about
4085     * this View which is the event source. In other words, the source of
4086     * an accessibility event is the view whose state change triggered firing
4087     * the event.
4088     * <p>
4089     * Example: Setting the password property of an event in addition
4090     *          to properties set by the super implementation:
4091     * <pre> public void onInitializeAccessibilityEvent(AccessibilityEvent event) {
4092     *     super.onInitializeAccessibilityEvent(event);
4093     *     event.setPassword(true);
4094     * }</pre>
4095     * <p>
4096     * If an {@link AccessibilityDelegate} has been specified via calling
4097     * {@link #setAccessibilityDelegate(AccessibilityDelegate)} its
4098     * {@link AccessibilityDelegate#onInitializeAccessibilityEvent(View, AccessibilityEvent)}
4099     * is responsible for handling this call.
4100     * </p>
4101     * <p class="note"><strong>Note:</strong> Always call the super implementation before adding
4102     * information to the event, in case the default implementation has basic information to add.
4103     * </p>
4104     * @param event The event to initialize.
4105     *
4106     * @see #sendAccessibilityEvent(int)
4107     * @see #dispatchPopulateAccessibilityEvent(AccessibilityEvent)
4108     */
4109    public void onInitializeAccessibilityEvent(AccessibilityEvent event) {
4110        if (mAccessibilityDelegate != null) {
4111            mAccessibilityDelegate.onInitializeAccessibilityEvent(this, event);
4112        } else {
4113            onInitializeAccessibilityEventInternal(event);
4114        }
4115    }
4116
4117    /**
4118     * @see #onInitializeAccessibilityEvent(AccessibilityEvent)
4119     *
4120     * Note: Called from the default {@link AccessibilityDelegate}.
4121     */
4122    void onInitializeAccessibilityEventInternal(AccessibilityEvent event) {
4123        event.setSource(this);
4124        event.setClassName(View.class.getName());
4125        event.setPackageName(getContext().getPackageName());
4126        event.setEnabled(isEnabled());
4127        event.setContentDescription(mContentDescription);
4128
4129        if (event.getEventType() == AccessibilityEvent.TYPE_VIEW_FOCUSED && mAttachInfo != null) {
4130            ArrayList<View> focusablesTempList = mAttachInfo.mFocusablesTempList;
4131            getRootView().addFocusables(focusablesTempList, View.FOCUS_FORWARD,
4132                    FOCUSABLES_ALL);
4133            event.setItemCount(focusablesTempList.size());
4134            event.setCurrentItemIndex(focusablesTempList.indexOf(this));
4135            focusablesTempList.clear();
4136        }
4137    }
4138
4139    /**
4140     * Returns an {@link AccessibilityNodeInfo} representing this view from the
4141     * point of view of an {@link android.accessibilityservice.AccessibilityService}.
4142     * This method is responsible for obtaining an accessibility node info from a
4143     * pool of reusable instances and calling
4144     * {@link #onInitializeAccessibilityNodeInfo(AccessibilityNodeInfo)} on this view to
4145     * initialize the former.
4146     * <p>
4147     * Note: The client is responsible for recycling the obtained instance by calling
4148     *       {@link AccessibilityNodeInfo#recycle()} to minimize object creation.
4149     * </p>
4150     *
4151     * @return A populated {@link AccessibilityNodeInfo}.
4152     *
4153     * @see AccessibilityNodeInfo
4154     */
4155    public AccessibilityNodeInfo createAccessibilityNodeInfo() {
4156        AccessibilityNodeProvider provider = getAccessibilityNodeProvider();
4157        if (provider != null) {
4158            return provider.createAccessibilityNodeInfo(View.NO_ID);
4159        } else {
4160            AccessibilityNodeInfo info = AccessibilityNodeInfo.obtain(this);
4161            onInitializeAccessibilityNodeInfo(info);
4162            return info;
4163        }
4164    }
4165
4166    /**
4167     * Initializes an {@link AccessibilityNodeInfo} with information about this view.
4168     * The base implementation sets:
4169     * <ul>
4170     *   <li>{@link AccessibilityNodeInfo#setParent(View)},</li>
4171     *   <li>{@link AccessibilityNodeInfo#setBoundsInParent(Rect)},</li>
4172     *   <li>{@link AccessibilityNodeInfo#setBoundsInScreen(Rect)},</li>
4173     *   <li>{@link AccessibilityNodeInfo#setPackageName(CharSequence)},</li>
4174     *   <li>{@link AccessibilityNodeInfo#setClassName(CharSequence)},</li>
4175     *   <li>{@link AccessibilityNodeInfo#setContentDescription(CharSequence)},</li>
4176     *   <li>{@link AccessibilityNodeInfo#setEnabled(boolean)},</li>
4177     *   <li>{@link AccessibilityNodeInfo#setClickable(boolean)},</li>
4178     *   <li>{@link AccessibilityNodeInfo#setFocusable(boolean)},</li>
4179     *   <li>{@link AccessibilityNodeInfo#setFocused(boolean)},</li>
4180     *   <li>{@link AccessibilityNodeInfo#setLongClickable(boolean)},</li>
4181     *   <li>{@link AccessibilityNodeInfo#setSelected(boolean)},</li>
4182     * </ul>
4183     * <p>
4184     * Subclasses should override this method, call the super implementation,
4185     * and set additional attributes.
4186     * </p>
4187     * <p>
4188     * If an {@link AccessibilityDelegate} has been specified via calling
4189     * {@link #setAccessibilityDelegate(AccessibilityDelegate)} its
4190     * {@link AccessibilityDelegate#onInitializeAccessibilityNodeInfo(View, AccessibilityNodeInfo)}
4191     * is responsible for handling this call.
4192     * </p>
4193     *
4194     * @param info The instance to initialize.
4195     */
4196    public void onInitializeAccessibilityNodeInfo(AccessibilityNodeInfo info) {
4197        if (mAccessibilityDelegate != null) {
4198            mAccessibilityDelegate.onInitializeAccessibilityNodeInfo(this, info);
4199        } else {
4200            onInitializeAccessibilityNodeInfoInternal(info);
4201        }
4202    }
4203
4204    /**
4205     * @see #onInitializeAccessibilityNodeInfo(AccessibilityNodeInfo)
4206     *
4207     * Note: Called from the default {@link AccessibilityDelegate}.
4208     */
4209    void onInitializeAccessibilityNodeInfoInternal(AccessibilityNodeInfo info) {
4210        Rect bounds = mAttachInfo.mTmpInvalRect;
4211        getDrawingRect(bounds);
4212        info.setBoundsInParent(bounds);
4213
4214        int[] locationOnScreen = mAttachInfo.mInvalidateChildLocation;
4215        getLocationOnScreen(locationOnScreen);
4216        bounds.offsetTo(0, 0);
4217        bounds.offset(locationOnScreen[0], locationOnScreen[1]);
4218        info.setBoundsInScreen(bounds);
4219
4220        if ((mPrivateFlags & IS_ROOT_NAMESPACE) == 0) {
4221            ViewParent parent = getParent();
4222            if (parent instanceof View) {
4223                View parentView = (View) parent;
4224                info.setParent(parentView);
4225            }
4226        }
4227
4228        info.setPackageName(mContext.getPackageName());
4229        info.setClassName(View.class.getName());
4230        info.setContentDescription(getContentDescription());
4231
4232        info.setEnabled(isEnabled());
4233        info.setClickable(isClickable());
4234        info.setFocusable(isFocusable());
4235        info.setFocused(isFocused());
4236        info.setSelected(isSelected());
4237        info.setLongClickable(isLongClickable());
4238
4239        // TODO: These make sense only if we are in an AdapterView but all
4240        // views can be selected. Maybe from accessiiblity perspective
4241        // we should report as selectable view in an AdapterView.
4242        info.addAction(AccessibilityNodeInfo.ACTION_SELECT);
4243        info.addAction(AccessibilityNodeInfo.ACTION_CLEAR_SELECTION);
4244
4245        if (isFocusable()) {
4246            if (isFocused()) {
4247                info.addAction(AccessibilityNodeInfo.ACTION_CLEAR_FOCUS);
4248            } else {
4249                info.addAction(AccessibilityNodeInfo.ACTION_FOCUS);
4250            }
4251        }
4252    }
4253
4254    /**
4255     * Sets a delegate for implementing accessibility support via compositon as
4256     * opposed to inheritance. The delegate's primary use is for implementing
4257     * backwards compatible widgets. For more details see {@link AccessibilityDelegate}.
4258     *
4259     * @param delegate The delegate instance.
4260     *
4261     * @see AccessibilityDelegate
4262     */
4263    public void setAccessibilityDelegate(AccessibilityDelegate delegate) {
4264        mAccessibilityDelegate = delegate;
4265    }
4266
4267    /**
4268     * Gets the provider for managing a virtual view hierarchy rooted at this View
4269     * and reported to {@link android.accessibilityservice.AccessibilityService}s
4270     * that explore the window content.
4271     * <p>
4272     * If this method returns an instance, this instance is responsible for managing
4273     * {@link AccessibilityNodeInfo}s describing the virtual sub-tree rooted at this
4274     * View including the one representing the View itself. Similarly the returned
4275     * instance is responsible for performing accessibility actions on any virtual
4276     * view or the root view itself.
4277     * </p>
4278     * <p>
4279     * If an {@link AccessibilityDelegate} has been specified via calling
4280     * {@link #setAccessibilityDelegate(AccessibilityDelegate)} its
4281     * {@link AccessibilityDelegate#getAccessibilityNodeProvider(View)}
4282     * is responsible for handling this call.
4283     * </p>
4284     *
4285     * @return The provider.
4286     *
4287     * @see AccessibilityNodeProvider
4288     */
4289    public AccessibilityNodeProvider getAccessibilityNodeProvider() {
4290        if (mAccessibilityDelegate != null) {
4291            return mAccessibilityDelegate.getAccessibilityNodeProvider(this);
4292        } else {
4293            return null;
4294        }
4295    }
4296
4297    /**
4298     * Gets the unique identifier of this view on the screen for accessibility purposes.
4299     * If this {@link View} is not attached to any window, {@value #NO_ID} is returned.
4300     *
4301     * @return The view accessibility id.
4302     *
4303     * @hide
4304     */
4305    public int getAccessibilityViewId() {
4306        if (mAccessibilityViewId == NO_ID) {
4307            mAccessibilityViewId = sNextAccessibilityViewId++;
4308        }
4309        return mAccessibilityViewId;
4310    }
4311
4312    /**
4313     * Gets the unique identifier of the window in which this View reseides.
4314     *
4315     * @return The window accessibility id.
4316     *
4317     * @hide
4318     */
4319    public int getAccessibilityWindowId() {
4320        return mAttachInfo != null ? mAttachInfo.mAccessibilityWindowId : NO_ID;
4321    }
4322
4323    /**
4324     * Gets the {@link View} description. It briefly describes the view and is
4325     * primarily used for accessibility support. Set this property to enable
4326     * better accessibility support for your application. This is especially
4327     * true for views that do not have textual representation (For example,
4328     * ImageButton).
4329     *
4330     * @return The content descriptiopn.
4331     *
4332     * @attr ref android.R.styleable#View_contentDescription
4333     */
4334    public CharSequence getContentDescription() {
4335        return mContentDescription;
4336    }
4337
4338    /**
4339     * Sets the {@link View} description. It briefly describes the view and is
4340     * primarily used for accessibility support. Set this property to enable
4341     * better accessibility support for your application. This is especially
4342     * true for views that do not have textual representation (For example,
4343     * ImageButton).
4344     *
4345     * @param contentDescription The content description.
4346     *
4347     * @attr ref android.R.styleable#View_contentDescription
4348     */
4349    @RemotableViewMethod
4350    public void setContentDescription(CharSequence contentDescription) {
4351        mContentDescription = contentDescription;
4352    }
4353
4354    /**
4355     * Invoked whenever this view loses focus, either by losing window focus or by losing
4356     * focus within its window. This method can be used to clear any state tied to the
4357     * focus. For instance, if a button is held pressed with the trackball and the window
4358     * loses focus, this method can be used to cancel the press.
4359     *
4360     * Subclasses of View overriding this method should always call super.onFocusLost().
4361     *
4362     * @see #onFocusChanged(boolean, int, android.graphics.Rect)
4363     * @see #onWindowFocusChanged(boolean)
4364     *
4365     * @hide pending API council approval
4366     */
4367    protected void onFocusLost() {
4368        resetPressedState();
4369    }
4370
4371    private void resetPressedState() {
4372        if ((mViewFlags & ENABLED_MASK) == DISABLED) {
4373            return;
4374        }
4375
4376        if (isPressed()) {
4377            setPressed(false);
4378
4379            if (!mHasPerformedLongPress) {
4380                removeLongPressCallback();
4381            }
4382        }
4383    }
4384
4385    /**
4386     * Returns true if this view has focus
4387     *
4388     * @return True if this view has focus, false otherwise.
4389     */
4390    @ViewDebug.ExportedProperty(category = "focus")
4391    public boolean isFocused() {
4392        return (mPrivateFlags & FOCUSED) != 0;
4393    }
4394
4395    /**
4396     * Find the view in the hierarchy rooted at this view that currently has
4397     * focus.
4398     *
4399     * @return The view that currently has focus, or null if no focused view can
4400     *         be found.
4401     */
4402    public View findFocus() {
4403        return (mPrivateFlags & FOCUSED) != 0 ? this : null;
4404    }
4405
4406    /**
4407     * Change whether this view is one of the set of scrollable containers in
4408     * its window.  This will be used to determine whether the window can
4409     * resize or must pan when a soft input area is open -- scrollable
4410     * containers allow the window to use resize mode since the container
4411     * will appropriately shrink.
4412     */
4413    public void setScrollContainer(boolean isScrollContainer) {
4414        if (isScrollContainer) {
4415            if (mAttachInfo != null && (mPrivateFlags&SCROLL_CONTAINER_ADDED) == 0) {
4416                mAttachInfo.mScrollContainers.add(this);
4417                mPrivateFlags |= SCROLL_CONTAINER_ADDED;
4418            }
4419            mPrivateFlags |= SCROLL_CONTAINER;
4420        } else {
4421            if ((mPrivateFlags&SCROLL_CONTAINER_ADDED) != 0) {
4422                mAttachInfo.mScrollContainers.remove(this);
4423            }
4424            mPrivateFlags &= ~(SCROLL_CONTAINER|SCROLL_CONTAINER_ADDED);
4425        }
4426    }
4427
4428    /**
4429     * Returns the quality of the drawing cache.
4430     *
4431     * @return One of {@link #DRAWING_CACHE_QUALITY_AUTO},
4432     *         {@link #DRAWING_CACHE_QUALITY_LOW}, or {@link #DRAWING_CACHE_QUALITY_HIGH}
4433     *
4434     * @see #setDrawingCacheQuality(int)
4435     * @see #setDrawingCacheEnabled(boolean)
4436     * @see #isDrawingCacheEnabled()
4437     *
4438     * @attr ref android.R.styleable#View_drawingCacheQuality
4439     */
4440    public int getDrawingCacheQuality() {
4441        return mViewFlags & DRAWING_CACHE_QUALITY_MASK;
4442    }
4443
4444    /**
4445     * Set the drawing cache quality of this view. This value is used only when the
4446     * drawing cache is enabled
4447     *
4448     * @param quality One of {@link #DRAWING_CACHE_QUALITY_AUTO},
4449     *        {@link #DRAWING_CACHE_QUALITY_LOW}, or {@link #DRAWING_CACHE_QUALITY_HIGH}
4450     *
4451     * @see #getDrawingCacheQuality()
4452     * @see #setDrawingCacheEnabled(boolean)
4453     * @see #isDrawingCacheEnabled()
4454     *
4455     * @attr ref android.R.styleable#View_drawingCacheQuality
4456     */
4457    public void setDrawingCacheQuality(int quality) {
4458        setFlags(quality, DRAWING_CACHE_QUALITY_MASK);
4459    }
4460
4461    /**
4462     * Returns whether the screen should remain on, corresponding to the current
4463     * value of {@link #KEEP_SCREEN_ON}.
4464     *
4465     * @return Returns true if {@link #KEEP_SCREEN_ON} is set.
4466     *
4467     * @see #setKeepScreenOn(boolean)
4468     *
4469     * @attr ref android.R.styleable#View_keepScreenOn
4470     */
4471    public boolean getKeepScreenOn() {
4472        return (mViewFlags & KEEP_SCREEN_ON) != 0;
4473    }
4474
4475    /**
4476     * Controls whether the screen should remain on, modifying the
4477     * value of {@link #KEEP_SCREEN_ON}.
4478     *
4479     * @param keepScreenOn Supply true to set {@link #KEEP_SCREEN_ON}.
4480     *
4481     * @see #getKeepScreenOn()
4482     *
4483     * @attr ref android.R.styleable#View_keepScreenOn
4484     */
4485    public void setKeepScreenOn(boolean keepScreenOn) {
4486        setFlags(keepScreenOn ? KEEP_SCREEN_ON : 0, KEEP_SCREEN_ON);
4487    }
4488
4489    /**
4490     * Gets the id of the view to use when the next focus is {@link #FOCUS_LEFT}.
4491     * @return The next focus ID, or {@link #NO_ID} if the framework should decide automatically.
4492     *
4493     * @attr ref android.R.styleable#View_nextFocusLeft
4494     */
4495    public int getNextFocusLeftId() {
4496        return mNextFocusLeftId;
4497    }
4498
4499    /**
4500     * Sets the id of the view to use when the next focus is {@link #FOCUS_LEFT}.
4501     * @param nextFocusLeftId The next focus ID, or {@link #NO_ID} if the framework should
4502     * decide automatically.
4503     *
4504     * @attr ref android.R.styleable#View_nextFocusLeft
4505     */
4506    public void setNextFocusLeftId(int nextFocusLeftId) {
4507        mNextFocusLeftId = nextFocusLeftId;
4508    }
4509
4510    /**
4511     * Gets the id of the view to use when the next focus is {@link #FOCUS_RIGHT}.
4512     * @return The next focus ID, or {@link #NO_ID} if the framework should decide automatically.
4513     *
4514     * @attr ref android.R.styleable#View_nextFocusRight
4515     */
4516    public int getNextFocusRightId() {
4517        return mNextFocusRightId;
4518    }
4519
4520    /**
4521     * Sets the id of the view to use when the next focus is {@link #FOCUS_RIGHT}.
4522     * @param nextFocusRightId The next focus ID, or {@link #NO_ID} if the framework should
4523     * decide automatically.
4524     *
4525     * @attr ref android.R.styleable#View_nextFocusRight
4526     */
4527    public void setNextFocusRightId(int nextFocusRightId) {
4528        mNextFocusRightId = nextFocusRightId;
4529    }
4530
4531    /**
4532     * Gets the id of the view to use when the next focus is {@link #FOCUS_UP}.
4533     * @return The next focus ID, or {@link #NO_ID} if the framework should decide automatically.
4534     *
4535     * @attr ref android.R.styleable#View_nextFocusUp
4536     */
4537    public int getNextFocusUpId() {
4538        return mNextFocusUpId;
4539    }
4540
4541    /**
4542     * Sets the id of the view to use when the next focus is {@link #FOCUS_UP}.
4543     * @param nextFocusUpId The next focus ID, or {@link #NO_ID} if the framework should
4544     * decide automatically.
4545     *
4546     * @attr ref android.R.styleable#View_nextFocusUp
4547     */
4548    public void setNextFocusUpId(int nextFocusUpId) {
4549        mNextFocusUpId = nextFocusUpId;
4550    }
4551
4552    /**
4553     * Gets the id of the view to use when the next focus is {@link #FOCUS_DOWN}.
4554     * @return The next focus ID, or {@link #NO_ID} if the framework should decide automatically.
4555     *
4556     * @attr ref android.R.styleable#View_nextFocusDown
4557     */
4558    public int getNextFocusDownId() {
4559        return mNextFocusDownId;
4560    }
4561
4562    /**
4563     * Sets the id of the view to use when the next focus is {@link #FOCUS_DOWN}.
4564     * @param nextFocusDownId The next focus ID, or {@link #NO_ID} if the framework should
4565     * decide automatically.
4566     *
4567     * @attr ref android.R.styleable#View_nextFocusDown
4568     */
4569    public void setNextFocusDownId(int nextFocusDownId) {
4570        mNextFocusDownId = nextFocusDownId;
4571    }
4572
4573    /**
4574     * Gets the id of the view to use when the next focus is {@link #FOCUS_FORWARD}.
4575     * @return The next focus ID, or {@link #NO_ID} if the framework should decide automatically.
4576     *
4577     * @attr ref android.R.styleable#View_nextFocusForward
4578     */
4579    public int getNextFocusForwardId() {
4580        return mNextFocusForwardId;
4581    }
4582
4583    /**
4584     * Sets the id of the view to use when the next focus is {@link #FOCUS_FORWARD}.
4585     * @param nextFocusForwardId The next focus ID, or {@link #NO_ID} if the framework should
4586     * decide automatically.
4587     *
4588     * @attr ref android.R.styleable#View_nextFocusForward
4589     */
4590    public void setNextFocusForwardId(int nextFocusForwardId) {
4591        mNextFocusForwardId = nextFocusForwardId;
4592    }
4593
4594    /**
4595     * Returns the visibility of this view and all of its ancestors
4596     *
4597     * @return True if this view and all of its ancestors are {@link #VISIBLE}
4598     */
4599    public boolean isShown() {
4600        View current = this;
4601        //noinspection ConstantConditions
4602        do {
4603            if ((current.mViewFlags & VISIBILITY_MASK) != VISIBLE) {
4604                return false;
4605            }
4606            ViewParent parent = current.mParent;
4607            if (parent == null) {
4608                return false; // We are not attached to the view root
4609            }
4610            if (!(parent instanceof View)) {
4611                return true;
4612            }
4613            current = (View) parent;
4614        } while (current != null);
4615
4616        return false;
4617    }
4618
4619    /**
4620     * Apply the insets for system windows to this view, if the FITS_SYSTEM_WINDOWS flag
4621     * is set
4622     *
4623     * @param insets Insets for system windows
4624     *
4625     * @return True if this view applied the insets, false otherwise
4626     */
4627    protected boolean fitSystemWindows(Rect insets) {
4628        if ((mViewFlags & FITS_SYSTEM_WINDOWS) == FITS_SYSTEM_WINDOWS) {
4629            mPaddingLeft = insets.left;
4630            mPaddingTop = insets.top;
4631            mPaddingRight = insets.right;
4632            mPaddingBottom = insets.bottom;
4633            requestLayout();
4634            return true;
4635        }
4636        return false;
4637    }
4638
4639    /**
4640     * Set whether or not this view should account for system screen decorations
4641     * such as the status bar and inset its content. This allows this view to be
4642     * positioned in absolute screen coordinates and remain visible to the user.
4643     *
4644     * <p>This should only be used by top-level window decor views.
4645     *
4646     * @param fitSystemWindows true to inset content for system screen decorations, false for
4647     *                         default behavior.
4648     *
4649     * @attr ref android.R.styleable#View_fitsSystemWindows
4650     */
4651    public void setFitsSystemWindows(boolean fitSystemWindows) {
4652        setFlags(fitSystemWindows ? FITS_SYSTEM_WINDOWS : 0, FITS_SYSTEM_WINDOWS);
4653    }
4654
4655    /**
4656     * Check for the FITS_SYSTEM_WINDOWS flag. If this method returns true, this view
4657     * will account for system screen decorations such as the status bar and inset its
4658     * content. This allows the view to be positioned in absolute screen coordinates
4659     * and remain visible to the user.
4660     *
4661     * @return true if this view will adjust its content bounds for system screen decorations.
4662     *
4663     * @attr ref android.R.styleable#View_fitsSystemWindows
4664     */
4665    public boolean fitsSystemWindows() {
4666        return (mViewFlags & FITS_SYSTEM_WINDOWS) == FITS_SYSTEM_WINDOWS;
4667    }
4668
4669    /**
4670     * Returns the visibility status for this view.
4671     *
4672     * @return One of {@link #VISIBLE}, {@link #INVISIBLE}, or {@link #GONE}.
4673     * @attr ref android.R.styleable#View_visibility
4674     */
4675    @ViewDebug.ExportedProperty(mapping = {
4676        @ViewDebug.IntToString(from = VISIBLE,   to = "VISIBLE"),
4677        @ViewDebug.IntToString(from = INVISIBLE, to = "INVISIBLE"),
4678        @ViewDebug.IntToString(from = GONE,      to = "GONE")
4679    })
4680    public int getVisibility() {
4681        return mViewFlags & VISIBILITY_MASK;
4682    }
4683
4684    /**
4685     * Set the enabled state of this view.
4686     *
4687     * @param visibility One of {@link #VISIBLE}, {@link #INVISIBLE}, or {@link #GONE}.
4688     * @attr ref android.R.styleable#View_visibility
4689     */
4690    @RemotableViewMethod
4691    public void setVisibility(int visibility) {
4692        setFlags(visibility, VISIBILITY_MASK);
4693        if (mBGDrawable != null) mBGDrawable.setVisible(visibility == VISIBLE, false);
4694    }
4695
4696    /**
4697     * Returns the enabled status for this view. The interpretation of the
4698     * enabled state varies by subclass.
4699     *
4700     * @return True if this view is enabled, false otherwise.
4701     */
4702    @ViewDebug.ExportedProperty
4703    public boolean isEnabled() {
4704        return (mViewFlags & ENABLED_MASK) == ENABLED;
4705    }
4706
4707    /**
4708     * Set the enabled state of this view. The interpretation of the enabled
4709     * state varies by subclass.
4710     *
4711     * @param enabled True if this view is enabled, false otherwise.
4712     */
4713    @RemotableViewMethod
4714    public void setEnabled(boolean enabled) {
4715        if (enabled == isEnabled()) return;
4716
4717        setFlags(enabled ? ENABLED : DISABLED, ENABLED_MASK);
4718
4719        /*
4720         * The View most likely has to change its appearance, so refresh
4721         * the drawable state.
4722         */
4723        refreshDrawableState();
4724
4725        // Invalidate too, since the default behavior for views is to be
4726        // be drawn at 50% alpha rather than to change the drawable.
4727        invalidate(true);
4728    }
4729
4730    /**
4731     * Set whether this view can receive the focus.
4732     *
4733     * Setting this to false will also ensure that this view is not focusable
4734     * in touch mode.
4735     *
4736     * @param focusable If true, this view can receive the focus.
4737     *
4738     * @see #setFocusableInTouchMode(boolean)
4739     * @attr ref android.R.styleable#View_focusable
4740     */
4741    public void setFocusable(boolean focusable) {
4742        if (!focusable) {
4743            setFlags(0, FOCUSABLE_IN_TOUCH_MODE);
4744        }
4745        setFlags(focusable ? FOCUSABLE : NOT_FOCUSABLE, FOCUSABLE_MASK);
4746    }
4747
4748    /**
4749     * Set whether this view can receive focus while in touch mode.
4750     *
4751     * Setting this to true will also ensure that this view is focusable.
4752     *
4753     * @param focusableInTouchMode If true, this view can receive the focus while
4754     *   in touch mode.
4755     *
4756     * @see #setFocusable(boolean)
4757     * @attr ref android.R.styleable#View_focusableInTouchMode
4758     */
4759    public void setFocusableInTouchMode(boolean focusableInTouchMode) {
4760        // Focusable in touch mode should always be set before the focusable flag
4761        // otherwise, setting the focusable flag will trigger a focusableViewAvailable()
4762        // which, in touch mode, will not successfully request focus on this view
4763        // because the focusable in touch mode flag is not set
4764        setFlags(focusableInTouchMode ? FOCUSABLE_IN_TOUCH_MODE : 0, FOCUSABLE_IN_TOUCH_MODE);
4765        if (focusableInTouchMode) {
4766            setFlags(FOCUSABLE, FOCUSABLE_MASK);
4767        }
4768    }
4769
4770    /**
4771     * Set whether this view should have sound effects enabled for events such as
4772     * clicking and touching.
4773     *
4774     * <p>You may wish to disable sound effects for a view if you already play sounds,
4775     * for instance, a dial key that plays dtmf tones.
4776     *
4777     * @param soundEffectsEnabled whether sound effects are enabled for this view.
4778     * @see #isSoundEffectsEnabled()
4779     * @see #playSoundEffect(int)
4780     * @attr ref android.R.styleable#View_soundEffectsEnabled
4781     */
4782    public void setSoundEffectsEnabled(boolean soundEffectsEnabled) {
4783        setFlags(soundEffectsEnabled ? SOUND_EFFECTS_ENABLED: 0, SOUND_EFFECTS_ENABLED);
4784    }
4785
4786    /**
4787     * @return whether this view should have sound effects enabled for events such as
4788     *     clicking and touching.
4789     *
4790     * @see #setSoundEffectsEnabled(boolean)
4791     * @see #playSoundEffect(int)
4792     * @attr ref android.R.styleable#View_soundEffectsEnabled
4793     */
4794    @ViewDebug.ExportedProperty
4795    public boolean isSoundEffectsEnabled() {
4796        return SOUND_EFFECTS_ENABLED == (mViewFlags & SOUND_EFFECTS_ENABLED);
4797    }
4798
4799    /**
4800     * Set whether this view should have haptic feedback for events such as
4801     * long presses.
4802     *
4803     * <p>You may wish to disable haptic feedback if your view already controls
4804     * its own haptic feedback.
4805     *
4806     * @param hapticFeedbackEnabled whether haptic feedback enabled for this view.
4807     * @see #isHapticFeedbackEnabled()
4808     * @see #performHapticFeedback(int)
4809     * @attr ref android.R.styleable#View_hapticFeedbackEnabled
4810     */
4811    public void setHapticFeedbackEnabled(boolean hapticFeedbackEnabled) {
4812        setFlags(hapticFeedbackEnabled ? HAPTIC_FEEDBACK_ENABLED: 0, HAPTIC_FEEDBACK_ENABLED);
4813    }
4814
4815    /**
4816     * @return whether this view should have haptic feedback enabled for events
4817     * long presses.
4818     *
4819     * @see #setHapticFeedbackEnabled(boolean)
4820     * @see #performHapticFeedback(int)
4821     * @attr ref android.R.styleable#View_hapticFeedbackEnabled
4822     */
4823    @ViewDebug.ExportedProperty
4824    public boolean isHapticFeedbackEnabled() {
4825        return HAPTIC_FEEDBACK_ENABLED == (mViewFlags & HAPTIC_FEEDBACK_ENABLED);
4826    }
4827
4828    /**
4829     * Returns the layout direction for this view.
4830     *
4831     * @return One of {@link #LAYOUT_DIRECTION_LTR},
4832     *   {@link #LAYOUT_DIRECTION_RTL},
4833     *   {@link #LAYOUT_DIRECTION_INHERIT} or
4834     *   {@link #LAYOUT_DIRECTION_LOCALE}.
4835     * @attr ref android.R.styleable#View_layoutDirection
4836     */
4837    @ViewDebug.ExportedProperty(category = "layout", mapping = {
4838        @ViewDebug.IntToString(from = LAYOUT_DIRECTION_LTR,     to = "LTR"),
4839        @ViewDebug.IntToString(from = LAYOUT_DIRECTION_RTL,     to = "RTL"),
4840        @ViewDebug.IntToString(from = LAYOUT_DIRECTION_INHERIT, to = "INHERIT"),
4841        @ViewDebug.IntToString(from = LAYOUT_DIRECTION_LOCALE,  to = "LOCALE")
4842    })
4843    public int getLayoutDirection() {
4844        return mViewFlags & LAYOUT_DIRECTION_MASK;
4845    }
4846
4847    /**
4848     * Set the layout direction for this view. This will propagate a reset of layout direction
4849     * resolution to the view's children and resolve layout direction for this view.
4850     *
4851     * @param layoutDirection One of {@link #LAYOUT_DIRECTION_LTR},
4852     *   {@link #LAYOUT_DIRECTION_RTL},
4853     *   {@link #LAYOUT_DIRECTION_INHERIT} or
4854     *   {@link #LAYOUT_DIRECTION_LOCALE}.
4855     *
4856     * @attr ref android.R.styleable#View_layoutDirection
4857     */
4858    @RemotableViewMethod
4859    public void setLayoutDirection(int layoutDirection) {
4860        if (getLayoutDirection() != layoutDirection) {
4861            resetResolvedLayoutDirection();
4862            // Setting the flag will also request a layout.
4863            setFlags(layoutDirection, LAYOUT_DIRECTION_MASK);
4864        }
4865    }
4866
4867    /**
4868     * Returns the resolved layout direction for this view.
4869     *
4870     * @return {@link #LAYOUT_DIRECTION_RTL} if the layout direction is RTL or returns
4871     * {@link #LAYOUT_DIRECTION_LTR} id the layout direction is not RTL.
4872     */
4873    @ViewDebug.ExportedProperty(category = "layout", mapping = {
4874        @ViewDebug.IntToString(from = LAYOUT_DIRECTION_LTR,     to = "RESOLVED_DIRECTION_LTR"),
4875        @ViewDebug.IntToString(from = LAYOUT_DIRECTION_RTL,     to = "RESOLVED_DIRECTION_RTL")
4876    })
4877    public int getResolvedLayoutDirection() {
4878        resolveLayoutDirectionIfNeeded();
4879        return ((mPrivateFlags2 & LAYOUT_DIRECTION_RESOLVED_RTL) == LAYOUT_DIRECTION_RESOLVED_RTL) ?
4880                LAYOUT_DIRECTION_RTL : LAYOUT_DIRECTION_LTR;
4881    }
4882
4883    /**
4884     * <p>Indicates whether or not this view's layout is right-to-left. This is resolved from
4885     * layout attribute and/or the inherited value from the parent.</p>
4886     *
4887     * @return true if the layout is right-to-left.
4888     */
4889    @ViewDebug.ExportedProperty(category = "layout")
4890    public boolean isLayoutRtl() {
4891        return (getResolvedLayoutDirection() == LAYOUT_DIRECTION_RTL);
4892    }
4893
4894    /**
4895     * Indicates whether the view is currently tracking transient state that the
4896     * app should not need to concern itself with saving and restoring, but that
4897     * the framework should take special note to preserve when possible.
4898     *
4899     * @return true if the view has transient state
4900     */
4901    @ViewDebug.ExportedProperty(category = "layout")
4902    public boolean hasTransientState() {
4903        return (mPrivateFlags2 & HAS_TRANSIENT_STATE) == HAS_TRANSIENT_STATE;
4904    }
4905
4906    /**
4907     * Set whether this view is currently tracking transient state that the
4908     * framework should attempt to preserve when possible.
4909     *
4910     * @param hasTransientState true if this view has transient state
4911     */
4912    public void setHasTransientState(boolean hasTransientState) {
4913        if (hasTransientState() == hasTransientState) return;
4914
4915        mPrivateFlags2 = (mPrivateFlags2 & ~HAS_TRANSIENT_STATE) |
4916                (hasTransientState ? HAS_TRANSIENT_STATE : 0);
4917        if (mParent != null) {
4918            try {
4919                mParent.childHasTransientStateChanged(this, hasTransientState);
4920            } catch (AbstractMethodError e) {
4921                Log.e(VIEW_LOG_TAG, mParent.getClass().getSimpleName() +
4922                        " does not fully implement ViewParent", e);
4923            }
4924        }
4925    }
4926
4927    /**
4928     * If this view doesn't do any drawing on its own, set this flag to
4929     * allow further optimizations. By default, this flag is not set on
4930     * View, but could be set on some View subclasses such as ViewGroup.
4931     *
4932     * Typically, if you override {@link #onDraw(android.graphics.Canvas)}
4933     * you should clear this flag.
4934     *
4935     * @param willNotDraw whether or not this View draw on its own
4936     */
4937    public void setWillNotDraw(boolean willNotDraw) {
4938        setFlags(willNotDraw ? WILL_NOT_DRAW : 0, DRAW_MASK);
4939    }
4940
4941    /**
4942     * Returns whether or not this View draws on its own.
4943     *
4944     * @return true if this view has nothing to draw, false otherwise
4945     */
4946    @ViewDebug.ExportedProperty(category = "drawing")
4947    public boolean willNotDraw() {
4948        return (mViewFlags & DRAW_MASK) == WILL_NOT_DRAW;
4949    }
4950
4951    /**
4952     * When a View's drawing cache is enabled, drawing is redirected to an
4953     * offscreen bitmap. Some views, like an ImageView, must be able to
4954     * bypass this mechanism if they already draw a single bitmap, to avoid
4955     * unnecessary usage of the memory.
4956     *
4957     * @param willNotCacheDrawing true if this view does not cache its
4958     *        drawing, false otherwise
4959     */
4960    public void setWillNotCacheDrawing(boolean willNotCacheDrawing) {
4961        setFlags(willNotCacheDrawing ? WILL_NOT_CACHE_DRAWING : 0, WILL_NOT_CACHE_DRAWING);
4962    }
4963
4964    /**
4965     * Returns whether or not this View can cache its drawing or not.
4966     *
4967     * @return true if this view does not cache its drawing, false otherwise
4968     */
4969    @ViewDebug.ExportedProperty(category = "drawing")
4970    public boolean willNotCacheDrawing() {
4971        return (mViewFlags & WILL_NOT_CACHE_DRAWING) == WILL_NOT_CACHE_DRAWING;
4972    }
4973
4974    /**
4975     * Indicates whether this view reacts to click events or not.
4976     *
4977     * @return true if the view is clickable, false otherwise
4978     *
4979     * @see #setClickable(boolean)
4980     * @attr ref android.R.styleable#View_clickable
4981     */
4982    @ViewDebug.ExportedProperty
4983    public boolean isClickable() {
4984        return (mViewFlags & CLICKABLE) == CLICKABLE;
4985    }
4986
4987    /**
4988     * Enables or disables click events for this view. When a view
4989     * is clickable it will change its state to "pressed" on every click.
4990     * Subclasses should set the view clickable to visually react to
4991     * user's clicks.
4992     *
4993     * @param clickable true to make the view clickable, false otherwise
4994     *
4995     * @see #isClickable()
4996     * @attr ref android.R.styleable#View_clickable
4997     */
4998    public void setClickable(boolean clickable) {
4999        setFlags(clickable ? CLICKABLE : 0, CLICKABLE);
5000    }
5001
5002    /**
5003     * Indicates whether this view reacts to long click events or not.
5004     *
5005     * @return true if the view is long clickable, false otherwise
5006     *
5007     * @see #setLongClickable(boolean)
5008     * @attr ref android.R.styleable#View_longClickable
5009     */
5010    public boolean isLongClickable() {
5011        return (mViewFlags & LONG_CLICKABLE) == LONG_CLICKABLE;
5012    }
5013
5014    /**
5015     * Enables or disables long click events for this view. When a view is long
5016     * clickable it reacts to the user holding down the button for a longer
5017     * duration than a tap. This event can either launch the listener or a
5018     * context menu.
5019     *
5020     * @param longClickable true to make the view long clickable, false otherwise
5021     * @see #isLongClickable()
5022     * @attr ref android.R.styleable#View_longClickable
5023     */
5024    public void setLongClickable(boolean longClickable) {
5025        setFlags(longClickable ? LONG_CLICKABLE : 0, LONG_CLICKABLE);
5026    }
5027
5028    /**
5029     * Sets the pressed state for this view.
5030     *
5031     * @see #isClickable()
5032     * @see #setClickable(boolean)
5033     *
5034     * @param pressed Pass true to set the View's internal state to "pressed", or false to reverts
5035     *        the View's internal state from a previously set "pressed" state.
5036     */
5037    public void setPressed(boolean pressed) {
5038        final boolean needsRefresh = pressed != ((mPrivateFlags & PRESSED) == PRESSED);
5039
5040        if (pressed) {
5041            mPrivateFlags |= PRESSED;
5042        } else {
5043            mPrivateFlags &= ~PRESSED;
5044        }
5045
5046        if (needsRefresh) {
5047            refreshDrawableState();
5048        }
5049        dispatchSetPressed(pressed);
5050    }
5051
5052    /**
5053     * Dispatch setPressed to all of this View's children.
5054     *
5055     * @see #setPressed(boolean)
5056     *
5057     * @param pressed The new pressed state
5058     */
5059    protected void dispatchSetPressed(boolean pressed) {
5060    }
5061
5062    /**
5063     * Indicates whether the view is currently in pressed state. Unless
5064     * {@link #setPressed(boolean)} is explicitly called, only clickable views can enter
5065     * the pressed state.
5066     *
5067     * @see #setPressed(boolean)
5068     * @see #isClickable()
5069     * @see #setClickable(boolean)
5070     *
5071     * @return true if the view is currently pressed, false otherwise
5072     */
5073    public boolean isPressed() {
5074        return (mPrivateFlags & PRESSED) == PRESSED;
5075    }
5076
5077    /**
5078     * Indicates whether this view will save its state (that is,
5079     * whether its {@link #onSaveInstanceState} method will be called).
5080     *
5081     * @return Returns true if the view state saving is enabled, else false.
5082     *
5083     * @see #setSaveEnabled(boolean)
5084     * @attr ref android.R.styleable#View_saveEnabled
5085     */
5086    public boolean isSaveEnabled() {
5087        return (mViewFlags & SAVE_DISABLED_MASK) != SAVE_DISABLED;
5088    }
5089
5090    /**
5091     * Controls whether the saving of this view's state is
5092     * enabled (that is, whether its {@link #onSaveInstanceState} method
5093     * will be called).  Note that even if freezing is enabled, the
5094     * view still must have an id assigned to it (via {@link #setId(int)})
5095     * for its state to be saved.  This flag can only disable the
5096     * saving of this view; any child views may still have their state saved.
5097     *
5098     * @param enabled Set to false to <em>disable</em> state saving, or true
5099     * (the default) to allow it.
5100     *
5101     * @see #isSaveEnabled()
5102     * @see #setId(int)
5103     * @see #onSaveInstanceState()
5104     * @attr ref android.R.styleable#View_saveEnabled
5105     */
5106    public void setSaveEnabled(boolean enabled) {
5107        setFlags(enabled ? 0 : SAVE_DISABLED, SAVE_DISABLED_MASK);
5108    }
5109
5110    /**
5111     * Gets whether the framework should discard touches when the view's
5112     * window is obscured by another visible window.
5113     * Refer to the {@link View} security documentation for more details.
5114     *
5115     * @return True if touch filtering is enabled.
5116     *
5117     * @see #setFilterTouchesWhenObscured(boolean)
5118     * @attr ref android.R.styleable#View_filterTouchesWhenObscured
5119     */
5120    @ViewDebug.ExportedProperty
5121    public boolean getFilterTouchesWhenObscured() {
5122        return (mViewFlags & FILTER_TOUCHES_WHEN_OBSCURED) != 0;
5123    }
5124
5125    /**
5126     * Sets whether the framework should discard touches when the view's
5127     * window is obscured by another visible window.
5128     * Refer to the {@link View} security documentation for more details.
5129     *
5130     * @param enabled True if touch filtering should be enabled.
5131     *
5132     * @see #getFilterTouchesWhenObscured
5133     * @attr ref android.R.styleable#View_filterTouchesWhenObscured
5134     */
5135    public void setFilterTouchesWhenObscured(boolean enabled) {
5136        setFlags(enabled ? 0 : FILTER_TOUCHES_WHEN_OBSCURED,
5137                FILTER_TOUCHES_WHEN_OBSCURED);
5138    }
5139
5140    /**
5141     * Indicates whether the entire hierarchy under this view will save its
5142     * state when a state saving traversal occurs from its parent.  The default
5143     * is true; if false, these views will not be saved unless
5144     * {@link #saveHierarchyState(SparseArray)} is called directly on this view.
5145     *
5146     * @return Returns true if the view state saving from parent is enabled, else false.
5147     *
5148     * @see #setSaveFromParentEnabled(boolean)
5149     */
5150    public boolean isSaveFromParentEnabled() {
5151        return (mViewFlags & PARENT_SAVE_DISABLED_MASK) != PARENT_SAVE_DISABLED;
5152    }
5153
5154    /**
5155     * Controls whether the entire hierarchy under this view will save its
5156     * state when a state saving traversal occurs from its parent.  The default
5157     * is true; if false, these views will not be saved unless
5158     * {@link #saveHierarchyState(SparseArray)} is called directly on this view.
5159     *
5160     * @param enabled Set to false to <em>disable</em> state saving, or true
5161     * (the default) to allow it.
5162     *
5163     * @see #isSaveFromParentEnabled()
5164     * @see #setId(int)
5165     * @see #onSaveInstanceState()
5166     */
5167    public void setSaveFromParentEnabled(boolean enabled) {
5168        setFlags(enabled ? 0 : PARENT_SAVE_DISABLED, PARENT_SAVE_DISABLED_MASK);
5169    }
5170
5171
5172    /**
5173     * Returns whether this View is able to take focus.
5174     *
5175     * @return True if this view can take focus, or false otherwise.
5176     * @attr ref android.R.styleable#View_focusable
5177     */
5178    @ViewDebug.ExportedProperty(category = "focus")
5179    public final boolean isFocusable() {
5180        return FOCUSABLE == (mViewFlags & FOCUSABLE_MASK);
5181    }
5182
5183    /**
5184     * When a view is focusable, it may not want to take focus when in touch mode.
5185     * For example, a button would like focus when the user is navigating via a D-pad
5186     * so that the user can click on it, but once the user starts touching the screen,
5187     * the button shouldn't take focus
5188     * @return Whether the view is focusable in touch mode.
5189     * @attr ref android.R.styleable#View_focusableInTouchMode
5190     */
5191    @ViewDebug.ExportedProperty
5192    public final boolean isFocusableInTouchMode() {
5193        return FOCUSABLE_IN_TOUCH_MODE == (mViewFlags & FOCUSABLE_IN_TOUCH_MODE);
5194    }
5195
5196    /**
5197     * Find the nearest view in the specified direction that can take focus.
5198     * This does not actually give focus to that view.
5199     *
5200     * @param direction One of FOCUS_UP, FOCUS_DOWN, FOCUS_LEFT, and FOCUS_RIGHT
5201     *
5202     * @return The nearest focusable in the specified direction, or null if none
5203     *         can be found.
5204     */
5205    public View focusSearch(int direction) {
5206        if (mParent != null) {
5207            return mParent.focusSearch(this, direction);
5208        } else {
5209            return null;
5210        }
5211    }
5212
5213    /**
5214     * This method is the last chance for the focused view and its ancestors to
5215     * respond to an arrow key. This is called when the focused view did not
5216     * consume the key internally, nor could the view system find a new view in
5217     * the requested direction to give focus to.
5218     *
5219     * @param focused The currently focused view.
5220     * @param direction The direction focus wants to move. One of FOCUS_UP,
5221     *        FOCUS_DOWN, FOCUS_LEFT, and FOCUS_RIGHT.
5222     * @return True if the this view consumed this unhandled move.
5223     */
5224    public boolean dispatchUnhandledMove(View focused, int direction) {
5225        return false;
5226    }
5227
5228    /**
5229     * If a user manually specified the next view id for a particular direction,
5230     * use the root to look up the view.
5231     * @param root The root view of the hierarchy containing this view.
5232     * @param direction One of FOCUS_UP, FOCUS_DOWN, FOCUS_LEFT, FOCUS_RIGHT, FOCUS_FORWARD,
5233     * or FOCUS_BACKWARD.
5234     * @return The user specified next view, or null if there is none.
5235     */
5236    View findUserSetNextFocus(View root, int direction) {
5237        switch (direction) {
5238            case FOCUS_LEFT:
5239                if (mNextFocusLeftId == View.NO_ID) return null;
5240                return findViewInsideOutShouldExist(root, mNextFocusLeftId);
5241            case FOCUS_RIGHT:
5242                if (mNextFocusRightId == View.NO_ID) return null;
5243                return findViewInsideOutShouldExist(root, mNextFocusRightId);
5244            case FOCUS_UP:
5245                if (mNextFocusUpId == View.NO_ID) return null;
5246                return findViewInsideOutShouldExist(root, mNextFocusUpId);
5247            case FOCUS_DOWN:
5248                if (mNextFocusDownId == View.NO_ID) return null;
5249                return findViewInsideOutShouldExist(root, mNextFocusDownId);
5250            case FOCUS_FORWARD:
5251                if (mNextFocusForwardId == View.NO_ID) return null;
5252                return findViewInsideOutShouldExist(root, mNextFocusForwardId);
5253            case FOCUS_BACKWARD: {
5254                if (mID == View.NO_ID) return null;
5255                final int id = mID;
5256                return root.findViewByPredicateInsideOut(this, new Predicate<View>() {
5257                    @Override
5258                    public boolean apply(View t) {
5259                        return t.mNextFocusForwardId == id;
5260                    }
5261                });
5262            }
5263        }
5264        return null;
5265    }
5266
5267    private View findViewInsideOutShouldExist(View root, final int childViewId) {
5268        View result = root.findViewByPredicateInsideOut(this, new Predicate<View>() {
5269            @Override
5270            public boolean apply(View t) {
5271                return t.mID == childViewId;
5272            }
5273        });
5274
5275        if (result == null) {
5276            Log.w(VIEW_LOG_TAG, "couldn't find next focus view specified "
5277                    + "by user for id " + childViewId);
5278        }
5279        return result;
5280    }
5281
5282    /**
5283     * Find and return all focusable views that are descendants of this view,
5284     * possibly including this view if it is focusable itself.
5285     *
5286     * @param direction The direction of the focus
5287     * @return A list of focusable views
5288     */
5289    public ArrayList<View> getFocusables(int direction) {
5290        ArrayList<View> result = new ArrayList<View>(24);
5291        addFocusables(result, direction);
5292        return result;
5293    }
5294
5295    /**
5296     * Add any focusable views that are descendants of this view (possibly
5297     * including this view if it is focusable itself) to views.  If we are in touch mode,
5298     * only add views that are also focusable in touch mode.
5299     *
5300     * @param views Focusable views found so far
5301     * @param direction The direction of the focus
5302     */
5303    public void addFocusables(ArrayList<View> views, int direction) {
5304        addFocusables(views, direction, FOCUSABLES_TOUCH_MODE);
5305    }
5306
5307    /**
5308     * Adds any focusable views that are descendants of this view (possibly
5309     * including this view if it is focusable itself) to views. This method
5310     * adds all focusable views regardless if we are in touch mode or
5311     * only views focusable in touch mode if we are in touch mode depending on
5312     * the focusable mode paramater.
5313     *
5314     * @param views Focusable views found so far or null if all we are interested is
5315     *        the number of focusables.
5316     * @param direction The direction of the focus.
5317     * @param focusableMode The type of focusables to be added.
5318     *
5319     * @see #FOCUSABLES_ALL
5320     * @see #FOCUSABLES_TOUCH_MODE
5321     */
5322    public void addFocusables(ArrayList<View> views, int direction, int focusableMode) {
5323        if (!isFocusable()) {
5324            return;
5325        }
5326
5327        if ((focusableMode & FOCUSABLES_TOUCH_MODE) == FOCUSABLES_TOUCH_MODE &&
5328                isInTouchMode() && !isFocusableInTouchMode()) {
5329            return;
5330        }
5331
5332        if (views != null) {
5333            views.add(this);
5334        }
5335    }
5336
5337    /**
5338     * Finds the Views that contain given text. The containment is case insensitive.
5339     * The search is performed by either the text that the View renders or the content
5340     * description that describes the view for accessibility purposes and the view does
5341     * not render or both. Clients can specify how the search is to be performed via
5342     * passing the {@link #FIND_VIEWS_WITH_TEXT} and
5343     * {@link #FIND_VIEWS_WITH_CONTENT_DESCRIPTION} flags.
5344     *
5345     * @param outViews The output list of matching Views.
5346     * @param searched The text to match against.
5347     *
5348     * @see #FIND_VIEWS_WITH_TEXT
5349     * @see #FIND_VIEWS_WITH_CONTENT_DESCRIPTION
5350     * @see #setContentDescription(CharSequence)
5351     */
5352    public void findViewsWithText(ArrayList<View> outViews, CharSequence searched, int flags) {
5353        if (getAccessibilityNodeProvider() != null) {
5354            if ((flags & FIND_VIEWS_WITH_ACCESSIBILITY_NODE_PROVIDERS) != 0) {
5355                outViews.add(this);
5356            }
5357        } else if ((flags & FIND_VIEWS_WITH_CONTENT_DESCRIPTION) != 0
5358                && !TextUtils.isEmpty(searched) && !TextUtils.isEmpty(mContentDescription)) {
5359            String searchedLowerCase = searched.toString().toLowerCase();
5360            String contentDescriptionLowerCase = mContentDescription.toString().toLowerCase();
5361            if (contentDescriptionLowerCase.contains(searchedLowerCase)) {
5362                outViews.add(this);
5363            }
5364        }
5365    }
5366
5367    /**
5368     * Find and return all touchable views that are descendants of this view,
5369     * possibly including this view if it is touchable itself.
5370     *
5371     * @return A list of touchable views
5372     */
5373    public ArrayList<View> getTouchables() {
5374        ArrayList<View> result = new ArrayList<View>();
5375        addTouchables(result);
5376        return result;
5377    }
5378
5379    /**
5380     * Add any touchable views that are descendants of this view (possibly
5381     * including this view if it is touchable itself) to views.
5382     *
5383     * @param views Touchable views found so far
5384     */
5385    public void addTouchables(ArrayList<View> views) {
5386        final int viewFlags = mViewFlags;
5387
5388        if (((viewFlags & CLICKABLE) == CLICKABLE || (viewFlags & LONG_CLICKABLE) == LONG_CLICKABLE)
5389                && (viewFlags & ENABLED_MASK) == ENABLED) {
5390            views.add(this);
5391        }
5392    }
5393
5394    /**
5395     * Call this to try to give focus to a specific view or to one of its
5396     * descendants.
5397     *
5398     * A view will not actually take focus if it is not focusable ({@link #isFocusable} returns
5399     * false), or if it is focusable and it is not focusable in touch mode
5400     * ({@link #isFocusableInTouchMode}) while the device is in touch mode.
5401     *
5402     * See also {@link #focusSearch(int)}, which is what you call to say that you
5403     * have focus, and you want your parent to look for the next one.
5404     *
5405     * This is equivalent to calling {@link #requestFocus(int, Rect)} with arguments
5406     * {@link #FOCUS_DOWN} and <code>null</code>.
5407     *
5408     * @return Whether this view or one of its descendants actually took focus.
5409     */
5410    public final boolean requestFocus() {
5411        return requestFocus(View.FOCUS_DOWN);
5412    }
5413
5414
5415    /**
5416     * Call this to try to give focus to a specific view or to one of its
5417     * descendants and give it a hint about what direction focus is heading.
5418     *
5419     * A view will not actually take focus if it is not focusable ({@link #isFocusable} returns
5420     * false), or if it is focusable and it is not focusable in touch mode
5421     * ({@link #isFocusableInTouchMode}) while the device is in touch mode.
5422     *
5423     * See also {@link #focusSearch(int)}, which is what you call to say that you
5424     * have focus, and you want your parent to look for the next one.
5425     *
5426     * This is equivalent to calling {@link #requestFocus(int, Rect)} with
5427     * <code>null</code> set for the previously focused rectangle.
5428     *
5429     * @param direction One of FOCUS_UP, FOCUS_DOWN, FOCUS_LEFT, and FOCUS_RIGHT
5430     * @return Whether this view or one of its descendants actually took focus.
5431     */
5432    public final boolean requestFocus(int direction) {
5433        return requestFocus(direction, null);
5434    }
5435
5436    /**
5437     * Call this to try to give focus to a specific view or to one of its descendants
5438     * and give it hints about the direction and a specific rectangle that the focus
5439     * is coming from.  The rectangle can help give larger views a finer grained hint
5440     * about where focus is coming from, and therefore, where to show selection, or
5441     * forward focus change internally.
5442     *
5443     * A view will not actually take focus if it is not focusable ({@link #isFocusable} returns
5444     * false), or if it is focusable and it is not focusable in touch mode
5445     * ({@link #isFocusableInTouchMode}) while the device is in touch mode.
5446     *
5447     * A View will not take focus if it is not visible.
5448     *
5449     * A View will not take focus if one of its parents has
5450     * {@link android.view.ViewGroup#getDescendantFocusability()} equal to
5451     * {@link ViewGroup#FOCUS_BLOCK_DESCENDANTS}.
5452     *
5453     * See also {@link #focusSearch(int)}, which is what you call to say that you
5454     * have focus, and you want your parent to look for the next one.
5455     *
5456     * You may wish to override this method if your custom {@link View} has an internal
5457     * {@link View} that it wishes to forward the request to.
5458     *
5459     * @param direction One of FOCUS_UP, FOCUS_DOWN, FOCUS_LEFT, and FOCUS_RIGHT
5460     * @param previouslyFocusedRect The rectangle (in this View's coordinate system)
5461     *        to give a finer grained hint about where focus is coming from.  May be null
5462     *        if there is no hint.
5463     * @return Whether this view or one of its descendants actually took focus.
5464     */
5465    public boolean requestFocus(int direction, Rect previouslyFocusedRect) {
5466        // need to be focusable
5467        if ((mViewFlags & FOCUSABLE_MASK) != FOCUSABLE ||
5468                (mViewFlags & VISIBILITY_MASK) != VISIBLE) {
5469            return false;
5470        }
5471
5472        // need to be focusable in touch mode if in touch mode
5473        if (isInTouchMode() &&
5474            (FOCUSABLE_IN_TOUCH_MODE != (mViewFlags & FOCUSABLE_IN_TOUCH_MODE))) {
5475               return false;
5476        }
5477
5478        // need to not have any parents blocking us
5479        if (hasAncestorThatBlocksDescendantFocus()) {
5480            return false;
5481        }
5482
5483        handleFocusGainInternal(direction, previouslyFocusedRect);
5484        return true;
5485    }
5486
5487    /**
5488     * Call this to try to give focus to a specific view or to one of its descendants. This is a
5489     * special variant of {@link #requestFocus() } that will allow views that are not focuable in
5490     * touch mode to request focus when they are touched.
5491     *
5492     * @return Whether this view or one of its descendants actually took focus.
5493     *
5494     * @see #isInTouchMode()
5495     *
5496     */
5497    public final boolean requestFocusFromTouch() {
5498        // Leave touch mode if we need to
5499        if (isInTouchMode()) {
5500            ViewRootImpl viewRoot = getViewRootImpl();
5501            if (viewRoot != null) {
5502                viewRoot.ensureTouchMode(false);
5503            }
5504        }
5505        return requestFocus(View.FOCUS_DOWN);
5506    }
5507
5508    /**
5509     * @return Whether any ancestor of this view blocks descendant focus.
5510     */
5511    private boolean hasAncestorThatBlocksDescendantFocus() {
5512        ViewParent ancestor = mParent;
5513        while (ancestor instanceof ViewGroup) {
5514            final ViewGroup vgAncestor = (ViewGroup) ancestor;
5515            if (vgAncestor.getDescendantFocusability() == ViewGroup.FOCUS_BLOCK_DESCENDANTS) {
5516                return true;
5517            } else {
5518                ancestor = vgAncestor.getParent();
5519            }
5520        }
5521        return false;
5522    }
5523
5524    /**
5525     * @hide
5526     */
5527    public void dispatchStartTemporaryDetach() {
5528        onStartTemporaryDetach();
5529    }
5530
5531    /**
5532     * This is called when a container is going to temporarily detach a child, with
5533     * {@link ViewGroup#detachViewFromParent(View) ViewGroup.detachViewFromParent}.
5534     * It will either be followed by {@link #onFinishTemporaryDetach()} or
5535     * {@link #onDetachedFromWindow()} when the container is done.
5536     */
5537    public void onStartTemporaryDetach() {
5538        removeUnsetPressCallback();
5539        mPrivateFlags |= CANCEL_NEXT_UP_EVENT;
5540    }
5541
5542    /**
5543     * @hide
5544     */
5545    public void dispatchFinishTemporaryDetach() {
5546        onFinishTemporaryDetach();
5547    }
5548
5549    /**
5550     * Called after {@link #onStartTemporaryDetach} when the container is done
5551     * changing the view.
5552     */
5553    public void onFinishTemporaryDetach() {
5554    }
5555
5556    /**
5557     * Return the global {@link KeyEvent.DispatcherState KeyEvent.DispatcherState}
5558     * for this view's window.  Returns null if the view is not currently attached
5559     * to the window.  Normally you will not need to use this directly, but
5560     * just use the standard high-level event callbacks like
5561     * {@link #onKeyDown(int, KeyEvent)}.
5562     */
5563    public KeyEvent.DispatcherState getKeyDispatcherState() {
5564        return mAttachInfo != null ? mAttachInfo.mKeyDispatchState : null;
5565    }
5566
5567    /**
5568     * Dispatch a key event before it is processed by any input method
5569     * associated with the view hierarchy.  This can be used to intercept
5570     * key events in special situations before the IME consumes them; a
5571     * typical example would be handling the BACK key to update the application's
5572     * UI instead of allowing the IME to see it and close itself.
5573     *
5574     * @param event The key event to be dispatched.
5575     * @return True if the event was handled, false otherwise.
5576     */
5577    public boolean dispatchKeyEventPreIme(KeyEvent event) {
5578        return onKeyPreIme(event.getKeyCode(), event);
5579    }
5580
5581    /**
5582     * Dispatch a key event to the next view on the focus path. This path runs
5583     * from the top of the view tree down to the currently focused view. If this
5584     * view has focus, it will dispatch to itself. Otherwise it will dispatch
5585     * the next node down the focus path. This method also fires any key
5586     * listeners.
5587     *
5588     * @param event The key event to be dispatched.
5589     * @return True if the event was handled, false otherwise.
5590     */
5591    public boolean dispatchKeyEvent(KeyEvent event) {
5592        if (mInputEventConsistencyVerifier != null) {
5593            mInputEventConsistencyVerifier.onKeyEvent(event, 0);
5594        }
5595
5596        // Give any attached key listener a first crack at the event.
5597        //noinspection SimplifiableIfStatement
5598        ListenerInfo li = mListenerInfo;
5599        if (li != null && li.mOnKeyListener != null && (mViewFlags & ENABLED_MASK) == ENABLED
5600                && li.mOnKeyListener.onKey(this, event.getKeyCode(), event)) {
5601            return true;
5602        }
5603
5604        if (event.dispatch(this, mAttachInfo != null
5605                ? mAttachInfo.mKeyDispatchState : null, this)) {
5606            return true;
5607        }
5608
5609        if (mInputEventConsistencyVerifier != null) {
5610            mInputEventConsistencyVerifier.onUnhandledEvent(event, 0);
5611        }
5612        return false;
5613    }
5614
5615    /**
5616     * Dispatches a key shortcut event.
5617     *
5618     * @param event The key event to be dispatched.
5619     * @return True if the event was handled by the view, false otherwise.
5620     */
5621    public boolean dispatchKeyShortcutEvent(KeyEvent event) {
5622        return onKeyShortcut(event.getKeyCode(), event);
5623    }
5624
5625    /**
5626     * Pass the touch screen motion event down to the target view, or this
5627     * view if it is the target.
5628     *
5629     * @param event The motion event to be dispatched.
5630     * @return True if the event was handled by the view, false otherwise.
5631     */
5632    public boolean dispatchTouchEvent(MotionEvent event) {
5633        if (mInputEventConsistencyVerifier != null) {
5634            mInputEventConsistencyVerifier.onTouchEvent(event, 0);
5635        }
5636
5637        if (onFilterTouchEventForSecurity(event)) {
5638            //noinspection SimplifiableIfStatement
5639            ListenerInfo li = mListenerInfo;
5640            if (li != null && li.mOnTouchListener != null && (mViewFlags & ENABLED_MASK) == ENABLED
5641                    && li.mOnTouchListener.onTouch(this, event)) {
5642                return true;
5643            }
5644
5645            if (onTouchEvent(event)) {
5646                return true;
5647            }
5648        }
5649
5650        if (mInputEventConsistencyVerifier != null) {
5651            mInputEventConsistencyVerifier.onUnhandledEvent(event, 0);
5652        }
5653        return false;
5654    }
5655
5656    /**
5657     * Filter the touch event to apply security policies.
5658     *
5659     * @param event The motion event to be filtered.
5660     * @return True if the event should be dispatched, false if the event should be dropped.
5661     *
5662     * @see #getFilterTouchesWhenObscured
5663     */
5664    public boolean onFilterTouchEventForSecurity(MotionEvent event) {
5665        //noinspection RedundantIfStatement
5666        if ((mViewFlags & FILTER_TOUCHES_WHEN_OBSCURED) != 0
5667                && (event.getFlags() & MotionEvent.FLAG_WINDOW_IS_OBSCURED) != 0) {
5668            // Window is obscured, drop this touch.
5669            return false;
5670        }
5671        return true;
5672    }
5673
5674    /**
5675     * Pass a trackball motion event down to the focused view.
5676     *
5677     * @param event The motion event to be dispatched.
5678     * @return True if the event was handled by the view, false otherwise.
5679     */
5680    public boolean dispatchTrackballEvent(MotionEvent event) {
5681        if (mInputEventConsistencyVerifier != null) {
5682            mInputEventConsistencyVerifier.onTrackballEvent(event, 0);
5683        }
5684
5685        return onTrackballEvent(event);
5686    }
5687
5688    /**
5689     * Dispatch a generic motion event.
5690     * <p>
5691     * Generic motion events with source class {@link InputDevice#SOURCE_CLASS_POINTER}
5692     * are delivered to the view under the pointer.  All other generic motion events are
5693     * delivered to the focused view.  Hover events are handled specially and are delivered
5694     * to {@link #onHoverEvent(MotionEvent)}.
5695     * </p>
5696     *
5697     * @param event The motion event to be dispatched.
5698     * @return True if the event was handled by the view, false otherwise.
5699     */
5700    public boolean dispatchGenericMotionEvent(MotionEvent event) {
5701        if (mInputEventConsistencyVerifier != null) {
5702            mInputEventConsistencyVerifier.onGenericMotionEvent(event, 0);
5703        }
5704
5705        final int source = event.getSource();
5706        if ((source & InputDevice.SOURCE_CLASS_POINTER) != 0) {
5707            final int action = event.getAction();
5708            if (action == MotionEvent.ACTION_HOVER_ENTER
5709                    || action == MotionEvent.ACTION_HOVER_MOVE
5710                    || action == MotionEvent.ACTION_HOVER_EXIT) {
5711                if (dispatchHoverEvent(event)) {
5712                    return true;
5713                }
5714            } else if (dispatchGenericPointerEvent(event)) {
5715                return true;
5716            }
5717        } else if (dispatchGenericFocusedEvent(event)) {
5718            return true;
5719        }
5720
5721        if (dispatchGenericMotionEventInternal(event)) {
5722            return true;
5723        }
5724
5725        if (mInputEventConsistencyVerifier != null) {
5726            mInputEventConsistencyVerifier.onUnhandledEvent(event, 0);
5727        }
5728        return false;
5729    }
5730
5731    private boolean dispatchGenericMotionEventInternal(MotionEvent event) {
5732        //noinspection SimplifiableIfStatement
5733        ListenerInfo li = mListenerInfo;
5734        if (li != null && li.mOnGenericMotionListener != null
5735                && (mViewFlags & ENABLED_MASK) == ENABLED
5736                && li.mOnGenericMotionListener.onGenericMotion(this, event)) {
5737            return true;
5738        }
5739
5740        if (onGenericMotionEvent(event)) {
5741            return true;
5742        }
5743
5744        if (mInputEventConsistencyVerifier != null) {
5745            mInputEventConsistencyVerifier.onUnhandledEvent(event, 0);
5746        }
5747        return false;
5748    }
5749
5750    /**
5751     * Dispatch a hover event.
5752     * <p>
5753     * Do not call this method directly.
5754     * Call {@link #dispatchGenericMotionEvent(MotionEvent)} instead.
5755     * </p>
5756     *
5757     * @param event The motion event to be dispatched.
5758     * @return True if the event was handled by the view, false otherwise.
5759     */
5760    protected boolean dispatchHoverEvent(MotionEvent event) {
5761        //noinspection SimplifiableIfStatement
5762        ListenerInfo li = mListenerInfo;
5763        if (li != null && li.mOnHoverListener != null
5764                && (mViewFlags & ENABLED_MASK) == ENABLED
5765                && li.mOnHoverListener.onHover(this, event)) {
5766            return true;
5767        }
5768
5769        return onHoverEvent(event);
5770    }
5771
5772    /**
5773     * Returns true if the view has a child to which it has recently sent
5774     * {@link MotionEvent#ACTION_HOVER_ENTER}.  If this view is hovered and
5775     * it does not have a hovered child, then it must be the innermost hovered view.
5776     * @hide
5777     */
5778    protected boolean hasHoveredChild() {
5779        return false;
5780    }
5781
5782    /**
5783     * Dispatch a generic motion event to the view under the first pointer.
5784     * <p>
5785     * Do not call this method directly.
5786     * Call {@link #dispatchGenericMotionEvent(MotionEvent)} instead.
5787     * </p>
5788     *
5789     * @param event The motion event to be dispatched.
5790     * @return True if the event was handled by the view, false otherwise.
5791     */
5792    protected boolean dispatchGenericPointerEvent(MotionEvent event) {
5793        return false;
5794    }
5795
5796    /**
5797     * Dispatch a generic motion event to the currently focused view.
5798     * <p>
5799     * Do not call this method directly.
5800     * Call {@link #dispatchGenericMotionEvent(MotionEvent)} instead.
5801     * </p>
5802     *
5803     * @param event The motion event to be dispatched.
5804     * @return True if the event was handled by the view, false otherwise.
5805     */
5806    protected boolean dispatchGenericFocusedEvent(MotionEvent event) {
5807        return false;
5808    }
5809
5810    /**
5811     * Dispatch a pointer event.
5812     * <p>
5813     * Dispatches touch related pointer events to {@link #onTouchEvent(MotionEvent)} and all
5814     * other events to {@link #onGenericMotionEvent(MotionEvent)}.  This separation of concerns
5815     * reinforces the invariant that {@link #onTouchEvent(MotionEvent)} is really about touches
5816     * and should not be expected to handle other pointing device features.
5817     * </p>
5818     *
5819     * @param event The motion event to be dispatched.
5820     * @return True if the event was handled by the view, false otherwise.
5821     * @hide
5822     */
5823    public final boolean dispatchPointerEvent(MotionEvent event) {
5824        if (event.isTouchEvent()) {
5825            return dispatchTouchEvent(event);
5826        } else {
5827            return dispatchGenericMotionEvent(event);
5828        }
5829    }
5830
5831    /**
5832     * Called when the window containing this view gains or loses window focus.
5833     * ViewGroups should override to route to their children.
5834     *
5835     * @param hasFocus True if the window containing this view now has focus,
5836     *        false otherwise.
5837     */
5838    public void dispatchWindowFocusChanged(boolean hasFocus) {
5839        onWindowFocusChanged(hasFocus);
5840    }
5841
5842    /**
5843     * Called when the window containing this view gains or loses focus.  Note
5844     * that this is separate from view focus: to receive key events, both
5845     * your view and its window must have focus.  If a window is displayed
5846     * on top of yours that takes input focus, then your own window will lose
5847     * focus but the view focus will remain unchanged.
5848     *
5849     * @param hasWindowFocus True if the window containing this view now has
5850     *        focus, false otherwise.
5851     */
5852    public void onWindowFocusChanged(boolean hasWindowFocus) {
5853        InputMethodManager imm = InputMethodManager.peekInstance();
5854        if (!hasWindowFocus) {
5855            if (isPressed()) {
5856                setPressed(false);
5857            }
5858            if (imm != null && (mPrivateFlags & FOCUSED) != 0) {
5859                imm.focusOut(this);
5860            }
5861            removeLongPressCallback();
5862            removeTapCallback();
5863            onFocusLost();
5864        } else if (imm != null && (mPrivateFlags & FOCUSED) != 0) {
5865            imm.focusIn(this);
5866        }
5867        refreshDrawableState();
5868    }
5869
5870    /**
5871     * Returns true if this view is in a window that currently has window focus.
5872     * Note that this is not the same as the view itself having focus.
5873     *
5874     * @return True if this view is in a window that currently has window focus.
5875     */
5876    public boolean hasWindowFocus() {
5877        return mAttachInfo != null && mAttachInfo.mHasWindowFocus;
5878    }
5879
5880    /**
5881     * Dispatch a view visibility change down the view hierarchy.
5882     * ViewGroups should override to route to their children.
5883     * @param changedView The view whose visibility changed. Could be 'this' or
5884     * an ancestor view.
5885     * @param visibility The new visibility of changedView: {@link #VISIBLE},
5886     * {@link #INVISIBLE} or {@link #GONE}.
5887     */
5888    protected void dispatchVisibilityChanged(View changedView, int visibility) {
5889        onVisibilityChanged(changedView, visibility);
5890    }
5891
5892    /**
5893     * Called when the visibility of the view or an ancestor of the view is changed.
5894     * @param changedView The view whose visibility changed. Could be 'this' or
5895     * an ancestor view.
5896     * @param visibility The new visibility of changedView: {@link #VISIBLE},
5897     * {@link #INVISIBLE} or {@link #GONE}.
5898     */
5899    protected void onVisibilityChanged(View changedView, int visibility) {
5900        if (visibility == VISIBLE) {
5901            if (mAttachInfo != null) {
5902                initialAwakenScrollBars();
5903            } else {
5904                mPrivateFlags |= AWAKEN_SCROLL_BARS_ON_ATTACH;
5905            }
5906        }
5907    }
5908
5909    /**
5910     * Dispatch a hint about whether this view is displayed. For instance, when
5911     * a View moves out of the screen, it might receives a display hint indicating
5912     * the view is not displayed. Applications should not <em>rely</em> on this hint
5913     * as there is no guarantee that they will receive one.
5914     *
5915     * @param hint A hint about whether or not this view is displayed:
5916     * {@link #VISIBLE} or {@link #INVISIBLE}.
5917     */
5918    public void dispatchDisplayHint(int hint) {
5919        onDisplayHint(hint);
5920    }
5921
5922    /**
5923     * Gives this view a hint about whether is displayed or not. For instance, when
5924     * a View moves out of the screen, it might receives a display hint indicating
5925     * the view is not displayed. Applications should not <em>rely</em> on this hint
5926     * as there is no guarantee that they will receive one.
5927     *
5928     * @param hint A hint about whether or not this view is displayed:
5929     * {@link #VISIBLE} or {@link #INVISIBLE}.
5930     */
5931    protected void onDisplayHint(int hint) {
5932    }
5933
5934    /**
5935     * Dispatch a window visibility change down the view hierarchy.
5936     * ViewGroups should override to route to their children.
5937     *
5938     * @param visibility The new visibility of the window.
5939     *
5940     * @see #onWindowVisibilityChanged(int)
5941     */
5942    public void dispatchWindowVisibilityChanged(int visibility) {
5943        onWindowVisibilityChanged(visibility);
5944    }
5945
5946    /**
5947     * Called when the window containing has change its visibility
5948     * (between {@link #GONE}, {@link #INVISIBLE}, and {@link #VISIBLE}).  Note
5949     * that this tells you whether or not your window is being made visible
5950     * to the window manager; this does <em>not</em> tell you whether or not
5951     * your window is obscured by other windows on the screen, even if it
5952     * is itself visible.
5953     *
5954     * @param visibility The new visibility of the window.
5955     */
5956    protected void onWindowVisibilityChanged(int visibility) {
5957        if (visibility == VISIBLE) {
5958            initialAwakenScrollBars();
5959        }
5960    }
5961
5962    /**
5963     * Returns the current visibility of the window this view is attached to
5964     * (either {@link #GONE}, {@link #INVISIBLE}, or {@link #VISIBLE}).
5965     *
5966     * @return Returns the current visibility of the view's window.
5967     */
5968    public int getWindowVisibility() {
5969        return mAttachInfo != null ? mAttachInfo.mWindowVisibility : GONE;
5970    }
5971
5972    /**
5973     * Retrieve the overall visible display size in which the window this view is
5974     * attached to has been positioned in.  This takes into account screen
5975     * decorations above the window, for both cases where the window itself
5976     * is being position inside of them or the window is being placed under
5977     * then and covered insets are used for the window to position its content
5978     * inside.  In effect, this tells you the available area where content can
5979     * be placed and remain visible to users.
5980     *
5981     * <p>This function requires an IPC back to the window manager to retrieve
5982     * the requested information, so should not be used in performance critical
5983     * code like drawing.
5984     *
5985     * @param outRect Filled in with the visible display frame.  If the view
5986     * is not attached to a window, this is simply the raw display size.
5987     */
5988    public void getWindowVisibleDisplayFrame(Rect outRect) {
5989        if (mAttachInfo != null) {
5990            try {
5991                mAttachInfo.mSession.getDisplayFrame(mAttachInfo.mWindow, outRect);
5992            } catch (RemoteException e) {
5993                return;
5994            }
5995            // XXX This is really broken, and probably all needs to be done
5996            // in the window manager, and we need to know more about whether
5997            // we want the area behind or in front of the IME.
5998            final Rect insets = mAttachInfo.mVisibleInsets;
5999            outRect.left += insets.left;
6000            outRect.top += insets.top;
6001            outRect.right -= insets.right;
6002            outRect.bottom -= insets.bottom;
6003            return;
6004        }
6005        Display d = WindowManagerImpl.getDefault().getDefaultDisplay();
6006        d.getRectSize(outRect);
6007    }
6008
6009    /**
6010     * Dispatch a notification about a resource configuration change down
6011     * the view hierarchy.
6012     * ViewGroups should override to route to their children.
6013     *
6014     * @param newConfig The new resource configuration.
6015     *
6016     * @see #onConfigurationChanged(android.content.res.Configuration)
6017     */
6018    public void dispatchConfigurationChanged(Configuration newConfig) {
6019        onConfigurationChanged(newConfig);
6020    }
6021
6022    /**
6023     * Called when the current configuration of the resources being used
6024     * by the application have changed.  You can use this to decide when
6025     * to reload resources that can changed based on orientation and other
6026     * configuration characterstics.  You only need to use this if you are
6027     * not relying on the normal {@link android.app.Activity} mechanism of
6028     * recreating the activity instance upon a configuration change.
6029     *
6030     * @param newConfig The new resource configuration.
6031     */
6032    protected void onConfigurationChanged(Configuration newConfig) {
6033    }
6034
6035    /**
6036     * Private function to aggregate all per-view attributes in to the view
6037     * root.
6038     */
6039    void dispatchCollectViewAttributes(int visibility) {
6040        performCollectViewAttributes(visibility);
6041    }
6042
6043    void performCollectViewAttributes(int visibility) {
6044        if ((visibility & VISIBILITY_MASK) == VISIBLE && mAttachInfo != null) {
6045            if ((mViewFlags & KEEP_SCREEN_ON) == KEEP_SCREEN_ON) {
6046                mAttachInfo.mKeepScreenOn = true;
6047            }
6048            mAttachInfo.mSystemUiVisibility |= mSystemUiVisibility;
6049            ListenerInfo li = mListenerInfo;
6050            if (li != null && li.mOnSystemUiVisibilityChangeListener != null) {
6051                mAttachInfo.mHasSystemUiListeners = true;
6052            }
6053        }
6054    }
6055
6056    void needGlobalAttributesUpdate(boolean force) {
6057        final AttachInfo ai = mAttachInfo;
6058        if (ai != null) {
6059            if (force || ai.mKeepScreenOn || (ai.mSystemUiVisibility != 0)
6060                    || ai.mHasSystemUiListeners) {
6061                ai.mRecomputeGlobalAttributes = true;
6062            }
6063        }
6064    }
6065
6066    /**
6067     * Returns whether the device is currently in touch mode.  Touch mode is entered
6068     * once the user begins interacting with the device by touch, and affects various
6069     * things like whether focus is always visible to the user.
6070     *
6071     * @return Whether the device is in touch mode.
6072     */
6073    @ViewDebug.ExportedProperty
6074    public boolean isInTouchMode() {
6075        if (mAttachInfo != null) {
6076            return mAttachInfo.mInTouchMode;
6077        } else {
6078            return ViewRootImpl.isInTouchMode();
6079        }
6080    }
6081
6082    /**
6083     * Returns the context the view is running in, through which it can
6084     * access the current theme, resources, etc.
6085     *
6086     * @return The view's Context.
6087     */
6088    @ViewDebug.CapturedViewProperty
6089    public final Context getContext() {
6090        return mContext;
6091    }
6092
6093    /**
6094     * Handle a key event before it is processed by any input method
6095     * associated with the view hierarchy.  This can be used to intercept
6096     * key events in special situations before the IME consumes them; a
6097     * typical example would be handling the BACK key to update the application's
6098     * UI instead of allowing the IME to see it and close itself.
6099     *
6100     * @param keyCode The value in event.getKeyCode().
6101     * @param event Description of the key event.
6102     * @return If you handled the event, return true. If you want to allow the
6103     *         event to be handled by the next receiver, return false.
6104     */
6105    public boolean onKeyPreIme(int keyCode, KeyEvent event) {
6106        return false;
6107    }
6108
6109    /**
6110     * Default implementation of {@link KeyEvent.Callback#onKeyDown(int, KeyEvent)
6111     * KeyEvent.Callback.onKeyDown()}: perform press of the view
6112     * when {@link KeyEvent#KEYCODE_DPAD_CENTER} or {@link KeyEvent#KEYCODE_ENTER}
6113     * is released, if the view is enabled and clickable.
6114     *
6115     * @param keyCode A key code that represents the button pressed, from
6116     *                {@link android.view.KeyEvent}.
6117     * @param event   The KeyEvent object that defines the button action.
6118     */
6119    public boolean onKeyDown(int keyCode, KeyEvent event) {
6120        boolean result = false;
6121
6122        switch (keyCode) {
6123            case KeyEvent.KEYCODE_DPAD_CENTER:
6124            case KeyEvent.KEYCODE_ENTER: {
6125                if ((mViewFlags & ENABLED_MASK) == DISABLED) {
6126                    return true;
6127                }
6128                // Long clickable items don't necessarily have to be clickable
6129                if (((mViewFlags & CLICKABLE) == CLICKABLE ||
6130                        (mViewFlags & LONG_CLICKABLE) == LONG_CLICKABLE) &&
6131                        (event.getRepeatCount() == 0)) {
6132                    setPressed(true);
6133                    checkForLongClick(0);
6134                    return true;
6135                }
6136                break;
6137            }
6138        }
6139        return result;
6140    }
6141
6142    /**
6143     * Default implementation of {@link KeyEvent.Callback#onKeyLongPress(int, KeyEvent)
6144     * KeyEvent.Callback.onKeyLongPress()}: always returns false (doesn't handle
6145     * the event).
6146     */
6147    public boolean onKeyLongPress(int keyCode, KeyEvent event) {
6148        return false;
6149    }
6150
6151    /**
6152     * Default implementation of {@link KeyEvent.Callback#onKeyUp(int, KeyEvent)
6153     * KeyEvent.Callback.onKeyUp()}: perform clicking of the view
6154     * when {@link KeyEvent#KEYCODE_DPAD_CENTER} or
6155     * {@link KeyEvent#KEYCODE_ENTER} is released.
6156     *
6157     * @param keyCode A key code that represents the button pressed, from
6158     *                {@link android.view.KeyEvent}.
6159     * @param event   The KeyEvent object that defines the button action.
6160     */
6161    public boolean onKeyUp(int keyCode, KeyEvent event) {
6162        boolean result = false;
6163
6164        switch (keyCode) {
6165            case KeyEvent.KEYCODE_DPAD_CENTER:
6166            case KeyEvent.KEYCODE_ENTER: {
6167                if ((mViewFlags & ENABLED_MASK) == DISABLED) {
6168                    return true;
6169                }
6170                if ((mViewFlags & CLICKABLE) == CLICKABLE && isPressed()) {
6171                    setPressed(false);
6172
6173                    if (!mHasPerformedLongPress) {
6174                        // This is a tap, so remove the longpress check
6175                        removeLongPressCallback();
6176
6177                        result = performClick();
6178                    }
6179                }
6180                break;
6181            }
6182        }
6183        return result;
6184    }
6185
6186    /**
6187     * Default implementation of {@link KeyEvent.Callback#onKeyMultiple(int, int, KeyEvent)
6188     * KeyEvent.Callback.onKeyMultiple()}: always returns false (doesn't handle
6189     * the event).
6190     *
6191     * @param keyCode     A key code that represents the button pressed, from
6192     *                    {@link android.view.KeyEvent}.
6193     * @param repeatCount The number of times the action was made.
6194     * @param event       The KeyEvent object that defines the button action.
6195     */
6196    public boolean onKeyMultiple(int keyCode, int repeatCount, KeyEvent event) {
6197        return false;
6198    }
6199
6200    /**
6201     * Called on the focused view when a key shortcut event is not handled.
6202     * Override this method to implement local key shortcuts for the View.
6203     * Key shortcuts can also be implemented by setting the
6204     * {@link MenuItem#setShortcut(char, char) shortcut} property of menu items.
6205     *
6206     * @param keyCode The value in event.getKeyCode().
6207     * @param event Description of the key event.
6208     * @return If you handled the event, return true. If you want to allow the
6209     *         event to be handled by the next receiver, return false.
6210     */
6211    public boolean onKeyShortcut(int keyCode, KeyEvent event) {
6212        return false;
6213    }
6214
6215    /**
6216     * Check whether the called view is a text editor, in which case it
6217     * would make sense to automatically display a soft input window for
6218     * it.  Subclasses should override this if they implement
6219     * {@link #onCreateInputConnection(EditorInfo)} to return true if
6220     * a call on that method would return a non-null InputConnection, and
6221     * they are really a first-class editor that the user would normally
6222     * start typing on when the go into a window containing your view.
6223     *
6224     * <p>The default implementation always returns false.  This does
6225     * <em>not</em> mean that its {@link #onCreateInputConnection(EditorInfo)}
6226     * will not be called or the user can not otherwise perform edits on your
6227     * view; it is just a hint to the system that this is not the primary
6228     * purpose of this view.
6229     *
6230     * @return Returns true if this view is a text editor, else false.
6231     */
6232    public boolean onCheckIsTextEditor() {
6233        return false;
6234    }
6235
6236    /**
6237     * Create a new InputConnection for an InputMethod to interact
6238     * with the view.  The default implementation returns null, since it doesn't
6239     * support input methods.  You can override this to implement such support.
6240     * This is only needed for views that take focus and text input.
6241     *
6242     * <p>When implementing this, you probably also want to implement
6243     * {@link #onCheckIsTextEditor()} to indicate you will return a
6244     * non-null InputConnection.
6245     *
6246     * @param outAttrs Fill in with attribute information about the connection.
6247     */
6248    public InputConnection onCreateInputConnection(EditorInfo outAttrs) {
6249        return null;
6250    }
6251
6252    /**
6253     * Called by the {@link android.view.inputmethod.InputMethodManager}
6254     * when a view who is not the current
6255     * input connection target is trying to make a call on the manager.  The
6256     * default implementation returns false; you can override this to return
6257     * true for certain views if you are performing InputConnection proxying
6258     * to them.
6259     * @param view The View that is making the InputMethodManager call.
6260     * @return Return true to allow the call, false to reject.
6261     */
6262    public boolean checkInputConnectionProxy(View view) {
6263        return false;
6264    }
6265
6266    /**
6267     * Show the context menu for this view. It is not safe to hold on to the
6268     * menu after returning from this method.
6269     *
6270     * You should normally not overload this method. Overload
6271     * {@link #onCreateContextMenu(ContextMenu)} or define an
6272     * {@link OnCreateContextMenuListener} to add items to the context menu.
6273     *
6274     * @param menu The context menu to populate
6275     */
6276    public void createContextMenu(ContextMenu menu) {
6277        ContextMenuInfo menuInfo = getContextMenuInfo();
6278
6279        // Sets the current menu info so all items added to menu will have
6280        // my extra info set.
6281        ((MenuBuilder)menu).setCurrentMenuInfo(menuInfo);
6282
6283        onCreateContextMenu(menu);
6284        ListenerInfo li = mListenerInfo;
6285        if (li != null && li.mOnCreateContextMenuListener != null) {
6286            li.mOnCreateContextMenuListener.onCreateContextMenu(menu, this, menuInfo);
6287        }
6288
6289        // Clear the extra information so subsequent items that aren't mine don't
6290        // have my extra info.
6291        ((MenuBuilder)menu).setCurrentMenuInfo(null);
6292
6293        if (mParent != null) {
6294            mParent.createContextMenu(menu);
6295        }
6296    }
6297
6298    /**
6299     * Views should implement this if they have extra information to associate
6300     * with the context menu. The return result is supplied as a parameter to
6301     * the {@link OnCreateContextMenuListener#onCreateContextMenu(ContextMenu, View, ContextMenuInfo)}
6302     * callback.
6303     *
6304     * @return Extra information about the item for which the context menu
6305     *         should be shown. This information will vary across different
6306     *         subclasses of View.
6307     */
6308    protected ContextMenuInfo getContextMenuInfo() {
6309        return null;
6310    }
6311
6312    /**
6313     * Views should implement this if the view itself is going to add items to
6314     * the context menu.
6315     *
6316     * @param menu the context menu to populate
6317     */
6318    protected void onCreateContextMenu(ContextMenu menu) {
6319    }
6320
6321    /**
6322     * Implement this method to handle trackball motion events.  The
6323     * <em>relative</em> movement of the trackball since the last event
6324     * can be retrieve with {@link MotionEvent#getX MotionEvent.getX()} and
6325     * {@link MotionEvent#getY MotionEvent.getY()}.  These are normalized so
6326     * that a movement of 1 corresponds to the user pressing one DPAD key (so
6327     * they will often be fractional values, representing the more fine-grained
6328     * movement information available from a trackball).
6329     *
6330     * @param event The motion event.
6331     * @return True if the event was handled, false otherwise.
6332     */
6333    public boolean onTrackballEvent(MotionEvent event) {
6334        return false;
6335    }
6336
6337    /**
6338     * Implement this method to handle generic motion events.
6339     * <p>
6340     * Generic motion events describe joystick movements, mouse hovers, track pad
6341     * touches, scroll wheel movements and other input events.  The
6342     * {@link MotionEvent#getSource() source} of the motion event specifies
6343     * the class of input that was received.  Implementations of this method
6344     * must examine the bits in the source before processing the event.
6345     * The following code example shows how this is done.
6346     * </p><p>
6347     * Generic motion events with source class {@link InputDevice#SOURCE_CLASS_POINTER}
6348     * are delivered to the view under the pointer.  All other generic motion events are
6349     * delivered to the focused view.
6350     * </p>
6351     * <pre> public boolean onGenericMotionEvent(MotionEvent event) {
6352     *     if ((event.getSource() &amp; InputDevice.SOURCE_CLASS_JOYSTICK) != 0) {
6353     *         if (event.getAction() == MotionEvent.ACTION_MOVE) {
6354     *             // process the joystick movement...
6355     *             return true;
6356     *         }
6357     *     }
6358     *     if ((event.getSource() &amp; InputDevice.SOURCE_CLASS_POINTER) != 0) {
6359     *         switch (event.getAction()) {
6360     *             case MotionEvent.ACTION_HOVER_MOVE:
6361     *                 // process the mouse hover movement...
6362     *                 return true;
6363     *             case MotionEvent.ACTION_SCROLL:
6364     *                 // process the scroll wheel movement...
6365     *                 return true;
6366     *         }
6367     *     }
6368     *     return super.onGenericMotionEvent(event);
6369     * }</pre>
6370     *
6371     * @param event The generic motion event being processed.
6372     * @return True if the event was handled, false otherwise.
6373     */
6374    public boolean onGenericMotionEvent(MotionEvent event) {
6375        return false;
6376    }
6377
6378    /**
6379     * Implement this method to handle hover events.
6380     * <p>
6381     * This method is called whenever a pointer is hovering into, over, or out of the
6382     * bounds of a view and the view is not currently being touched.
6383     * Hover events are represented as pointer events with action
6384     * {@link MotionEvent#ACTION_HOVER_ENTER}, {@link MotionEvent#ACTION_HOVER_MOVE},
6385     * or {@link MotionEvent#ACTION_HOVER_EXIT}.
6386     * </p>
6387     * <ul>
6388     * <li>The view receives a hover event with action {@link MotionEvent#ACTION_HOVER_ENTER}
6389     * when the pointer enters the bounds of the view.</li>
6390     * <li>The view receives a hover event with action {@link MotionEvent#ACTION_HOVER_MOVE}
6391     * when the pointer has already entered the bounds of the view and has moved.</li>
6392     * <li>The view receives a hover event with action {@link MotionEvent#ACTION_HOVER_EXIT}
6393     * when the pointer has exited the bounds of the view or when the pointer is
6394     * about to go down due to a button click, tap, or similar user action that
6395     * causes the view to be touched.</li>
6396     * </ul>
6397     * <p>
6398     * The view should implement this method to return true to indicate that it is
6399     * handling the hover event, such as by changing its drawable state.
6400     * </p><p>
6401     * The default implementation calls {@link #setHovered} to update the hovered state
6402     * of the view when a hover enter or hover exit event is received, if the view
6403     * is enabled and is clickable.  The default implementation also sends hover
6404     * accessibility events.
6405     * </p>
6406     *
6407     * @param event The motion event that describes the hover.
6408     * @return True if the view handled the hover event.
6409     *
6410     * @see #isHovered
6411     * @see #setHovered
6412     * @see #onHoverChanged
6413     */
6414    public boolean onHoverEvent(MotionEvent event) {
6415        // The root view may receive hover (or touch) events that are outside the bounds of
6416        // the window.  This code ensures that we only send accessibility events for
6417        // hovers that are actually within the bounds of the root view.
6418        final int action = event.getAction();
6419        if (!mSendingHoverAccessibilityEvents) {
6420            if ((action == MotionEvent.ACTION_HOVER_ENTER
6421                    || action == MotionEvent.ACTION_HOVER_MOVE)
6422                    && !hasHoveredChild()
6423                    && pointInView(event.getX(), event.getY())) {
6424                mSendingHoverAccessibilityEvents = true;
6425                sendAccessibilityEvent(AccessibilityEvent.TYPE_VIEW_HOVER_ENTER);
6426            }
6427        } else {
6428            if (action == MotionEvent.ACTION_HOVER_EXIT
6429                    || (action == MotionEvent.ACTION_HOVER_MOVE
6430                            && !pointInView(event.getX(), event.getY()))) {
6431                mSendingHoverAccessibilityEvents = false;
6432                sendAccessibilityEvent(AccessibilityEvent.TYPE_VIEW_HOVER_EXIT);
6433            }
6434        }
6435
6436        if (isHoverable()) {
6437            switch (action) {
6438                case MotionEvent.ACTION_HOVER_ENTER:
6439                    setHovered(true);
6440                    break;
6441                case MotionEvent.ACTION_HOVER_EXIT:
6442                    setHovered(false);
6443                    break;
6444            }
6445
6446            // Dispatch the event to onGenericMotionEvent before returning true.
6447            // This is to provide compatibility with existing applications that
6448            // handled HOVER_MOVE events in onGenericMotionEvent and that would
6449            // break because of the new default handling for hoverable views
6450            // in onHoverEvent.
6451            // Note that onGenericMotionEvent will be called by default when
6452            // onHoverEvent returns false (refer to dispatchGenericMotionEvent).
6453            dispatchGenericMotionEventInternal(event);
6454            return true;
6455        }
6456        return false;
6457    }
6458
6459    /**
6460     * Returns true if the view should handle {@link #onHoverEvent}
6461     * by calling {@link #setHovered} to change its hovered state.
6462     *
6463     * @return True if the view is hoverable.
6464     */
6465    private boolean isHoverable() {
6466        final int viewFlags = mViewFlags;
6467        //noinspection SimplifiableIfStatement
6468        if ((viewFlags & ENABLED_MASK) == DISABLED) {
6469            return false;
6470        }
6471
6472        return (viewFlags & CLICKABLE) == CLICKABLE
6473                || (viewFlags & LONG_CLICKABLE) == LONG_CLICKABLE;
6474    }
6475
6476    /**
6477     * Returns true if the view is currently hovered.
6478     *
6479     * @return True if the view is currently hovered.
6480     *
6481     * @see #setHovered
6482     * @see #onHoverChanged
6483     */
6484    @ViewDebug.ExportedProperty
6485    public boolean isHovered() {
6486        return (mPrivateFlags & HOVERED) != 0;
6487    }
6488
6489    /**
6490     * Sets whether the view is currently hovered.
6491     * <p>
6492     * Calling this method also changes the drawable state of the view.  This
6493     * enables the view to react to hover by using different drawable resources
6494     * to change its appearance.
6495     * </p><p>
6496     * The {@link #onHoverChanged} method is called when the hovered state changes.
6497     * </p>
6498     *
6499     * @param hovered True if the view is hovered.
6500     *
6501     * @see #isHovered
6502     * @see #onHoverChanged
6503     */
6504    public void setHovered(boolean hovered) {
6505        if (hovered) {
6506            if ((mPrivateFlags & HOVERED) == 0) {
6507                mPrivateFlags |= HOVERED;
6508                refreshDrawableState();
6509                onHoverChanged(true);
6510            }
6511        } else {
6512            if ((mPrivateFlags & HOVERED) != 0) {
6513                mPrivateFlags &= ~HOVERED;
6514                refreshDrawableState();
6515                onHoverChanged(false);
6516            }
6517        }
6518    }
6519
6520    /**
6521     * Implement this method to handle hover state changes.
6522     * <p>
6523     * This method is called whenever the hover state changes as a result of a
6524     * call to {@link #setHovered}.
6525     * </p>
6526     *
6527     * @param hovered The current hover state, as returned by {@link #isHovered}.
6528     *
6529     * @see #isHovered
6530     * @see #setHovered
6531     */
6532    public void onHoverChanged(boolean hovered) {
6533    }
6534
6535    /**
6536     * Implement this method to handle touch screen motion events.
6537     *
6538     * @param event The motion event.
6539     * @return True if the event was handled, false otherwise.
6540     */
6541    public boolean onTouchEvent(MotionEvent event) {
6542        final int viewFlags = mViewFlags;
6543
6544        if ((viewFlags & ENABLED_MASK) == DISABLED) {
6545            if (event.getAction() == MotionEvent.ACTION_UP && (mPrivateFlags & PRESSED) != 0) {
6546                setPressed(false);
6547            }
6548            // A disabled view that is clickable still consumes the touch
6549            // events, it just doesn't respond to them.
6550            return (((viewFlags & CLICKABLE) == CLICKABLE ||
6551                    (viewFlags & LONG_CLICKABLE) == LONG_CLICKABLE));
6552        }
6553
6554        if (mTouchDelegate != null) {
6555            if (mTouchDelegate.onTouchEvent(event)) {
6556                return true;
6557            }
6558        }
6559
6560        if (((viewFlags & CLICKABLE) == CLICKABLE ||
6561                (viewFlags & LONG_CLICKABLE) == LONG_CLICKABLE)) {
6562            switch (event.getAction()) {
6563                case MotionEvent.ACTION_UP:
6564                    boolean prepressed = (mPrivateFlags & PREPRESSED) != 0;
6565                    if ((mPrivateFlags & PRESSED) != 0 || prepressed) {
6566                        // take focus if we don't have it already and we should in
6567                        // touch mode.
6568                        boolean focusTaken = false;
6569                        if (isFocusable() && isFocusableInTouchMode() && !isFocused()) {
6570                            focusTaken = requestFocus();
6571                        }
6572
6573                        if (prepressed) {
6574                            // The button is being released before we actually
6575                            // showed it as pressed.  Make it show the pressed
6576                            // state now (before scheduling the click) to ensure
6577                            // the user sees it.
6578                            setPressed(true);
6579                       }
6580
6581                        if (!mHasPerformedLongPress) {
6582                            // This is a tap, so remove the longpress check
6583                            removeLongPressCallback();
6584
6585                            // Only perform take click actions if we were in the pressed state
6586                            if (!focusTaken) {
6587                                // Use a Runnable and post this rather than calling
6588                                // performClick directly. This lets other visual state
6589                                // of the view update before click actions start.
6590                                if (mPerformClick == null) {
6591                                    mPerformClick = new PerformClick();
6592                                }
6593                                if (!post(mPerformClick)) {
6594                                    performClick();
6595                                }
6596                            }
6597                        }
6598
6599                        if (mUnsetPressedState == null) {
6600                            mUnsetPressedState = new UnsetPressedState();
6601                        }
6602
6603                        if (prepressed) {
6604                            postDelayed(mUnsetPressedState,
6605                                    ViewConfiguration.getPressedStateDuration());
6606                        } else if (!post(mUnsetPressedState)) {
6607                            // If the post failed, unpress right now
6608                            mUnsetPressedState.run();
6609                        }
6610                        removeTapCallback();
6611                    }
6612                    break;
6613
6614                case MotionEvent.ACTION_DOWN:
6615                    mHasPerformedLongPress = false;
6616
6617                    if (performButtonActionOnTouchDown(event)) {
6618                        break;
6619                    }
6620
6621                    // Walk up the hierarchy to determine if we're inside a scrolling container.
6622                    boolean isInScrollingContainer = isInScrollingContainer();
6623
6624                    // For views inside a scrolling container, delay the pressed feedback for
6625                    // a short period in case this is a scroll.
6626                    if (isInScrollingContainer) {
6627                        mPrivateFlags |= PREPRESSED;
6628                        if (mPendingCheckForTap == null) {
6629                            mPendingCheckForTap = new CheckForTap();
6630                        }
6631                        postDelayed(mPendingCheckForTap, ViewConfiguration.getTapTimeout());
6632                    } else {
6633                        // Not inside a scrolling container, so show the feedback right away
6634                        setPressed(true);
6635                        checkForLongClick(0);
6636                    }
6637                    break;
6638
6639                case MotionEvent.ACTION_CANCEL:
6640                    setPressed(false);
6641                    removeTapCallback();
6642                    break;
6643
6644                case MotionEvent.ACTION_MOVE:
6645                    final int x = (int) event.getX();
6646                    final int y = (int) event.getY();
6647
6648                    // Be lenient about moving outside of buttons
6649                    if (!pointInView(x, y, mTouchSlop)) {
6650                        // Outside button
6651                        removeTapCallback();
6652                        if ((mPrivateFlags & PRESSED) != 0) {
6653                            // Remove any future long press/tap checks
6654                            removeLongPressCallback();
6655
6656                            setPressed(false);
6657                        }
6658                    }
6659                    break;
6660            }
6661            return true;
6662        }
6663
6664        return false;
6665    }
6666
6667    /**
6668     * @hide
6669     */
6670    public boolean isInScrollingContainer() {
6671        ViewParent p = getParent();
6672        while (p != null && p instanceof ViewGroup) {
6673            if (((ViewGroup) p).shouldDelayChildPressedState()) {
6674                return true;
6675            }
6676            p = p.getParent();
6677        }
6678        return false;
6679    }
6680
6681    /**
6682     * Remove the longpress detection timer.
6683     */
6684    private void removeLongPressCallback() {
6685        if (mPendingCheckForLongPress != null) {
6686          removeCallbacks(mPendingCheckForLongPress);
6687        }
6688    }
6689
6690    /**
6691     * Remove the pending click action
6692     */
6693    private void removePerformClickCallback() {
6694        if (mPerformClick != null) {
6695            removeCallbacks(mPerformClick);
6696        }
6697    }
6698
6699    /**
6700     * Remove the prepress detection timer.
6701     */
6702    private void removeUnsetPressCallback() {
6703        if ((mPrivateFlags & PRESSED) != 0 && mUnsetPressedState != null) {
6704            setPressed(false);
6705            removeCallbacks(mUnsetPressedState);
6706        }
6707    }
6708
6709    /**
6710     * Remove the tap detection timer.
6711     */
6712    private void removeTapCallback() {
6713        if (mPendingCheckForTap != null) {
6714            mPrivateFlags &= ~PREPRESSED;
6715            removeCallbacks(mPendingCheckForTap);
6716        }
6717    }
6718
6719    /**
6720     * Cancels a pending long press.  Your subclass can use this if you
6721     * want the context menu to come up if the user presses and holds
6722     * at the same place, but you don't want it to come up if they press
6723     * and then move around enough to cause scrolling.
6724     */
6725    public void cancelLongPress() {
6726        removeLongPressCallback();
6727
6728        /*
6729         * The prepressed state handled by the tap callback is a display
6730         * construct, but the tap callback will post a long press callback
6731         * less its own timeout. Remove it here.
6732         */
6733        removeTapCallback();
6734    }
6735
6736    /**
6737     * Remove the pending callback for sending a
6738     * {@link AccessibilityEvent#TYPE_VIEW_SCROLLED} accessibility event.
6739     */
6740    private void removeSendViewScrolledAccessibilityEventCallback() {
6741        if (mSendViewScrolledAccessibilityEvent != null) {
6742            removeCallbacks(mSendViewScrolledAccessibilityEvent);
6743        }
6744    }
6745
6746    /**
6747     * Sets the TouchDelegate for this View.
6748     */
6749    public void setTouchDelegate(TouchDelegate delegate) {
6750        mTouchDelegate = delegate;
6751    }
6752
6753    /**
6754     * Gets the TouchDelegate for this View.
6755     */
6756    public TouchDelegate getTouchDelegate() {
6757        return mTouchDelegate;
6758    }
6759
6760    /**
6761     * Set flags controlling behavior of this view.
6762     *
6763     * @param flags Constant indicating the value which should be set
6764     * @param mask Constant indicating the bit range that should be changed
6765     */
6766    void setFlags(int flags, int mask) {
6767        int old = mViewFlags;
6768        mViewFlags = (mViewFlags & ~mask) | (flags & mask);
6769
6770        int changed = mViewFlags ^ old;
6771        if (changed == 0) {
6772            return;
6773        }
6774        int privateFlags = mPrivateFlags;
6775
6776        /* Check if the FOCUSABLE bit has changed */
6777        if (((changed & FOCUSABLE_MASK) != 0) &&
6778                ((privateFlags & HAS_BOUNDS) !=0)) {
6779            if (((old & FOCUSABLE_MASK) == FOCUSABLE)
6780                    && ((privateFlags & FOCUSED) != 0)) {
6781                /* Give up focus if we are no longer focusable */
6782                clearFocus();
6783            } else if (((old & FOCUSABLE_MASK) == NOT_FOCUSABLE)
6784                    && ((privateFlags & FOCUSED) == 0)) {
6785                /*
6786                 * Tell the view system that we are now available to take focus
6787                 * if no one else already has it.
6788                 */
6789                if (mParent != null) mParent.focusableViewAvailable(this);
6790            }
6791        }
6792
6793        if ((flags & VISIBILITY_MASK) == VISIBLE) {
6794            if ((changed & VISIBILITY_MASK) != 0) {
6795                /*
6796                 * If this view is becoming visible, invalidate it in case it changed while
6797                 * it was not visible. Marking it drawn ensures that the invalidation will
6798                 * go through.
6799                 */
6800                mPrivateFlags |= DRAWN;
6801                invalidate(true);
6802
6803                needGlobalAttributesUpdate(true);
6804
6805                // a view becoming visible is worth notifying the parent
6806                // about in case nothing has focus.  even if this specific view
6807                // isn't focusable, it may contain something that is, so let
6808                // the root view try to give this focus if nothing else does.
6809                if ((mParent != null) && (mBottom > mTop) && (mRight > mLeft)) {
6810                    mParent.focusableViewAvailable(this);
6811                }
6812            }
6813        }
6814
6815        /* Check if the GONE bit has changed */
6816        if ((changed & GONE) != 0) {
6817            needGlobalAttributesUpdate(false);
6818            requestLayout();
6819
6820            if (((mViewFlags & VISIBILITY_MASK) == GONE)) {
6821                if (hasFocus()) clearFocus();
6822                destroyDrawingCache();
6823                if (mParent instanceof View) {
6824                    // GONE views noop invalidation, so invalidate the parent
6825                    ((View) mParent).invalidate(true);
6826                }
6827                // Mark the view drawn to ensure that it gets invalidated properly the next
6828                // time it is visible and gets invalidated
6829                mPrivateFlags |= DRAWN;
6830            }
6831            if (mAttachInfo != null) {
6832                mAttachInfo.mViewVisibilityChanged = true;
6833            }
6834        }
6835
6836        /* Check if the VISIBLE bit has changed */
6837        if ((changed & INVISIBLE) != 0) {
6838            needGlobalAttributesUpdate(false);
6839            /*
6840             * If this view is becoming invisible, set the DRAWN flag so that
6841             * the next invalidate() will not be skipped.
6842             */
6843            mPrivateFlags |= DRAWN;
6844
6845            if (((mViewFlags & VISIBILITY_MASK) == INVISIBLE) && hasFocus()) {
6846                // root view becoming invisible shouldn't clear focus
6847                if (getRootView() != this) {
6848                    clearFocus();
6849                }
6850            }
6851            if (mAttachInfo != null) {
6852                mAttachInfo.mViewVisibilityChanged = true;
6853            }
6854        }
6855
6856        if ((changed & VISIBILITY_MASK) != 0) {
6857            if (mParent instanceof ViewGroup) {
6858                ((ViewGroup) mParent).onChildVisibilityChanged(this,
6859                        (changed & VISIBILITY_MASK), (flags & VISIBILITY_MASK));
6860                ((View) mParent).invalidate(true);
6861            } else if (mParent != null) {
6862                mParent.invalidateChild(this, null);
6863            }
6864            dispatchVisibilityChanged(this, (flags & VISIBILITY_MASK));
6865        }
6866
6867        if ((changed & WILL_NOT_CACHE_DRAWING) != 0) {
6868            destroyDrawingCache();
6869        }
6870
6871        if ((changed & DRAWING_CACHE_ENABLED) != 0) {
6872            destroyDrawingCache();
6873            mPrivateFlags &= ~DRAWING_CACHE_VALID;
6874            invalidateParentCaches();
6875        }
6876
6877        if ((changed & DRAWING_CACHE_QUALITY_MASK) != 0) {
6878            destroyDrawingCache();
6879            mPrivateFlags &= ~DRAWING_CACHE_VALID;
6880        }
6881
6882        if ((changed & DRAW_MASK) != 0) {
6883            if ((mViewFlags & WILL_NOT_DRAW) != 0) {
6884                if (mBGDrawable != null) {
6885                    mPrivateFlags &= ~SKIP_DRAW;
6886                    mPrivateFlags |= ONLY_DRAWS_BACKGROUND;
6887                } else {
6888                    mPrivateFlags |= SKIP_DRAW;
6889                }
6890            } else {
6891                mPrivateFlags &= ~SKIP_DRAW;
6892            }
6893            requestLayout();
6894            invalidate(true);
6895        }
6896
6897        if ((changed & KEEP_SCREEN_ON) != 0) {
6898            if (mParent != null && mAttachInfo != null && !mAttachInfo.mRecomputeGlobalAttributes) {
6899                mParent.recomputeViewAttributes(this);
6900            }
6901        }
6902
6903        if ((changed & LAYOUT_DIRECTION_MASK) != 0) {
6904            requestLayout();
6905        }
6906    }
6907
6908    /**
6909     * Change the view's z order in the tree, so it's on top of other sibling
6910     * views
6911     */
6912    public void bringToFront() {
6913        if (mParent != null) {
6914            mParent.bringChildToFront(this);
6915        }
6916    }
6917
6918    /**
6919     * This is called in response to an internal scroll in this view (i.e., the
6920     * view scrolled its own contents). This is typically as a result of
6921     * {@link #scrollBy(int, int)} or {@link #scrollTo(int, int)} having been
6922     * called.
6923     *
6924     * @param l Current horizontal scroll origin.
6925     * @param t Current vertical scroll origin.
6926     * @param oldl Previous horizontal scroll origin.
6927     * @param oldt Previous vertical scroll origin.
6928     */
6929    protected void onScrollChanged(int l, int t, int oldl, int oldt) {
6930        if (AccessibilityManager.getInstance(mContext).isEnabled()) {
6931            postSendViewScrolledAccessibilityEventCallback();
6932        }
6933
6934        mBackgroundSizeChanged = true;
6935
6936        final AttachInfo ai = mAttachInfo;
6937        if (ai != null) {
6938            ai.mViewScrollChanged = true;
6939        }
6940    }
6941
6942    /**
6943     * Interface definition for a callback to be invoked when the layout bounds of a view
6944     * changes due to layout processing.
6945     */
6946    public interface OnLayoutChangeListener {
6947        /**
6948         * Called when the focus state of a view has changed.
6949         *
6950         * @param v The view whose state has changed.
6951         * @param left The new value of the view's left property.
6952         * @param top The new value of the view's top property.
6953         * @param right The new value of the view's right property.
6954         * @param bottom The new value of the view's bottom property.
6955         * @param oldLeft The previous value of the view's left property.
6956         * @param oldTop The previous value of the view's top property.
6957         * @param oldRight The previous value of the view's right property.
6958         * @param oldBottom The previous value of the view's bottom property.
6959         */
6960        void onLayoutChange(View v, int left, int top, int right, int bottom,
6961            int oldLeft, int oldTop, int oldRight, int oldBottom);
6962    }
6963
6964    /**
6965     * This is called during layout when the size of this view has changed. If
6966     * you were just added to the view hierarchy, you're called with the old
6967     * values of 0.
6968     *
6969     * @param w Current width of this view.
6970     * @param h Current height of this view.
6971     * @param oldw Old width of this view.
6972     * @param oldh Old height of this view.
6973     */
6974    protected void onSizeChanged(int w, int h, int oldw, int oldh) {
6975    }
6976
6977    /**
6978     * Called by draw to draw the child views. This may be overridden
6979     * by derived classes to gain control just before its children are drawn
6980     * (but after its own view has been drawn).
6981     * @param canvas the canvas on which to draw the view
6982     */
6983    protected void dispatchDraw(Canvas canvas) {
6984    }
6985
6986    /**
6987     * Gets the parent of this view. Note that the parent is a
6988     * ViewParent and not necessarily a View.
6989     *
6990     * @return Parent of this view.
6991     */
6992    public final ViewParent getParent() {
6993        return mParent;
6994    }
6995
6996    /**
6997     * Set the horizontal scrolled position of your view. This will cause a call to
6998     * {@link #onScrollChanged(int, int, int, int)} and the view will be
6999     * invalidated.
7000     * @param value the x position to scroll to
7001     */
7002    public void setScrollX(int value) {
7003        scrollTo(value, mScrollY);
7004    }
7005
7006    /**
7007     * Set the vertical scrolled position of your view. This will cause a call to
7008     * {@link #onScrollChanged(int, int, int, int)} and the view will be
7009     * invalidated.
7010     * @param value the y position to scroll to
7011     */
7012    public void setScrollY(int value) {
7013        scrollTo(mScrollX, value);
7014    }
7015
7016    /**
7017     * Return the scrolled left position of this view. This is the left edge of
7018     * the displayed part of your view. You do not need to draw any pixels
7019     * farther left, since those are outside of the frame of your view on
7020     * screen.
7021     *
7022     * @return The left edge of the displayed part of your view, in pixels.
7023     */
7024    public final int getScrollX() {
7025        return mScrollX;
7026    }
7027
7028    /**
7029     * Return the scrolled top position of this view. This is the top edge of
7030     * the displayed part of your view. You do not need to draw any pixels above
7031     * it, since those are outside of the frame of your view on screen.
7032     *
7033     * @return The top edge of the displayed part of your view, in pixels.
7034     */
7035    public final int getScrollY() {
7036        return mScrollY;
7037    }
7038
7039    /**
7040     * Return the width of the your view.
7041     *
7042     * @return The width of your view, in pixels.
7043     */
7044    @ViewDebug.ExportedProperty(category = "layout")
7045    public final int getWidth() {
7046        return mRight - mLeft;
7047    }
7048
7049    /**
7050     * Return the height of your view.
7051     *
7052     * @return The height of your view, in pixels.
7053     */
7054    @ViewDebug.ExportedProperty(category = "layout")
7055    public final int getHeight() {
7056        return mBottom - mTop;
7057    }
7058
7059    /**
7060     * Return the visible drawing bounds of your view. Fills in the output
7061     * rectangle with the values from getScrollX(), getScrollY(),
7062     * getWidth(), and getHeight().
7063     *
7064     * @param outRect The (scrolled) drawing bounds of the view.
7065     */
7066    public void getDrawingRect(Rect outRect) {
7067        outRect.left = mScrollX;
7068        outRect.top = mScrollY;
7069        outRect.right = mScrollX + (mRight - mLeft);
7070        outRect.bottom = mScrollY + (mBottom - mTop);
7071    }
7072
7073    /**
7074     * Like {@link #getMeasuredWidthAndState()}, but only returns the
7075     * raw width component (that is the result is masked by
7076     * {@link #MEASURED_SIZE_MASK}).
7077     *
7078     * @return The raw measured width of this view.
7079     */
7080    public final int getMeasuredWidth() {
7081        return mMeasuredWidth & MEASURED_SIZE_MASK;
7082    }
7083
7084    /**
7085     * Return the full width measurement information for this view as computed
7086     * by the most recent call to {@link #measure(int, int)}.  This result is a bit mask
7087     * as defined by {@link #MEASURED_SIZE_MASK} and {@link #MEASURED_STATE_TOO_SMALL}.
7088     * This should be used during measurement and layout calculations only. Use
7089     * {@link #getWidth()} to see how wide a view is after layout.
7090     *
7091     * @return The measured width of this view as a bit mask.
7092     */
7093    public final int getMeasuredWidthAndState() {
7094        return mMeasuredWidth;
7095    }
7096
7097    /**
7098     * Like {@link #getMeasuredHeightAndState()}, but only returns the
7099     * raw width component (that is the result is masked by
7100     * {@link #MEASURED_SIZE_MASK}).
7101     *
7102     * @return The raw measured height of this view.
7103     */
7104    public final int getMeasuredHeight() {
7105        return mMeasuredHeight & MEASURED_SIZE_MASK;
7106    }
7107
7108    /**
7109     * Return the full height measurement information for this view as computed
7110     * by the most recent call to {@link #measure(int, int)}.  This result is a bit mask
7111     * as defined by {@link #MEASURED_SIZE_MASK} and {@link #MEASURED_STATE_TOO_SMALL}.
7112     * This should be used during measurement and layout calculations only. Use
7113     * {@link #getHeight()} to see how wide a view is after layout.
7114     *
7115     * @return The measured width of this view as a bit mask.
7116     */
7117    public final int getMeasuredHeightAndState() {
7118        return mMeasuredHeight;
7119    }
7120
7121    /**
7122     * Return only the state bits of {@link #getMeasuredWidthAndState()}
7123     * and {@link #getMeasuredHeightAndState()}, combined into one integer.
7124     * The width component is in the regular bits {@link #MEASURED_STATE_MASK}
7125     * and the height component is at the shifted bits
7126     * {@link #MEASURED_HEIGHT_STATE_SHIFT}>>{@link #MEASURED_STATE_MASK}.
7127     */
7128    public final int getMeasuredState() {
7129        return (mMeasuredWidth&MEASURED_STATE_MASK)
7130                | ((mMeasuredHeight>>MEASURED_HEIGHT_STATE_SHIFT)
7131                        & (MEASURED_STATE_MASK>>MEASURED_HEIGHT_STATE_SHIFT));
7132    }
7133
7134    /**
7135     * The transform matrix of this view, which is calculated based on the current
7136     * roation, scale, and pivot properties.
7137     *
7138     * @see #getRotation()
7139     * @see #getScaleX()
7140     * @see #getScaleY()
7141     * @see #getPivotX()
7142     * @see #getPivotY()
7143     * @return The current transform matrix for the view
7144     */
7145    public Matrix getMatrix() {
7146        if (mTransformationInfo != null) {
7147            updateMatrix();
7148            return mTransformationInfo.mMatrix;
7149        }
7150        return Matrix.IDENTITY_MATRIX;
7151    }
7152
7153    /**
7154     * Utility function to determine if the value is far enough away from zero to be
7155     * considered non-zero.
7156     * @param value A floating point value to check for zero-ness
7157     * @return whether the passed-in value is far enough away from zero to be considered non-zero
7158     */
7159    private static boolean nonzero(float value) {
7160        return (value < -NONZERO_EPSILON || value > NONZERO_EPSILON);
7161    }
7162
7163    /**
7164     * Returns true if the transform matrix is the identity matrix.
7165     * Recomputes the matrix if necessary.
7166     *
7167     * @return True if the transform matrix is the identity matrix, false otherwise.
7168     */
7169    final boolean hasIdentityMatrix() {
7170        if (mTransformationInfo != null) {
7171            updateMatrix();
7172            return mTransformationInfo.mMatrixIsIdentity;
7173        }
7174        return true;
7175    }
7176
7177    void ensureTransformationInfo() {
7178        if (mTransformationInfo == null) {
7179            mTransformationInfo = new TransformationInfo();
7180        }
7181    }
7182
7183    /**
7184     * Recomputes the transform matrix if necessary.
7185     */
7186    private void updateMatrix() {
7187        final TransformationInfo info = mTransformationInfo;
7188        if (info == null) {
7189            return;
7190        }
7191        if (info.mMatrixDirty) {
7192            // transform-related properties have changed since the last time someone
7193            // asked for the matrix; recalculate it with the current values
7194
7195            // Figure out if we need to update the pivot point
7196            if ((mPrivateFlags & PIVOT_EXPLICITLY_SET) == 0) {
7197                if ((mRight - mLeft) != info.mPrevWidth || (mBottom - mTop) != info.mPrevHeight) {
7198                    info.mPrevWidth = mRight - mLeft;
7199                    info.mPrevHeight = mBottom - mTop;
7200                    info.mPivotX = info.mPrevWidth / 2f;
7201                    info.mPivotY = info.mPrevHeight / 2f;
7202                }
7203            }
7204            info.mMatrix.reset();
7205            if (!nonzero(info.mRotationX) && !nonzero(info.mRotationY)) {
7206                info.mMatrix.setTranslate(info.mTranslationX, info.mTranslationY);
7207                info.mMatrix.preRotate(info.mRotation, info.mPivotX, info.mPivotY);
7208                info.mMatrix.preScale(info.mScaleX, info.mScaleY, info.mPivotX, info.mPivotY);
7209            } else {
7210                if (info.mCamera == null) {
7211                    info.mCamera = new Camera();
7212                    info.matrix3D = new Matrix();
7213                }
7214                info.mCamera.save();
7215                info.mMatrix.preScale(info.mScaleX, info.mScaleY, info.mPivotX, info.mPivotY);
7216                info.mCamera.rotate(info.mRotationX, info.mRotationY, -info.mRotation);
7217                info.mCamera.getMatrix(info.matrix3D);
7218                info.matrix3D.preTranslate(-info.mPivotX, -info.mPivotY);
7219                info.matrix3D.postTranslate(info.mPivotX + info.mTranslationX,
7220                        info.mPivotY + info.mTranslationY);
7221                info.mMatrix.postConcat(info.matrix3D);
7222                info.mCamera.restore();
7223            }
7224            info.mMatrixDirty = false;
7225            info.mMatrixIsIdentity = info.mMatrix.isIdentity();
7226            info.mInverseMatrixDirty = true;
7227        }
7228    }
7229
7230    /**
7231     * Utility method to retrieve the inverse of the current mMatrix property.
7232     * We cache the matrix to avoid recalculating it when transform properties
7233     * have not changed.
7234     *
7235     * @return The inverse of the current matrix of this view.
7236     */
7237    final Matrix getInverseMatrix() {
7238        final TransformationInfo info = mTransformationInfo;
7239        if (info != null) {
7240            updateMatrix();
7241            if (info.mInverseMatrixDirty) {
7242                if (info.mInverseMatrix == null) {
7243                    info.mInverseMatrix = new Matrix();
7244                }
7245                info.mMatrix.invert(info.mInverseMatrix);
7246                info.mInverseMatrixDirty = false;
7247            }
7248            return info.mInverseMatrix;
7249        }
7250        return Matrix.IDENTITY_MATRIX;
7251    }
7252
7253    /**
7254     * <p>Sets the distance along the Z axis (orthogonal to the X/Y plane on which
7255     * views are drawn) from the camera to this view. The camera's distance
7256     * affects 3D transformations, for instance rotations around the X and Y
7257     * axis. If the rotationX or rotationY properties are changed and this view is
7258     * large (more than half the size of the screen), it is recommended to always
7259     * use a camera distance that's greater than the height (X axis rotation) or
7260     * the width (Y axis rotation) of this view.</p>
7261     *
7262     * <p>The distance of the camera from the view plane can have an affect on the
7263     * perspective distortion of the view when it is rotated around the x or y axis.
7264     * For example, a large distance will result in a large viewing angle, and there
7265     * will not be much perspective distortion of the view as it rotates. A short
7266     * distance may cause much more perspective distortion upon rotation, and can
7267     * also result in some drawing artifacts if the rotated view ends up partially
7268     * behind the camera (which is why the recommendation is to use a distance at
7269     * least as far as the size of the view, if the view is to be rotated.)</p>
7270     *
7271     * <p>The distance is expressed in "depth pixels." The default distance depends
7272     * on the screen density. For instance, on a medium density display, the
7273     * default distance is 1280. On a high density display, the default distance
7274     * is 1920.</p>
7275     *
7276     * <p>If you want to specify a distance that leads to visually consistent
7277     * results across various densities, use the following formula:</p>
7278     * <pre>
7279     * float scale = context.getResources().getDisplayMetrics().density;
7280     * view.setCameraDistance(distance * scale);
7281     * </pre>
7282     *
7283     * <p>The density scale factor of a high density display is 1.5,
7284     * and 1920 = 1280 * 1.5.</p>
7285     *
7286     * @param distance The distance in "depth pixels", if negative the opposite
7287     *        value is used
7288     *
7289     * @see #setRotationX(float)
7290     * @see #setRotationY(float)
7291     */
7292    public void setCameraDistance(float distance) {
7293        invalidateParentCaches();
7294        invalidate(false);
7295
7296        ensureTransformationInfo();
7297        final float dpi = mResources.getDisplayMetrics().densityDpi;
7298        final TransformationInfo info = mTransformationInfo;
7299        if (info.mCamera == null) {
7300            info.mCamera = new Camera();
7301            info.matrix3D = new Matrix();
7302        }
7303
7304        info.mCamera.setLocation(0.0f, 0.0f, -Math.abs(distance) / dpi);
7305        info.mMatrixDirty = true;
7306
7307        invalidate(false);
7308    }
7309
7310    /**
7311     * The degrees that the view is rotated around the pivot point.
7312     *
7313     * @see #setRotation(float)
7314     * @see #getPivotX()
7315     * @see #getPivotY()
7316     *
7317     * @return The degrees of rotation.
7318     */
7319    @ViewDebug.ExportedProperty(category = "drawing")
7320    public float getRotation() {
7321        return mTransformationInfo != null ? mTransformationInfo.mRotation : 0;
7322    }
7323
7324    /**
7325     * Sets the degrees that the view is rotated around the pivot point. Increasing values
7326     * result in clockwise rotation.
7327     *
7328     * @param rotation The degrees of rotation.
7329     *
7330     * @see #getRotation()
7331     * @see #getPivotX()
7332     * @see #getPivotY()
7333     * @see #setRotationX(float)
7334     * @see #setRotationY(float)
7335     *
7336     * @attr ref android.R.styleable#View_rotation
7337     */
7338    public void setRotation(float rotation) {
7339        ensureTransformationInfo();
7340        final TransformationInfo info = mTransformationInfo;
7341        if (info.mRotation != rotation) {
7342            invalidateParentCaches();
7343            // Double-invalidation is necessary to capture view's old and new areas
7344            invalidate(false);
7345            info.mRotation = rotation;
7346            info.mMatrixDirty = true;
7347            mPrivateFlags |= DRAWN; // force another invalidation with the new orientation
7348            invalidate(false);
7349        }
7350    }
7351
7352    /**
7353     * The degrees that the view is rotated around the vertical axis through the pivot point.
7354     *
7355     * @see #getPivotX()
7356     * @see #getPivotY()
7357     * @see #setRotationY(float)
7358     *
7359     * @return The degrees of Y rotation.
7360     */
7361    @ViewDebug.ExportedProperty(category = "drawing")
7362    public float getRotationY() {
7363        return mTransformationInfo != null ? mTransformationInfo.mRotationY : 0;
7364    }
7365
7366    /**
7367     * Sets the degrees that the view is rotated around the vertical axis through the pivot point.
7368     * Increasing values result in counter-clockwise rotation from the viewpoint of looking
7369     * down the y axis.
7370     *
7371     * When rotating large views, it is recommended to adjust the camera distance
7372     * accordingly. Refer to {@link #setCameraDistance(float)} for more information.
7373     *
7374     * @param rotationY The degrees of Y rotation.
7375     *
7376     * @see #getRotationY()
7377     * @see #getPivotX()
7378     * @see #getPivotY()
7379     * @see #setRotation(float)
7380     * @see #setRotationX(float)
7381     * @see #setCameraDistance(float)
7382     *
7383     * @attr ref android.R.styleable#View_rotationY
7384     */
7385    public void setRotationY(float rotationY) {
7386        ensureTransformationInfo();
7387        final TransformationInfo info = mTransformationInfo;
7388        if (info.mRotationY != rotationY) {
7389            invalidateParentCaches();
7390            // Double-invalidation is necessary to capture view's old and new areas
7391            invalidate(false);
7392            info.mRotationY = rotationY;
7393            info.mMatrixDirty = true;
7394            mPrivateFlags |= DRAWN; // force another invalidation with the new orientation
7395            invalidate(false);
7396        }
7397    }
7398
7399    /**
7400     * The degrees that the view is rotated around the horizontal axis through the pivot point.
7401     *
7402     * @see #getPivotX()
7403     * @see #getPivotY()
7404     * @see #setRotationX(float)
7405     *
7406     * @return The degrees of X rotation.
7407     */
7408    @ViewDebug.ExportedProperty(category = "drawing")
7409    public float getRotationX() {
7410        return mTransformationInfo != null ? mTransformationInfo.mRotationX : 0;
7411    }
7412
7413    /**
7414     * Sets the degrees that the view is rotated around the horizontal axis through the pivot point.
7415     * Increasing values result in clockwise rotation from the viewpoint of looking down the
7416     * x axis.
7417     *
7418     * When rotating large views, it is recommended to adjust the camera distance
7419     * accordingly. Refer to {@link #setCameraDistance(float)} for more information.
7420     *
7421     * @param rotationX The degrees of X rotation.
7422     *
7423     * @see #getRotationX()
7424     * @see #getPivotX()
7425     * @see #getPivotY()
7426     * @see #setRotation(float)
7427     * @see #setRotationY(float)
7428     * @see #setCameraDistance(float)
7429     *
7430     * @attr ref android.R.styleable#View_rotationX
7431     */
7432    public void setRotationX(float rotationX) {
7433        ensureTransformationInfo();
7434        final TransformationInfo info = mTransformationInfo;
7435        if (info.mRotationX != rotationX) {
7436            invalidateParentCaches();
7437            // Double-invalidation is necessary to capture view's old and new areas
7438            invalidate(false);
7439            info.mRotationX = rotationX;
7440            info.mMatrixDirty = true;
7441            mPrivateFlags |= DRAWN; // force another invalidation with the new orientation
7442            invalidate(false);
7443        }
7444    }
7445
7446    /**
7447     * The amount that the view is scaled in x around the pivot point, as a proportion of
7448     * the view's unscaled width. A value of 1, the default, means that no scaling is applied.
7449     *
7450     * <p>By default, this is 1.0f.
7451     *
7452     * @see #getPivotX()
7453     * @see #getPivotY()
7454     * @return The scaling factor.
7455     */
7456    @ViewDebug.ExportedProperty(category = "drawing")
7457    public float getScaleX() {
7458        return mTransformationInfo != null ? mTransformationInfo.mScaleX : 1;
7459    }
7460
7461    /**
7462     * Sets the amount that the view is scaled in x around the pivot point, as a proportion of
7463     * the view's unscaled width. A value of 1 means that no scaling is applied.
7464     *
7465     * @param scaleX The scaling factor.
7466     * @see #getPivotX()
7467     * @see #getPivotY()
7468     *
7469     * @attr ref android.R.styleable#View_scaleX
7470     */
7471    public void setScaleX(float scaleX) {
7472        ensureTransformationInfo();
7473        final TransformationInfo info = mTransformationInfo;
7474        if (info.mScaleX != scaleX) {
7475            invalidateParentCaches();
7476            // Double-invalidation is necessary to capture view's old and new areas
7477            invalidate(false);
7478            info.mScaleX = scaleX;
7479            info.mMatrixDirty = true;
7480            mPrivateFlags |= DRAWN; // force another invalidation with the new orientation
7481            invalidate(false);
7482        }
7483    }
7484
7485    /**
7486     * The amount that the view is scaled in y around the pivot point, as a proportion of
7487     * the view's unscaled height. A value of 1, the default, means that no scaling is applied.
7488     *
7489     * <p>By default, this is 1.0f.
7490     *
7491     * @see #getPivotX()
7492     * @see #getPivotY()
7493     * @return The scaling factor.
7494     */
7495    @ViewDebug.ExportedProperty(category = "drawing")
7496    public float getScaleY() {
7497        return mTransformationInfo != null ? mTransformationInfo.mScaleY : 1;
7498    }
7499
7500    /**
7501     * Sets the amount that the view is scaled in Y around the pivot point, as a proportion of
7502     * the view's unscaled width. A value of 1 means that no scaling is applied.
7503     *
7504     * @param scaleY The scaling factor.
7505     * @see #getPivotX()
7506     * @see #getPivotY()
7507     *
7508     * @attr ref android.R.styleable#View_scaleY
7509     */
7510    public void setScaleY(float scaleY) {
7511        ensureTransformationInfo();
7512        final TransformationInfo info = mTransformationInfo;
7513        if (info.mScaleY != scaleY) {
7514            invalidateParentCaches();
7515            // Double-invalidation is necessary to capture view's old and new areas
7516            invalidate(false);
7517            info.mScaleY = scaleY;
7518            info.mMatrixDirty = true;
7519            mPrivateFlags |= DRAWN; // force another invalidation with the new orientation
7520            invalidate(false);
7521        }
7522    }
7523
7524    /**
7525     * The x location of the point around which the view is {@link #setRotation(float) rotated}
7526     * and {@link #setScaleX(float) scaled}.
7527     *
7528     * @see #getRotation()
7529     * @see #getScaleX()
7530     * @see #getScaleY()
7531     * @see #getPivotY()
7532     * @return The x location of the pivot point.
7533     */
7534    @ViewDebug.ExportedProperty(category = "drawing")
7535    public float getPivotX() {
7536        return mTransformationInfo != null ? mTransformationInfo.mPivotX : 0;
7537    }
7538
7539    /**
7540     * Sets the x location of the point around which the view is
7541     * {@link #setRotation(float) rotated} and {@link #setScaleX(float) scaled}.
7542     * By default, the pivot point is centered on the object.
7543     * Setting this property disables this behavior and causes the view to use only the
7544     * explicitly set pivotX and pivotY values.
7545     *
7546     * @param pivotX The x location of the pivot point.
7547     * @see #getRotation()
7548     * @see #getScaleX()
7549     * @see #getScaleY()
7550     * @see #getPivotY()
7551     *
7552     * @attr ref android.R.styleable#View_transformPivotX
7553     */
7554    public void setPivotX(float pivotX) {
7555        ensureTransformationInfo();
7556        mPrivateFlags |= PIVOT_EXPLICITLY_SET;
7557        final TransformationInfo info = mTransformationInfo;
7558        if (info.mPivotX != pivotX) {
7559            invalidateParentCaches();
7560            // Double-invalidation is necessary to capture view's old and new areas
7561            invalidate(false);
7562            info.mPivotX = pivotX;
7563            info.mMatrixDirty = true;
7564            mPrivateFlags |= DRAWN; // force another invalidation with the new orientation
7565            invalidate(false);
7566        }
7567    }
7568
7569    /**
7570     * The y location of the point around which the view is {@link #setRotation(float) rotated}
7571     * and {@link #setScaleY(float) scaled}.
7572     *
7573     * @see #getRotation()
7574     * @see #getScaleX()
7575     * @see #getScaleY()
7576     * @see #getPivotY()
7577     * @return The y location of the pivot point.
7578     */
7579    @ViewDebug.ExportedProperty(category = "drawing")
7580    public float getPivotY() {
7581        return mTransformationInfo != null ? mTransformationInfo.mPivotY : 0;
7582    }
7583
7584    /**
7585     * Sets the y location of the point around which the view is {@link #setRotation(float) rotated}
7586     * and {@link #setScaleY(float) scaled}. By default, the pivot point is centered on the object.
7587     * Setting this property disables this behavior and causes the view to use only the
7588     * explicitly set pivotX and pivotY values.
7589     *
7590     * @param pivotY The y location of the pivot point.
7591     * @see #getRotation()
7592     * @see #getScaleX()
7593     * @see #getScaleY()
7594     * @see #getPivotY()
7595     *
7596     * @attr ref android.R.styleable#View_transformPivotY
7597     */
7598    public void setPivotY(float pivotY) {
7599        ensureTransformationInfo();
7600        mPrivateFlags |= PIVOT_EXPLICITLY_SET;
7601        final TransformationInfo info = mTransformationInfo;
7602        if (info.mPivotY != pivotY) {
7603            invalidateParentCaches();
7604            // Double-invalidation is necessary to capture view's old and new areas
7605            invalidate(false);
7606            info.mPivotY = pivotY;
7607            info.mMatrixDirty = true;
7608            mPrivateFlags |= DRAWN; // force another invalidation with the new orientation
7609            invalidate(false);
7610        }
7611    }
7612
7613    /**
7614     * The opacity of the view. This is a value from 0 to 1, where 0 means the view is
7615     * completely transparent and 1 means the view is completely opaque.
7616     *
7617     * <p>By default this is 1.0f.
7618     * @return The opacity of the view.
7619     */
7620    @ViewDebug.ExportedProperty(category = "drawing")
7621    public float getAlpha() {
7622        return mTransformationInfo != null ? mTransformationInfo.mAlpha : 1;
7623    }
7624
7625    /**
7626     * <p>Sets the opacity of the view. This is a value from 0 to 1, where 0 means the view is
7627     * completely transparent and 1 means the view is completely opaque.</p>
7628     *
7629     * <p>If this view overrides {@link #onSetAlpha(int)} to return true, then this view is
7630     * responsible for applying the opacity itself. Otherwise, calling this method is
7631     * equivalent to calling {@link #setLayerType(int, android.graphics.Paint)} and
7632     * setting a hardware layer.</p>
7633     *
7634     * <p>Note that setting alpha to a translucent value (0 < alpha < 1) may have
7635     * performance implications. It is generally best to use the alpha property sparingly and
7636     * transiently, as in the case of fading animations.</p>
7637     *
7638     * @param alpha The opacity of the view.
7639     *
7640     * @see #setLayerType(int, android.graphics.Paint)
7641     *
7642     * @attr ref android.R.styleable#View_alpha
7643     */
7644    public void setAlpha(float alpha) {
7645        ensureTransformationInfo();
7646        if (mTransformationInfo.mAlpha != alpha) {
7647            mTransformationInfo.mAlpha = alpha;
7648            invalidateParentCaches();
7649            if (onSetAlpha((int) (alpha * 255))) {
7650                mPrivateFlags |= ALPHA_SET;
7651                // subclass is handling alpha - don't optimize rendering cache invalidation
7652                invalidate(true);
7653            } else {
7654                mPrivateFlags &= ~ALPHA_SET;
7655                invalidate(false);
7656            }
7657        }
7658    }
7659
7660    /**
7661     * Faster version of setAlpha() which performs the same steps except there are
7662     * no calls to invalidate(). The caller of this function should perform proper invalidation
7663     * on the parent and this object. The return value indicates whether the subclass handles
7664     * alpha (the return value for onSetAlpha()).
7665     *
7666     * @param alpha The new value for the alpha property
7667     * @return true if the View subclass handles alpha (the return value for onSetAlpha()) and
7668     *         the new value for the alpha property is different from the old value
7669     */
7670    boolean setAlphaNoInvalidation(float alpha) {
7671        ensureTransformationInfo();
7672        if (mTransformationInfo.mAlpha != alpha) {
7673            mTransformationInfo.mAlpha = alpha;
7674            boolean subclassHandlesAlpha = onSetAlpha((int) (alpha * 255));
7675            if (subclassHandlesAlpha) {
7676                mPrivateFlags |= ALPHA_SET;
7677                return true;
7678            } else {
7679                mPrivateFlags &= ~ALPHA_SET;
7680            }
7681        }
7682        return false;
7683    }
7684
7685    /**
7686     * Top position of this view relative to its parent.
7687     *
7688     * @return The top of this view, in pixels.
7689     */
7690    @ViewDebug.CapturedViewProperty
7691    public final int getTop() {
7692        return mTop;
7693    }
7694
7695    /**
7696     * Sets the top position of this view relative to its parent. This method is meant to be called
7697     * by the layout system and should not generally be called otherwise, because the property
7698     * may be changed at any time by the layout.
7699     *
7700     * @param top The top of this view, in pixels.
7701     */
7702    public final void setTop(int top) {
7703        if (top != mTop) {
7704            updateMatrix();
7705            final boolean matrixIsIdentity = mTransformationInfo == null
7706                    || mTransformationInfo.mMatrixIsIdentity;
7707            if (matrixIsIdentity) {
7708                if (mAttachInfo != null) {
7709                    int minTop;
7710                    int yLoc;
7711                    if (top < mTop) {
7712                        minTop = top;
7713                        yLoc = top - mTop;
7714                    } else {
7715                        minTop = mTop;
7716                        yLoc = 0;
7717                    }
7718                    invalidate(0, yLoc, mRight - mLeft, mBottom - minTop);
7719                }
7720            } else {
7721                // Double-invalidation is necessary to capture view's old and new areas
7722                invalidate(true);
7723            }
7724
7725            int width = mRight - mLeft;
7726            int oldHeight = mBottom - mTop;
7727
7728            mTop = top;
7729
7730            onSizeChanged(width, mBottom - mTop, width, oldHeight);
7731
7732            if (!matrixIsIdentity) {
7733                if ((mPrivateFlags & PIVOT_EXPLICITLY_SET) == 0) {
7734                    // A change in dimension means an auto-centered pivot point changes, too
7735                    mTransformationInfo.mMatrixDirty = true;
7736                }
7737                mPrivateFlags |= DRAWN; // force another invalidation with the new orientation
7738                invalidate(true);
7739            }
7740            mBackgroundSizeChanged = true;
7741            invalidateParentIfNeeded();
7742        }
7743    }
7744
7745    /**
7746     * Bottom position of this view relative to its parent.
7747     *
7748     * @return The bottom of this view, in pixels.
7749     */
7750    @ViewDebug.CapturedViewProperty
7751    public final int getBottom() {
7752        return mBottom;
7753    }
7754
7755    /**
7756     * True if this view has changed since the last time being drawn.
7757     *
7758     * @return The dirty state of this view.
7759     */
7760    public boolean isDirty() {
7761        return (mPrivateFlags & DIRTY_MASK) != 0;
7762    }
7763
7764    /**
7765     * Sets the bottom position of this view relative to its parent. This method is meant to be
7766     * called by the layout system and should not generally be called otherwise, because the
7767     * property may be changed at any time by the layout.
7768     *
7769     * @param bottom The bottom of this view, in pixels.
7770     */
7771    public final void setBottom(int bottom) {
7772        if (bottom != mBottom) {
7773            updateMatrix();
7774            final boolean matrixIsIdentity = mTransformationInfo == null
7775                    || mTransformationInfo.mMatrixIsIdentity;
7776            if (matrixIsIdentity) {
7777                if (mAttachInfo != null) {
7778                    int maxBottom;
7779                    if (bottom < mBottom) {
7780                        maxBottom = mBottom;
7781                    } else {
7782                        maxBottom = bottom;
7783                    }
7784                    invalidate(0, 0, mRight - mLeft, maxBottom - mTop);
7785                }
7786            } else {
7787                // Double-invalidation is necessary to capture view's old and new areas
7788                invalidate(true);
7789            }
7790
7791            int width = mRight - mLeft;
7792            int oldHeight = mBottom - mTop;
7793
7794            mBottom = bottom;
7795
7796            onSizeChanged(width, mBottom - mTop, width, oldHeight);
7797
7798            if (!matrixIsIdentity) {
7799                if ((mPrivateFlags & PIVOT_EXPLICITLY_SET) == 0) {
7800                    // A change in dimension means an auto-centered pivot point changes, too
7801                    mTransformationInfo.mMatrixDirty = true;
7802                }
7803                mPrivateFlags |= DRAWN; // force another invalidation with the new orientation
7804                invalidate(true);
7805            }
7806            mBackgroundSizeChanged = true;
7807            invalidateParentIfNeeded();
7808        }
7809    }
7810
7811    /**
7812     * Left position of this view relative to its parent.
7813     *
7814     * @return The left edge of this view, in pixels.
7815     */
7816    @ViewDebug.CapturedViewProperty
7817    public final int getLeft() {
7818        return mLeft;
7819    }
7820
7821    /**
7822     * Sets the left position of this view relative to its parent. This method is meant to be called
7823     * by the layout system and should not generally be called otherwise, because the property
7824     * may be changed at any time by the layout.
7825     *
7826     * @param left The bottom of this view, in pixels.
7827     */
7828    public final void setLeft(int left) {
7829        if (left != mLeft) {
7830            updateMatrix();
7831            final boolean matrixIsIdentity = mTransformationInfo == null
7832                    || mTransformationInfo.mMatrixIsIdentity;
7833            if (matrixIsIdentity) {
7834                if (mAttachInfo != null) {
7835                    int minLeft;
7836                    int xLoc;
7837                    if (left < mLeft) {
7838                        minLeft = left;
7839                        xLoc = left - mLeft;
7840                    } else {
7841                        minLeft = mLeft;
7842                        xLoc = 0;
7843                    }
7844                    invalidate(xLoc, 0, mRight - minLeft, mBottom - mTop);
7845                }
7846            } else {
7847                // Double-invalidation is necessary to capture view's old and new areas
7848                invalidate(true);
7849            }
7850
7851            int oldWidth = mRight - mLeft;
7852            int height = mBottom - mTop;
7853
7854            mLeft = left;
7855
7856            onSizeChanged(mRight - mLeft, height, oldWidth, height);
7857
7858            if (!matrixIsIdentity) {
7859                if ((mPrivateFlags & PIVOT_EXPLICITLY_SET) == 0) {
7860                    // A change in dimension means an auto-centered pivot point changes, too
7861                    mTransformationInfo.mMatrixDirty = true;
7862                }
7863                mPrivateFlags |= DRAWN; // force another invalidation with the new orientation
7864                invalidate(true);
7865            }
7866            mBackgroundSizeChanged = true;
7867            invalidateParentIfNeeded();
7868        }
7869    }
7870
7871    /**
7872     * Right position of this view relative to its parent.
7873     *
7874     * @return The right edge of this view, in pixels.
7875     */
7876    @ViewDebug.CapturedViewProperty
7877    public final int getRight() {
7878        return mRight;
7879    }
7880
7881    /**
7882     * Sets the right position of this view relative to its parent. This method is meant to be called
7883     * by the layout system and should not generally be called otherwise, because the property
7884     * may be changed at any time by the layout.
7885     *
7886     * @param right The bottom of this view, in pixels.
7887     */
7888    public final void setRight(int right) {
7889        if (right != mRight) {
7890            updateMatrix();
7891            final boolean matrixIsIdentity = mTransformationInfo == null
7892                    || mTransformationInfo.mMatrixIsIdentity;
7893            if (matrixIsIdentity) {
7894                if (mAttachInfo != null) {
7895                    int maxRight;
7896                    if (right < mRight) {
7897                        maxRight = mRight;
7898                    } else {
7899                        maxRight = right;
7900                    }
7901                    invalidate(0, 0, maxRight - mLeft, mBottom - mTop);
7902                }
7903            } else {
7904                // Double-invalidation is necessary to capture view's old and new areas
7905                invalidate(true);
7906            }
7907
7908            int oldWidth = mRight - mLeft;
7909            int height = mBottom - mTop;
7910
7911            mRight = right;
7912
7913            onSizeChanged(mRight - mLeft, height, oldWidth, height);
7914
7915            if (!matrixIsIdentity) {
7916                if ((mPrivateFlags & PIVOT_EXPLICITLY_SET) == 0) {
7917                    // A change in dimension means an auto-centered pivot point changes, too
7918                    mTransformationInfo.mMatrixDirty = true;
7919                }
7920                mPrivateFlags |= DRAWN; // force another invalidation with the new orientation
7921                invalidate(true);
7922            }
7923            mBackgroundSizeChanged = true;
7924            invalidateParentIfNeeded();
7925        }
7926    }
7927
7928    /**
7929     * The visual x position of this view, in pixels. This is equivalent to the
7930     * {@link #setTranslationX(float) translationX} property plus the current
7931     * {@link #getLeft() left} property.
7932     *
7933     * @return The visual x position of this view, in pixels.
7934     */
7935    @ViewDebug.ExportedProperty(category = "drawing")
7936    public float getX() {
7937        return mLeft + (mTransformationInfo != null ? mTransformationInfo.mTranslationX : 0);
7938    }
7939
7940    /**
7941     * Sets the visual x position of this view, in pixels. This is equivalent to setting the
7942     * {@link #setTranslationX(float) translationX} property to be the difference between
7943     * the x value passed in and the current {@link #getLeft() left} property.
7944     *
7945     * @param x The visual x position of this view, in pixels.
7946     */
7947    public void setX(float x) {
7948        setTranslationX(x - mLeft);
7949    }
7950
7951    /**
7952     * The visual y position of this view, in pixels. This is equivalent to the
7953     * {@link #setTranslationY(float) translationY} property plus the current
7954     * {@link #getTop() top} property.
7955     *
7956     * @return The visual y position of this view, in pixels.
7957     */
7958    @ViewDebug.ExportedProperty(category = "drawing")
7959    public float getY() {
7960        return mTop + (mTransformationInfo != null ? mTransformationInfo.mTranslationY : 0);
7961    }
7962
7963    /**
7964     * Sets the visual y position of this view, in pixels. This is equivalent to setting the
7965     * {@link #setTranslationY(float) translationY} property to be the difference between
7966     * the y value passed in and the current {@link #getTop() top} property.
7967     *
7968     * @param y The visual y position of this view, in pixels.
7969     */
7970    public void setY(float y) {
7971        setTranslationY(y - mTop);
7972    }
7973
7974
7975    /**
7976     * The horizontal location of this view relative to its {@link #getLeft() left} position.
7977     * This position is post-layout, in addition to wherever the object's
7978     * layout placed it.
7979     *
7980     * @return The horizontal position of this view relative to its left position, in pixels.
7981     */
7982    @ViewDebug.ExportedProperty(category = "drawing")
7983    public float getTranslationX() {
7984        return mTransformationInfo != null ? mTransformationInfo.mTranslationX : 0;
7985    }
7986
7987    /**
7988     * Sets the horizontal location of this view relative to its {@link #getLeft() left} position.
7989     * This effectively positions the object post-layout, in addition to wherever the object's
7990     * layout placed it.
7991     *
7992     * @param translationX The horizontal position of this view relative to its left position,
7993     * in pixels.
7994     *
7995     * @attr ref android.R.styleable#View_translationX
7996     */
7997    public void setTranslationX(float translationX) {
7998        ensureTransformationInfo();
7999        final TransformationInfo info = mTransformationInfo;
8000        if (info.mTranslationX != translationX) {
8001            invalidateParentCaches();
8002            // Double-invalidation is necessary to capture view's old and new areas
8003            invalidate(false);
8004            info.mTranslationX = translationX;
8005            info.mMatrixDirty = true;
8006            mPrivateFlags |= DRAWN; // force another invalidation with the new orientation
8007            invalidate(false);
8008        }
8009    }
8010
8011    /**
8012     * The horizontal location of this view relative to its {@link #getTop() top} position.
8013     * This position is post-layout, in addition to wherever the object's
8014     * layout placed it.
8015     *
8016     * @return The vertical position of this view relative to its top position,
8017     * in pixels.
8018     */
8019    @ViewDebug.ExportedProperty(category = "drawing")
8020    public float getTranslationY() {
8021        return mTransformationInfo != null ? mTransformationInfo.mTranslationY : 0;
8022    }
8023
8024    /**
8025     * Sets the vertical location of this view relative to its {@link #getTop() top} position.
8026     * This effectively positions the object post-layout, in addition to wherever the object's
8027     * layout placed it.
8028     *
8029     * @param translationY The vertical position of this view relative to its top position,
8030     * in pixels.
8031     *
8032     * @attr ref android.R.styleable#View_translationY
8033     */
8034    public void setTranslationY(float translationY) {
8035        ensureTransformationInfo();
8036        final TransformationInfo info = mTransformationInfo;
8037        if (info.mTranslationY != translationY) {
8038            invalidateParentCaches();
8039            // Double-invalidation is necessary to capture view's old and new areas
8040            invalidate(false);
8041            info.mTranslationY = translationY;
8042            info.mMatrixDirty = true;
8043            mPrivateFlags |= DRAWN; // force another invalidation with the new orientation
8044            invalidate(false);
8045        }
8046    }
8047
8048    /**
8049     * Hit rectangle in parent's coordinates
8050     *
8051     * @param outRect The hit rectangle of the view.
8052     */
8053    public void getHitRect(Rect outRect) {
8054        updateMatrix();
8055        final TransformationInfo info = mTransformationInfo;
8056        if (info == null || info.mMatrixIsIdentity || mAttachInfo == null) {
8057            outRect.set(mLeft, mTop, mRight, mBottom);
8058        } else {
8059            final RectF tmpRect = mAttachInfo.mTmpTransformRect;
8060            tmpRect.set(-info.mPivotX, -info.mPivotY,
8061                    getWidth() - info.mPivotX, getHeight() - info.mPivotY);
8062            info.mMatrix.mapRect(tmpRect);
8063            outRect.set((int) tmpRect.left + mLeft, (int) tmpRect.top + mTop,
8064                    (int) tmpRect.right + mLeft, (int) tmpRect.bottom + mTop);
8065        }
8066    }
8067
8068    /**
8069     * Determines whether the given point, in local coordinates is inside the view.
8070     */
8071    /*package*/ final boolean pointInView(float localX, float localY) {
8072        return localX >= 0 && localX < (mRight - mLeft)
8073                && localY >= 0 && localY < (mBottom - mTop);
8074    }
8075
8076    /**
8077     * Utility method to determine whether the given point, in local coordinates,
8078     * is inside the view, where the area of the view is expanded by the slop factor.
8079     * This method is called while processing touch-move events to determine if the event
8080     * is still within the view.
8081     */
8082    private boolean pointInView(float localX, float localY, float slop) {
8083        return localX >= -slop && localY >= -slop && localX < ((mRight - mLeft) + slop) &&
8084                localY < ((mBottom - mTop) + slop);
8085    }
8086
8087    /**
8088     * When a view has focus and the user navigates away from it, the next view is searched for
8089     * starting from the rectangle filled in by this method.
8090     *
8091     * By default, the rectange is the {@link #getDrawingRect(android.graphics.Rect)})
8092     * of the view.  However, if your view maintains some idea of internal selection,
8093     * such as a cursor, or a selected row or column, you should override this method and
8094     * fill in a more specific rectangle.
8095     *
8096     * @param r The rectangle to fill in, in this view's coordinates.
8097     */
8098    public void getFocusedRect(Rect r) {
8099        getDrawingRect(r);
8100    }
8101
8102    /**
8103     * If some part of this view is not clipped by any of its parents, then
8104     * return that area in r in global (root) coordinates. To convert r to local
8105     * coordinates (without taking possible View rotations into account), offset
8106     * it by -globalOffset (e.g. r.offset(-globalOffset.x, -globalOffset.y)).
8107     * If the view is completely clipped or translated out, return false.
8108     *
8109     * @param r If true is returned, r holds the global coordinates of the
8110     *        visible portion of this view.
8111     * @param globalOffset If true is returned, globalOffset holds the dx,dy
8112     *        between this view and its root. globalOffet may be null.
8113     * @return true if r is non-empty (i.e. part of the view is visible at the
8114     *         root level.
8115     */
8116    public boolean getGlobalVisibleRect(Rect r, Point globalOffset) {
8117        int width = mRight - mLeft;
8118        int height = mBottom - mTop;
8119        if (width > 0 && height > 0) {
8120            r.set(0, 0, width, height);
8121            if (globalOffset != null) {
8122                globalOffset.set(-mScrollX, -mScrollY);
8123            }
8124            return mParent == null || mParent.getChildVisibleRect(this, r, globalOffset);
8125        }
8126        return false;
8127    }
8128
8129    public final boolean getGlobalVisibleRect(Rect r) {
8130        return getGlobalVisibleRect(r, null);
8131    }
8132
8133    public final boolean getLocalVisibleRect(Rect r) {
8134        Point offset = new Point();
8135        if (getGlobalVisibleRect(r, offset)) {
8136            r.offset(-offset.x, -offset.y); // make r local
8137            return true;
8138        }
8139        return false;
8140    }
8141
8142    /**
8143     * Offset this view's vertical location by the specified number of pixels.
8144     *
8145     * @param offset the number of pixels to offset the view by
8146     */
8147    public void offsetTopAndBottom(int offset) {
8148        if (offset != 0) {
8149            updateMatrix();
8150            final boolean matrixIsIdentity = mTransformationInfo == null
8151                    || mTransformationInfo.mMatrixIsIdentity;
8152            if (matrixIsIdentity) {
8153                final ViewParent p = mParent;
8154                if (p != null && mAttachInfo != null) {
8155                    final Rect r = mAttachInfo.mTmpInvalRect;
8156                    int minTop;
8157                    int maxBottom;
8158                    int yLoc;
8159                    if (offset < 0) {
8160                        minTop = mTop + offset;
8161                        maxBottom = mBottom;
8162                        yLoc = offset;
8163                    } else {
8164                        minTop = mTop;
8165                        maxBottom = mBottom + offset;
8166                        yLoc = 0;
8167                    }
8168                    r.set(0, yLoc, mRight - mLeft, maxBottom - minTop);
8169                    p.invalidateChild(this, r);
8170                }
8171            } else {
8172                invalidate(false);
8173            }
8174
8175            mTop += offset;
8176            mBottom += offset;
8177
8178            if (!matrixIsIdentity) {
8179                mPrivateFlags |= DRAWN; // force another invalidation with the new orientation
8180                invalidate(false);
8181            }
8182            invalidateParentIfNeeded();
8183        }
8184    }
8185
8186    /**
8187     * Offset this view's horizontal location by the specified amount of pixels.
8188     *
8189     * @param offset the numer of pixels to offset the view by
8190     */
8191    public void offsetLeftAndRight(int offset) {
8192        if (offset != 0) {
8193            updateMatrix();
8194            final boolean matrixIsIdentity = mTransformationInfo == null
8195                    || mTransformationInfo.mMatrixIsIdentity;
8196            if (matrixIsIdentity) {
8197                final ViewParent p = mParent;
8198                if (p != null && mAttachInfo != null) {
8199                    final Rect r = mAttachInfo.mTmpInvalRect;
8200                    int minLeft;
8201                    int maxRight;
8202                    if (offset < 0) {
8203                        minLeft = mLeft + offset;
8204                        maxRight = mRight;
8205                    } else {
8206                        minLeft = mLeft;
8207                        maxRight = mRight + offset;
8208                    }
8209                    r.set(0, 0, maxRight - minLeft, mBottom - mTop);
8210                    p.invalidateChild(this, r);
8211                }
8212            } else {
8213                invalidate(false);
8214            }
8215
8216            mLeft += offset;
8217            mRight += offset;
8218
8219            if (!matrixIsIdentity) {
8220                mPrivateFlags |= DRAWN; // force another invalidation with the new orientation
8221                invalidate(false);
8222            }
8223            invalidateParentIfNeeded();
8224        }
8225    }
8226
8227    /**
8228     * Get the LayoutParams associated with this view. All views should have
8229     * layout parameters. These supply parameters to the <i>parent</i> of this
8230     * view specifying how it should be arranged. There are many subclasses of
8231     * ViewGroup.LayoutParams, and these correspond to the different subclasses
8232     * of ViewGroup that are responsible for arranging their children.
8233     *
8234     * This method may return null if this View is not attached to a parent
8235     * ViewGroup or {@link #setLayoutParams(android.view.ViewGroup.LayoutParams)}
8236     * was not invoked successfully. When a View is attached to a parent
8237     * ViewGroup, this method must not return null.
8238     *
8239     * @return The LayoutParams associated with this view, or null if no
8240     *         parameters have been set yet
8241     */
8242    @ViewDebug.ExportedProperty(deepExport = true, prefix = "layout_")
8243    public ViewGroup.LayoutParams getLayoutParams() {
8244        return mLayoutParams;
8245    }
8246
8247    /**
8248     * Set the layout parameters associated with this view. These supply
8249     * parameters to the <i>parent</i> of this view specifying how it should be
8250     * arranged. There are many subclasses of ViewGroup.LayoutParams, and these
8251     * correspond to the different subclasses of ViewGroup that are responsible
8252     * for arranging their children.
8253     *
8254     * @param params The layout parameters for this view, cannot be null
8255     */
8256    public void setLayoutParams(ViewGroup.LayoutParams params) {
8257        if (params == null) {
8258            throw new NullPointerException("Layout parameters cannot be null");
8259        }
8260        mLayoutParams = params;
8261        if (mParent instanceof ViewGroup) {
8262            ((ViewGroup) mParent).onSetLayoutParams(this, params);
8263        }
8264        requestLayout();
8265    }
8266
8267    /**
8268     * Set the scrolled position of your view. This will cause a call to
8269     * {@link #onScrollChanged(int, int, int, int)} and the view will be
8270     * invalidated.
8271     * @param x the x position to scroll to
8272     * @param y the y position to scroll to
8273     */
8274    public void scrollTo(int x, int y) {
8275        if (mScrollX != x || mScrollY != y) {
8276            int oldX = mScrollX;
8277            int oldY = mScrollY;
8278            mScrollX = x;
8279            mScrollY = y;
8280            invalidateParentCaches();
8281            onScrollChanged(mScrollX, mScrollY, oldX, oldY);
8282            if (!awakenScrollBars()) {
8283                invalidate(true);
8284            }
8285        }
8286    }
8287
8288    /**
8289     * Move the scrolled position of your view. This will cause a call to
8290     * {@link #onScrollChanged(int, int, int, int)} and the view will be
8291     * invalidated.
8292     * @param x the amount of pixels to scroll by horizontally
8293     * @param y the amount of pixels to scroll by vertically
8294     */
8295    public void scrollBy(int x, int y) {
8296        scrollTo(mScrollX + x, mScrollY + y);
8297    }
8298
8299    /**
8300     * <p>Trigger the scrollbars to draw. When invoked this method starts an
8301     * animation to fade the scrollbars out after a default delay. If a subclass
8302     * provides animated scrolling, the start delay should equal the duration
8303     * of the scrolling animation.</p>
8304     *
8305     * <p>The animation starts only if at least one of the scrollbars is
8306     * enabled, as specified by {@link #isHorizontalScrollBarEnabled()} and
8307     * {@link #isVerticalScrollBarEnabled()}. When the animation is started,
8308     * this method returns true, and false otherwise. If the animation is
8309     * started, this method calls {@link #invalidate()}; in that case the
8310     * caller should not call {@link #invalidate()}.</p>
8311     *
8312     * <p>This method should be invoked every time a subclass directly updates
8313     * the scroll parameters.</p>
8314     *
8315     * <p>This method is automatically invoked by {@link #scrollBy(int, int)}
8316     * and {@link #scrollTo(int, int)}.</p>
8317     *
8318     * @return true if the animation is played, false otherwise
8319     *
8320     * @see #awakenScrollBars(int)
8321     * @see #scrollBy(int, int)
8322     * @see #scrollTo(int, int)
8323     * @see #isHorizontalScrollBarEnabled()
8324     * @see #isVerticalScrollBarEnabled()
8325     * @see #setHorizontalScrollBarEnabled(boolean)
8326     * @see #setVerticalScrollBarEnabled(boolean)
8327     */
8328    protected boolean awakenScrollBars() {
8329        return mScrollCache != null &&
8330                awakenScrollBars(mScrollCache.scrollBarDefaultDelayBeforeFade, true);
8331    }
8332
8333    /**
8334     * Trigger the scrollbars to draw.
8335     * This method differs from awakenScrollBars() only in its default duration.
8336     * initialAwakenScrollBars() will show the scroll bars for longer than
8337     * usual to give the user more of a chance to notice them.
8338     *
8339     * @return true if the animation is played, false otherwise.
8340     */
8341    private boolean initialAwakenScrollBars() {
8342        return mScrollCache != null &&
8343                awakenScrollBars(mScrollCache.scrollBarDefaultDelayBeforeFade * 4, true);
8344    }
8345
8346    /**
8347     * <p>
8348     * Trigger the scrollbars to draw. When invoked this method starts an
8349     * animation to fade the scrollbars out after a fixed delay. If a subclass
8350     * provides animated scrolling, the start delay should equal the duration of
8351     * the scrolling animation.
8352     * </p>
8353     *
8354     * <p>
8355     * The animation starts only if at least one of the scrollbars is enabled,
8356     * as specified by {@link #isHorizontalScrollBarEnabled()} and
8357     * {@link #isVerticalScrollBarEnabled()}. When the animation is started,
8358     * this method returns true, and false otherwise. If the animation is
8359     * started, this method calls {@link #invalidate()}; in that case the caller
8360     * should not call {@link #invalidate()}.
8361     * </p>
8362     *
8363     * <p>
8364     * This method should be invoked everytime a subclass directly updates the
8365     * scroll parameters.
8366     * </p>
8367     *
8368     * @param startDelay the delay, in milliseconds, after which the animation
8369     *        should start; when the delay is 0, the animation starts
8370     *        immediately
8371     * @return true if the animation is played, false otherwise
8372     *
8373     * @see #scrollBy(int, int)
8374     * @see #scrollTo(int, int)
8375     * @see #isHorizontalScrollBarEnabled()
8376     * @see #isVerticalScrollBarEnabled()
8377     * @see #setHorizontalScrollBarEnabled(boolean)
8378     * @see #setVerticalScrollBarEnabled(boolean)
8379     */
8380    protected boolean awakenScrollBars(int startDelay) {
8381        return awakenScrollBars(startDelay, true);
8382    }
8383
8384    /**
8385     * <p>
8386     * Trigger the scrollbars to draw. When invoked this method starts an
8387     * animation to fade the scrollbars out after a fixed delay. If a subclass
8388     * provides animated scrolling, the start delay should equal the duration of
8389     * the scrolling animation.
8390     * </p>
8391     *
8392     * <p>
8393     * The animation starts only if at least one of the scrollbars is enabled,
8394     * as specified by {@link #isHorizontalScrollBarEnabled()} and
8395     * {@link #isVerticalScrollBarEnabled()}. When the animation is started,
8396     * this method returns true, and false otherwise. If the animation is
8397     * started, this method calls {@link #invalidate()} if the invalidate parameter
8398     * is set to true; in that case the caller
8399     * should not call {@link #invalidate()}.
8400     * </p>
8401     *
8402     * <p>
8403     * This method should be invoked everytime a subclass directly updates the
8404     * scroll parameters.
8405     * </p>
8406     *
8407     * @param startDelay the delay, in milliseconds, after which the animation
8408     *        should start; when the delay is 0, the animation starts
8409     *        immediately
8410     *
8411     * @param invalidate Wheter this method should call invalidate
8412     *
8413     * @return true if the animation is played, false otherwise
8414     *
8415     * @see #scrollBy(int, int)
8416     * @see #scrollTo(int, int)
8417     * @see #isHorizontalScrollBarEnabled()
8418     * @see #isVerticalScrollBarEnabled()
8419     * @see #setHorizontalScrollBarEnabled(boolean)
8420     * @see #setVerticalScrollBarEnabled(boolean)
8421     */
8422    protected boolean awakenScrollBars(int startDelay, boolean invalidate) {
8423        final ScrollabilityCache scrollCache = mScrollCache;
8424
8425        if (scrollCache == null || !scrollCache.fadeScrollBars) {
8426            return false;
8427        }
8428
8429        if (scrollCache.scrollBar == null) {
8430            scrollCache.scrollBar = new ScrollBarDrawable();
8431        }
8432
8433        if (isHorizontalScrollBarEnabled() || isVerticalScrollBarEnabled()) {
8434
8435            if (invalidate) {
8436                // Invalidate to show the scrollbars
8437                invalidate(true);
8438            }
8439
8440            if (scrollCache.state == ScrollabilityCache.OFF) {
8441                // FIXME: this is copied from WindowManagerService.
8442                // We should get this value from the system when it
8443                // is possible to do so.
8444                final int KEY_REPEAT_FIRST_DELAY = 750;
8445                startDelay = Math.max(KEY_REPEAT_FIRST_DELAY, startDelay);
8446            }
8447
8448            // Tell mScrollCache when we should start fading. This may
8449            // extend the fade start time if one was already scheduled
8450            long fadeStartTime = AnimationUtils.currentAnimationTimeMillis() + startDelay;
8451            scrollCache.fadeStartTime = fadeStartTime;
8452            scrollCache.state = ScrollabilityCache.ON;
8453
8454            // Schedule our fader to run, unscheduling any old ones first
8455            if (mAttachInfo != null) {
8456                mAttachInfo.mHandler.removeCallbacks(scrollCache);
8457                mAttachInfo.mHandler.postAtTime(scrollCache, fadeStartTime);
8458            }
8459
8460            return true;
8461        }
8462
8463        return false;
8464    }
8465
8466    /**
8467     * Do not invalidate views which are not visible and which are not running an animation. They
8468     * will not get drawn and they should not set dirty flags as if they will be drawn
8469     */
8470    private boolean skipInvalidate() {
8471        return (mViewFlags & VISIBILITY_MASK) != VISIBLE && mCurrentAnimation == null &&
8472                (!(mParent instanceof ViewGroup) ||
8473                        !((ViewGroup) mParent).isViewTransitioning(this));
8474    }
8475    /**
8476     * Mark the area defined by dirty as needing to be drawn. If the view is
8477     * visible, {@link #onDraw(android.graphics.Canvas)} will be called at some point
8478     * in the future. This must be called from a UI thread. To call from a non-UI
8479     * thread, call {@link #postInvalidate()}.
8480     *
8481     * WARNING: This method is destructive to dirty.
8482     * @param dirty the rectangle representing the bounds of the dirty region
8483     */
8484    public void invalidate(Rect dirty) {
8485        if (ViewDebug.TRACE_HIERARCHY) {
8486            ViewDebug.trace(this, ViewDebug.HierarchyTraceType.INVALIDATE);
8487        }
8488
8489        if (skipInvalidate()) {
8490            return;
8491        }
8492        if ((mPrivateFlags & (DRAWN | HAS_BOUNDS)) == (DRAWN | HAS_BOUNDS) ||
8493                (mPrivateFlags & DRAWING_CACHE_VALID) == DRAWING_CACHE_VALID ||
8494                (mPrivateFlags & INVALIDATED) != INVALIDATED) {
8495            mPrivateFlags &= ~DRAWING_CACHE_VALID;
8496            mPrivateFlags |= INVALIDATED;
8497            mPrivateFlags |= DIRTY;
8498            final ViewParent p = mParent;
8499            final AttachInfo ai = mAttachInfo;
8500            //noinspection PointlessBooleanExpression,ConstantConditions
8501            if (!HardwareRenderer.RENDER_DIRTY_REGIONS) {
8502                if (p != null && ai != null && ai.mHardwareAccelerated) {
8503                    // fast-track for GL-enabled applications; just invalidate the whole hierarchy
8504                    // with a null dirty rect, which tells the ViewAncestor to redraw everything
8505                    p.invalidateChild(this, null);
8506                    return;
8507                }
8508            }
8509            if (p != null && ai != null) {
8510                final int scrollX = mScrollX;
8511                final int scrollY = mScrollY;
8512                final Rect r = ai.mTmpInvalRect;
8513                r.set(dirty.left - scrollX, dirty.top - scrollY,
8514                        dirty.right - scrollX, dirty.bottom - scrollY);
8515                mParent.invalidateChild(this, r);
8516            }
8517        }
8518    }
8519
8520    /**
8521     * Mark the area defined by the rect (l,t,r,b) as needing to be drawn.
8522     * The coordinates of the dirty rect are relative to the view.
8523     * If the view is visible, {@link #onDraw(android.graphics.Canvas)}
8524     * will be called at some point in the future. This must be called from
8525     * a UI thread. To call from a non-UI thread, call {@link #postInvalidate()}.
8526     * @param l the left position of the dirty region
8527     * @param t the top position of the dirty region
8528     * @param r the right position of the dirty region
8529     * @param b the bottom position of the dirty region
8530     */
8531    public void invalidate(int l, int t, int r, int b) {
8532        if (ViewDebug.TRACE_HIERARCHY) {
8533            ViewDebug.trace(this, ViewDebug.HierarchyTraceType.INVALIDATE);
8534        }
8535
8536        if (skipInvalidate()) {
8537            return;
8538        }
8539        if ((mPrivateFlags & (DRAWN | HAS_BOUNDS)) == (DRAWN | HAS_BOUNDS) ||
8540                (mPrivateFlags & DRAWING_CACHE_VALID) == DRAWING_CACHE_VALID ||
8541                (mPrivateFlags & INVALIDATED) != INVALIDATED) {
8542            mPrivateFlags &= ~DRAWING_CACHE_VALID;
8543            mPrivateFlags |= INVALIDATED;
8544            mPrivateFlags |= DIRTY;
8545            final ViewParent p = mParent;
8546            final AttachInfo ai = mAttachInfo;
8547            //noinspection PointlessBooleanExpression,ConstantConditions
8548            if (!HardwareRenderer.RENDER_DIRTY_REGIONS) {
8549                if (p != null && ai != null && ai.mHardwareAccelerated) {
8550                    // fast-track for GL-enabled applications; just invalidate the whole hierarchy
8551                    // with a null dirty rect, which tells the ViewAncestor to redraw everything
8552                    p.invalidateChild(this, null);
8553                    return;
8554                }
8555            }
8556            if (p != null && ai != null && l < r && t < b) {
8557                final int scrollX = mScrollX;
8558                final int scrollY = mScrollY;
8559                final Rect tmpr = ai.mTmpInvalRect;
8560                tmpr.set(l - scrollX, t - scrollY, r - scrollX, b - scrollY);
8561                p.invalidateChild(this, tmpr);
8562            }
8563        }
8564    }
8565
8566    /**
8567     * Invalidate the whole view. If the view is visible,
8568     * {@link #onDraw(android.graphics.Canvas)} will be called at some point in
8569     * the future. This must be called from a UI thread. To call from a non-UI thread,
8570     * call {@link #postInvalidate()}.
8571     */
8572    public void invalidate() {
8573        invalidate(true);
8574    }
8575
8576    /**
8577     * This is where the invalidate() work actually happens. A full invalidate()
8578     * causes the drawing cache to be invalidated, but this function can be called with
8579     * invalidateCache set to false to skip that invalidation step for cases that do not
8580     * need it (for example, a component that remains at the same dimensions with the same
8581     * content).
8582     *
8583     * @param invalidateCache Whether the drawing cache for this view should be invalidated as
8584     * well. This is usually true for a full invalidate, but may be set to false if the
8585     * View's contents or dimensions have not changed.
8586     */
8587    void invalidate(boolean invalidateCache) {
8588        if (ViewDebug.TRACE_HIERARCHY) {
8589            ViewDebug.trace(this, ViewDebug.HierarchyTraceType.INVALIDATE);
8590        }
8591
8592        if (skipInvalidate()) {
8593            return;
8594        }
8595        if ((mPrivateFlags & (DRAWN | HAS_BOUNDS)) == (DRAWN | HAS_BOUNDS) ||
8596                (invalidateCache && (mPrivateFlags & DRAWING_CACHE_VALID) == DRAWING_CACHE_VALID) ||
8597                (mPrivateFlags & INVALIDATED) != INVALIDATED || isOpaque() != mLastIsOpaque) {
8598            mLastIsOpaque = isOpaque();
8599            mPrivateFlags &= ~DRAWN;
8600            mPrivateFlags |= DIRTY;
8601            if (invalidateCache) {
8602                mPrivateFlags |= INVALIDATED;
8603                mPrivateFlags &= ~DRAWING_CACHE_VALID;
8604            }
8605            final AttachInfo ai = mAttachInfo;
8606            final ViewParent p = mParent;
8607            //noinspection PointlessBooleanExpression,ConstantConditions
8608            if (!HardwareRenderer.RENDER_DIRTY_REGIONS) {
8609                if (p != null && ai != null && ai.mHardwareAccelerated) {
8610                    // fast-track for GL-enabled applications; just invalidate the whole hierarchy
8611                    // with a null dirty rect, which tells the ViewAncestor to redraw everything
8612                    p.invalidateChild(this, null);
8613                    return;
8614                }
8615            }
8616
8617            if (p != null && ai != null) {
8618                final Rect r = ai.mTmpInvalRect;
8619                r.set(0, 0, mRight - mLeft, mBottom - mTop);
8620                // Don't call invalidate -- we don't want to internally scroll
8621                // our own bounds
8622                p.invalidateChild(this, r);
8623            }
8624        }
8625    }
8626
8627    /**
8628     * Used to indicate that the parent of this view should clear its caches. This functionality
8629     * is used to force the parent to rebuild its display list (when hardware-accelerated),
8630     * which is necessary when various parent-managed properties of the view change, such as
8631     * alpha, translationX/Y, scrollX/Y, scaleX/Y, and rotation/X/Y. This method only
8632     * clears the parent caches and does not causes an invalidate event.
8633     *
8634     * @hide
8635     */
8636    protected void invalidateParentCaches() {
8637        if (mParent instanceof View) {
8638            ((View) mParent).mPrivateFlags |= INVALIDATED;
8639        }
8640    }
8641
8642    /**
8643     * Used to indicate that the parent of this view should be invalidated. This functionality
8644     * is used to force the parent to rebuild its display list (when hardware-accelerated),
8645     * which is necessary when various parent-managed properties of the view change, such as
8646     * alpha, translationX/Y, scrollX/Y, scaleX/Y, and rotation/X/Y. This method will propagate
8647     * an invalidation event to the parent.
8648     *
8649     * @hide
8650     */
8651    protected void invalidateParentIfNeeded() {
8652        if (isHardwareAccelerated() && mParent instanceof View) {
8653            ((View) mParent).invalidate(true);
8654        }
8655    }
8656
8657    /**
8658     * Indicates whether this View is opaque. An opaque View guarantees that it will
8659     * draw all the pixels overlapping its bounds using a fully opaque color.
8660     *
8661     * Subclasses of View should override this method whenever possible to indicate
8662     * whether an instance is opaque. Opaque Views are treated in a special way by
8663     * the View hierarchy, possibly allowing it to perform optimizations during
8664     * invalidate/draw passes.
8665     *
8666     * @return True if this View is guaranteed to be fully opaque, false otherwise.
8667     */
8668    @ViewDebug.ExportedProperty(category = "drawing")
8669    public boolean isOpaque() {
8670        return (mPrivateFlags & OPAQUE_MASK) == OPAQUE_MASK &&
8671                ((mTransformationInfo != null ? mTransformationInfo.mAlpha : 1)
8672                        >= 1.0f - ViewConfiguration.ALPHA_THRESHOLD);
8673    }
8674
8675    /**
8676     * @hide
8677     */
8678    protected void computeOpaqueFlags() {
8679        // Opaque if:
8680        //   - Has a background
8681        //   - Background is opaque
8682        //   - Doesn't have scrollbars or scrollbars are inside overlay
8683
8684        if (mBGDrawable != null && mBGDrawable.getOpacity() == PixelFormat.OPAQUE) {
8685            mPrivateFlags |= OPAQUE_BACKGROUND;
8686        } else {
8687            mPrivateFlags &= ~OPAQUE_BACKGROUND;
8688        }
8689
8690        final int flags = mViewFlags;
8691        if (((flags & SCROLLBARS_VERTICAL) == 0 && (flags & SCROLLBARS_HORIZONTAL) == 0) ||
8692                (flags & SCROLLBARS_STYLE_MASK) == SCROLLBARS_INSIDE_OVERLAY) {
8693            mPrivateFlags |= OPAQUE_SCROLLBARS;
8694        } else {
8695            mPrivateFlags &= ~OPAQUE_SCROLLBARS;
8696        }
8697    }
8698
8699    /**
8700     * @hide
8701     */
8702    protected boolean hasOpaqueScrollbars() {
8703        return (mPrivateFlags & OPAQUE_SCROLLBARS) == OPAQUE_SCROLLBARS;
8704    }
8705
8706    /**
8707     * @return A handler associated with the thread running the View. This
8708     * handler can be used to pump events in the UI events queue.
8709     */
8710    public Handler getHandler() {
8711        if (mAttachInfo != null) {
8712            return mAttachInfo.mHandler;
8713        }
8714        return null;
8715    }
8716
8717    /**
8718     * Gets the view root associated with the View.
8719     * @return The view root, or null if none.
8720     * @hide
8721     */
8722    public ViewRootImpl getViewRootImpl() {
8723        if (mAttachInfo != null) {
8724            return mAttachInfo.mViewRootImpl;
8725        }
8726        return null;
8727    }
8728
8729    /**
8730     * <p>Causes the Runnable to be added to the message queue.
8731     * The runnable will be run on the user interface thread.</p>
8732     *
8733     * <p>This method can be invoked from outside of the UI thread
8734     * only when this View is attached to a window.</p>
8735     *
8736     * @param action The Runnable that will be executed.
8737     *
8738     * @return Returns true if the Runnable was successfully placed in to the
8739     *         message queue.  Returns false on failure, usually because the
8740     *         looper processing the message queue is exiting.
8741     */
8742    public boolean post(Runnable action) {
8743        final AttachInfo attachInfo = mAttachInfo;
8744        if (attachInfo != null) {
8745            return attachInfo.mHandler.post(action);
8746        }
8747        // Assume that post will succeed later
8748        ViewRootImpl.getRunQueue().post(action);
8749        return true;
8750    }
8751
8752    /**
8753     * <p>Causes the Runnable to be added to the message queue, to be run
8754     * after the specified amount of time elapses.
8755     * The runnable will be run on the user interface thread.</p>
8756     *
8757     * <p>This method can be invoked from outside of the UI thread
8758     * only when this View is attached to a window.</p>
8759     *
8760     * @param action The Runnable that will be executed.
8761     * @param delayMillis The delay (in milliseconds) until the Runnable
8762     *        will be executed.
8763     *
8764     * @return true if the Runnable was successfully placed in to the
8765     *         message queue.  Returns false on failure, usually because the
8766     *         looper processing the message queue is exiting.  Note that a
8767     *         result of true does not mean the Runnable will be processed --
8768     *         if the looper is quit before the delivery time of the message
8769     *         occurs then the message will be dropped.
8770     */
8771    public boolean postDelayed(Runnable action, long delayMillis) {
8772        final AttachInfo attachInfo = mAttachInfo;
8773        if (attachInfo != null) {
8774            return attachInfo.mHandler.postDelayed(action, delayMillis);
8775        }
8776        // Assume that post will succeed later
8777        ViewRootImpl.getRunQueue().postDelayed(action, delayMillis);
8778        return true;
8779    }
8780
8781    /**
8782     * <p>Removes the specified Runnable from the message queue.</p>
8783     *
8784     * <p>This method can be invoked from outside of the UI thread
8785     * only when this View is attached to a window.</p>
8786     *
8787     * @param action The Runnable to remove from the message handling queue
8788     *
8789     * @return true if this view could ask the Handler to remove the Runnable,
8790     *         false otherwise. When the returned value is true, the Runnable
8791     *         may or may not have been actually removed from the message queue
8792     *         (for instance, if the Runnable was not in the queue already.)
8793     */
8794    public boolean removeCallbacks(Runnable action) {
8795        final AttachInfo attachInfo = mAttachInfo;
8796        if (attachInfo != null) {
8797            attachInfo.mHandler.removeCallbacks(action);
8798        } else {
8799            // Assume that post will succeed later
8800            ViewRootImpl.getRunQueue().removeCallbacks(action);
8801        }
8802        return true;
8803    }
8804
8805    /**
8806     * <p>Cause an invalidate to happen on a subsequent cycle through the event loop.
8807     * Use this to invalidate the View from a non-UI thread.</p>
8808     *
8809     * <p>This method can be invoked from outside of the UI thread
8810     * only when this View is attached to a window.</p>
8811     *
8812     * @see #invalidate()
8813     */
8814    public void postInvalidate() {
8815        postInvalidateDelayed(0);
8816    }
8817
8818    /**
8819     * <p>Cause an invalidate of the specified area to happen on a subsequent cycle
8820     * through the event loop. Use this to invalidate the View from a non-UI thread.</p>
8821     *
8822     * <p>This method can be invoked from outside of the UI thread
8823     * only when this View is attached to a window.</p>
8824     *
8825     * @param left The left coordinate of the rectangle to invalidate.
8826     * @param top The top coordinate of the rectangle to invalidate.
8827     * @param right The right coordinate of the rectangle to invalidate.
8828     * @param bottom The bottom coordinate of the rectangle to invalidate.
8829     *
8830     * @see #invalidate(int, int, int, int)
8831     * @see #invalidate(Rect)
8832     */
8833    public void postInvalidate(int left, int top, int right, int bottom) {
8834        postInvalidateDelayed(0, left, top, right, bottom);
8835    }
8836
8837    /**
8838     * <p>Cause an invalidate to happen on a subsequent cycle through the event
8839     * loop. Waits for the specified amount of time.</p>
8840     *
8841     * <p>This method can be invoked from outside of the UI thread
8842     * only when this View is attached to a window.</p>
8843     *
8844     * @param delayMilliseconds the duration in milliseconds to delay the
8845     *         invalidation by
8846     */
8847    public void postInvalidateDelayed(long delayMilliseconds) {
8848        // We try only with the AttachInfo because there's no point in invalidating
8849        // if we are not attached to our window
8850        final AttachInfo attachInfo = mAttachInfo;
8851        if (attachInfo != null) {
8852            attachInfo.mViewRootImpl.dispatchInvalidateDelayed(this, delayMilliseconds);
8853        }
8854    }
8855
8856    /**
8857     * <p>Cause an invalidate of the specified area to happen on a subsequent cycle
8858     * through the event loop. Waits for the specified amount of time.</p>
8859     *
8860     * <p>This method can be invoked from outside of the UI thread
8861     * only when this View is attached to a window.</p>
8862     *
8863     * @param delayMilliseconds the duration in milliseconds to delay the
8864     *         invalidation by
8865     * @param left The left coordinate of the rectangle to invalidate.
8866     * @param top The top coordinate of the rectangle to invalidate.
8867     * @param right The right coordinate of the rectangle to invalidate.
8868     * @param bottom The bottom coordinate of the rectangle to invalidate.
8869     */
8870    public void postInvalidateDelayed(long delayMilliseconds, int left, int top,
8871            int right, int bottom) {
8872
8873        // We try only with the AttachInfo because there's no point in invalidating
8874        // if we are not attached to our window
8875        final AttachInfo attachInfo = mAttachInfo;
8876        if (attachInfo != null) {
8877            final AttachInfo.InvalidateInfo info = AttachInfo.InvalidateInfo.acquire();
8878            info.target = this;
8879            info.left = left;
8880            info.top = top;
8881            info.right = right;
8882            info.bottom = bottom;
8883
8884            attachInfo.mViewRootImpl.dispatchInvalidateRectDelayed(info, delayMilliseconds);
8885        }
8886    }
8887
8888    /**
8889     * <p>Cause an invalidate to happen on the next animation time step, typically the
8890     * next display frame.</p>
8891     *
8892     * <p>This method can be invoked from outside of the UI thread
8893     * only when this View is attached to a window.</p>
8894     *
8895     * @hide
8896     */
8897    public void postInvalidateOnAnimation() {
8898        // We try only with the AttachInfo because there's no point in invalidating
8899        // if we are not attached to our window
8900        final AttachInfo attachInfo = mAttachInfo;
8901        if (attachInfo != null) {
8902            attachInfo.mViewRootImpl.dispatchInvalidateOnAnimation(this);
8903        }
8904    }
8905
8906    /**
8907     * <p>Cause an invalidate of the specified area to happen on the next animation
8908     * time step, typically the next display frame.</p>
8909     *
8910     * <p>This method can be invoked from outside of the UI thread
8911     * only when this View is attached to a window.</p>
8912     *
8913     * @param left The left coordinate of the rectangle to invalidate.
8914     * @param top The top coordinate of the rectangle to invalidate.
8915     * @param right The right coordinate of the rectangle to invalidate.
8916     * @param bottom The bottom coordinate of the rectangle to invalidate.
8917     *
8918     * @hide
8919     */
8920    public void postInvalidateOnAnimation(int left, int top, int right, int bottom) {
8921        // We try only with the AttachInfo because there's no point in invalidating
8922        // if we are not attached to our window
8923        final AttachInfo attachInfo = mAttachInfo;
8924        if (attachInfo != null) {
8925            final AttachInfo.InvalidateInfo info = AttachInfo.InvalidateInfo.acquire();
8926            info.target = this;
8927            info.left = left;
8928            info.top = top;
8929            info.right = right;
8930            info.bottom = bottom;
8931
8932            attachInfo.mViewRootImpl.dispatchInvalidateRectOnAnimation(info);
8933        }
8934    }
8935
8936    /**
8937     * Post a callback to send a {@link AccessibilityEvent#TYPE_VIEW_SCROLLED} event.
8938     * This event is sent at most once every
8939     * {@link ViewConfiguration#getSendRecurringAccessibilityEventsInterval()}.
8940     */
8941    private void postSendViewScrolledAccessibilityEventCallback() {
8942        if (mSendViewScrolledAccessibilityEvent == null) {
8943            mSendViewScrolledAccessibilityEvent = new SendViewScrolledAccessibilityEvent();
8944        }
8945        if (!mSendViewScrolledAccessibilityEvent.mIsPending) {
8946            mSendViewScrolledAccessibilityEvent.mIsPending = true;
8947            postDelayed(mSendViewScrolledAccessibilityEvent,
8948                    ViewConfiguration.getSendRecurringAccessibilityEventsInterval());
8949        }
8950    }
8951
8952    /**
8953     * Called by a parent to request that a child update its values for mScrollX
8954     * and mScrollY if necessary. This will typically be done if the child is
8955     * animating a scroll using a {@link android.widget.Scroller Scroller}
8956     * object.
8957     */
8958    public void computeScroll() {
8959    }
8960
8961    /**
8962     * <p>Indicate whether the horizontal edges are faded when the view is
8963     * scrolled horizontally.</p>
8964     *
8965     * @return true if the horizontal edges should are faded on scroll, false
8966     *         otherwise
8967     *
8968     * @see #setHorizontalFadingEdgeEnabled(boolean)
8969     * @attr ref android.R.styleable#View_requiresFadingEdge
8970     */
8971    public boolean isHorizontalFadingEdgeEnabled() {
8972        return (mViewFlags & FADING_EDGE_HORIZONTAL) == FADING_EDGE_HORIZONTAL;
8973    }
8974
8975    /**
8976     * <p>Define whether the horizontal edges should be faded when this view
8977     * is scrolled horizontally.</p>
8978     *
8979     * @param horizontalFadingEdgeEnabled true if the horizontal edges should
8980     *                                    be faded when the view is scrolled
8981     *                                    horizontally
8982     *
8983     * @see #isHorizontalFadingEdgeEnabled()
8984     * @attr ref android.R.styleable#View_requiresFadingEdge
8985     */
8986    public void setHorizontalFadingEdgeEnabled(boolean horizontalFadingEdgeEnabled) {
8987        if (isHorizontalFadingEdgeEnabled() != horizontalFadingEdgeEnabled) {
8988            if (horizontalFadingEdgeEnabled) {
8989                initScrollCache();
8990            }
8991
8992            mViewFlags ^= FADING_EDGE_HORIZONTAL;
8993        }
8994    }
8995
8996    /**
8997     * <p>Indicate whether the vertical edges are faded when the view is
8998     * scrolled horizontally.</p>
8999     *
9000     * @return true if the vertical edges should are faded on scroll, false
9001     *         otherwise
9002     *
9003     * @see #setVerticalFadingEdgeEnabled(boolean)
9004     * @attr ref android.R.styleable#View_requiresFadingEdge
9005     */
9006    public boolean isVerticalFadingEdgeEnabled() {
9007        return (mViewFlags & FADING_EDGE_VERTICAL) == FADING_EDGE_VERTICAL;
9008    }
9009
9010    /**
9011     * <p>Define whether the vertical edges should be faded when this view
9012     * is scrolled vertically.</p>
9013     *
9014     * @param verticalFadingEdgeEnabled true if the vertical edges should
9015     *                                  be faded when the view is scrolled
9016     *                                  vertically
9017     *
9018     * @see #isVerticalFadingEdgeEnabled()
9019     * @attr ref android.R.styleable#View_requiresFadingEdge
9020     */
9021    public void setVerticalFadingEdgeEnabled(boolean verticalFadingEdgeEnabled) {
9022        if (isVerticalFadingEdgeEnabled() != verticalFadingEdgeEnabled) {
9023            if (verticalFadingEdgeEnabled) {
9024                initScrollCache();
9025            }
9026
9027            mViewFlags ^= FADING_EDGE_VERTICAL;
9028        }
9029    }
9030
9031    /**
9032     * Returns the strength, or intensity, of the top faded edge. The strength is
9033     * a value between 0.0 (no fade) and 1.0 (full fade). The default implementation
9034     * returns 0.0 or 1.0 but no value in between.
9035     *
9036     * Subclasses should override this method to provide a smoother fade transition
9037     * when scrolling occurs.
9038     *
9039     * @return the intensity of the top fade as a float between 0.0f and 1.0f
9040     */
9041    protected float getTopFadingEdgeStrength() {
9042        return computeVerticalScrollOffset() > 0 ? 1.0f : 0.0f;
9043    }
9044
9045    /**
9046     * Returns the strength, or intensity, of the bottom faded edge. The strength is
9047     * a value between 0.0 (no fade) and 1.0 (full fade). The default implementation
9048     * returns 0.0 or 1.0 but no value in between.
9049     *
9050     * Subclasses should override this method to provide a smoother fade transition
9051     * when scrolling occurs.
9052     *
9053     * @return the intensity of the bottom fade as a float between 0.0f and 1.0f
9054     */
9055    protected float getBottomFadingEdgeStrength() {
9056        return computeVerticalScrollOffset() + computeVerticalScrollExtent() <
9057                computeVerticalScrollRange() ? 1.0f : 0.0f;
9058    }
9059
9060    /**
9061     * Returns the strength, or intensity, of the left faded edge. The strength is
9062     * a value between 0.0 (no fade) and 1.0 (full fade). The default implementation
9063     * returns 0.0 or 1.0 but no value in between.
9064     *
9065     * Subclasses should override this method to provide a smoother fade transition
9066     * when scrolling occurs.
9067     *
9068     * @return the intensity of the left fade as a float between 0.0f and 1.0f
9069     */
9070    protected float getLeftFadingEdgeStrength() {
9071        return computeHorizontalScrollOffset() > 0 ? 1.0f : 0.0f;
9072    }
9073
9074    /**
9075     * Returns the strength, or intensity, of the right faded edge. The strength is
9076     * a value between 0.0 (no fade) and 1.0 (full fade). The default implementation
9077     * returns 0.0 or 1.0 but no value in between.
9078     *
9079     * Subclasses should override this method to provide a smoother fade transition
9080     * when scrolling occurs.
9081     *
9082     * @return the intensity of the right fade as a float between 0.0f and 1.0f
9083     */
9084    protected float getRightFadingEdgeStrength() {
9085        return computeHorizontalScrollOffset() + computeHorizontalScrollExtent() <
9086                computeHorizontalScrollRange() ? 1.0f : 0.0f;
9087    }
9088
9089    /**
9090     * <p>Indicate whether the horizontal scrollbar should be drawn or not. The
9091     * scrollbar is not drawn by default.</p>
9092     *
9093     * @return true if the horizontal scrollbar should be painted, false
9094     *         otherwise
9095     *
9096     * @see #setHorizontalScrollBarEnabled(boolean)
9097     */
9098    public boolean isHorizontalScrollBarEnabled() {
9099        return (mViewFlags & SCROLLBARS_HORIZONTAL) == SCROLLBARS_HORIZONTAL;
9100    }
9101
9102    /**
9103     * <p>Define whether the horizontal scrollbar should be drawn or not. The
9104     * scrollbar is not drawn by default.</p>
9105     *
9106     * @param horizontalScrollBarEnabled true if the horizontal scrollbar should
9107     *                                   be painted
9108     *
9109     * @see #isHorizontalScrollBarEnabled()
9110     */
9111    public void setHorizontalScrollBarEnabled(boolean horizontalScrollBarEnabled) {
9112        if (isHorizontalScrollBarEnabled() != horizontalScrollBarEnabled) {
9113            mViewFlags ^= SCROLLBARS_HORIZONTAL;
9114            computeOpaqueFlags();
9115            resolvePadding();
9116        }
9117    }
9118
9119    /**
9120     * <p>Indicate whether the vertical scrollbar should be drawn or not. The
9121     * scrollbar is not drawn by default.</p>
9122     *
9123     * @return true if the vertical scrollbar should be painted, false
9124     *         otherwise
9125     *
9126     * @see #setVerticalScrollBarEnabled(boolean)
9127     */
9128    public boolean isVerticalScrollBarEnabled() {
9129        return (mViewFlags & SCROLLBARS_VERTICAL) == SCROLLBARS_VERTICAL;
9130    }
9131
9132    /**
9133     * <p>Define whether the vertical scrollbar should be drawn or not. The
9134     * scrollbar is not drawn by default.</p>
9135     *
9136     * @param verticalScrollBarEnabled true if the vertical scrollbar should
9137     *                                 be painted
9138     *
9139     * @see #isVerticalScrollBarEnabled()
9140     */
9141    public void setVerticalScrollBarEnabled(boolean verticalScrollBarEnabled) {
9142        if (isVerticalScrollBarEnabled() != verticalScrollBarEnabled) {
9143            mViewFlags ^= SCROLLBARS_VERTICAL;
9144            computeOpaqueFlags();
9145            resolvePadding();
9146        }
9147    }
9148
9149    /**
9150     * @hide
9151     */
9152    protected void recomputePadding() {
9153        setPadding(mUserPaddingLeft, mPaddingTop, mUserPaddingRight, mUserPaddingBottom);
9154    }
9155
9156    /**
9157     * Define whether scrollbars will fade when the view is not scrolling.
9158     *
9159     * @param fadeScrollbars wheter to enable fading
9160     *
9161     */
9162    public void setScrollbarFadingEnabled(boolean fadeScrollbars) {
9163        initScrollCache();
9164        final ScrollabilityCache scrollabilityCache = mScrollCache;
9165        scrollabilityCache.fadeScrollBars = fadeScrollbars;
9166        if (fadeScrollbars) {
9167            scrollabilityCache.state = ScrollabilityCache.OFF;
9168        } else {
9169            scrollabilityCache.state = ScrollabilityCache.ON;
9170        }
9171    }
9172
9173    /**
9174     *
9175     * Returns true if scrollbars will fade when this view is not scrolling
9176     *
9177     * @return true if scrollbar fading is enabled
9178     */
9179    public boolean isScrollbarFadingEnabled() {
9180        return mScrollCache != null && mScrollCache.fadeScrollBars;
9181    }
9182
9183    /**
9184     * <p>Specify the style of the scrollbars. The scrollbars can be overlaid or
9185     * inset. When inset, they add to the padding of the view. And the scrollbars
9186     * can be drawn inside the padding area or on the edge of the view. For example,
9187     * if a view has a background drawable and you want to draw the scrollbars
9188     * inside the padding specified by the drawable, you can use
9189     * SCROLLBARS_INSIDE_OVERLAY or SCROLLBARS_INSIDE_INSET. If you want them to
9190     * appear at the edge of the view, ignoring the padding, then you can use
9191     * SCROLLBARS_OUTSIDE_OVERLAY or SCROLLBARS_OUTSIDE_INSET.</p>
9192     * @param style the style of the scrollbars. Should be one of
9193     * SCROLLBARS_INSIDE_OVERLAY, SCROLLBARS_INSIDE_INSET,
9194     * SCROLLBARS_OUTSIDE_OVERLAY or SCROLLBARS_OUTSIDE_INSET.
9195     * @see #SCROLLBARS_INSIDE_OVERLAY
9196     * @see #SCROLLBARS_INSIDE_INSET
9197     * @see #SCROLLBARS_OUTSIDE_OVERLAY
9198     * @see #SCROLLBARS_OUTSIDE_INSET
9199     */
9200    public void setScrollBarStyle(int style) {
9201        if (style != (mViewFlags & SCROLLBARS_STYLE_MASK)) {
9202            mViewFlags = (mViewFlags & ~SCROLLBARS_STYLE_MASK) | (style & SCROLLBARS_STYLE_MASK);
9203            computeOpaqueFlags();
9204            resolvePadding();
9205        }
9206    }
9207
9208    /**
9209     * <p>Returns the current scrollbar style.</p>
9210     * @return the current scrollbar style
9211     * @see #SCROLLBARS_INSIDE_OVERLAY
9212     * @see #SCROLLBARS_INSIDE_INSET
9213     * @see #SCROLLBARS_OUTSIDE_OVERLAY
9214     * @see #SCROLLBARS_OUTSIDE_INSET
9215     */
9216    @ViewDebug.ExportedProperty(mapping = {
9217            @ViewDebug.IntToString(from = SCROLLBARS_INSIDE_OVERLAY, to = "INSIDE_OVERLAY"),
9218            @ViewDebug.IntToString(from = SCROLLBARS_INSIDE_INSET, to = "INSIDE_INSET"),
9219            @ViewDebug.IntToString(from = SCROLLBARS_OUTSIDE_OVERLAY, to = "OUTSIDE_OVERLAY"),
9220            @ViewDebug.IntToString(from = SCROLLBARS_OUTSIDE_INSET, to = "OUTSIDE_INSET")
9221    })
9222    public int getScrollBarStyle() {
9223        return mViewFlags & SCROLLBARS_STYLE_MASK;
9224    }
9225
9226    /**
9227     * <p>Compute the horizontal range that the horizontal scrollbar
9228     * represents.</p>
9229     *
9230     * <p>The range is expressed in arbitrary units that must be the same as the
9231     * units used by {@link #computeHorizontalScrollExtent()} and
9232     * {@link #computeHorizontalScrollOffset()}.</p>
9233     *
9234     * <p>The default range is the drawing width of this view.</p>
9235     *
9236     * @return the total horizontal range represented by the horizontal
9237     *         scrollbar
9238     *
9239     * @see #computeHorizontalScrollExtent()
9240     * @see #computeHorizontalScrollOffset()
9241     * @see android.widget.ScrollBarDrawable
9242     */
9243    protected int computeHorizontalScrollRange() {
9244        return getWidth();
9245    }
9246
9247    /**
9248     * <p>Compute the horizontal offset of the horizontal scrollbar's thumb
9249     * within the horizontal range. This value is used to compute the position
9250     * of the thumb within the scrollbar's track.</p>
9251     *
9252     * <p>The range is expressed in arbitrary units that must be the same as the
9253     * units used by {@link #computeHorizontalScrollRange()} and
9254     * {@link #computeHorizontalScrollExtent()}.</p>
9255     *
9256     * <p>The default offset is the scroll offset of this view.</p>
9257     *
9258     * @return the horizontal offset of the scrollbar's thumb
9259     *
9260     * @see #computeHorizontalScrollRange()
9261     * @see #computeHorizontalScrollExtent()
9262     * @see android.widget.ScrollBarDrawable
9263     */
9264    protected int computeHorizontalScrollOffset() {
9265        return mScrollX;
9266    }
9267
9268    /**
9269     * <p>Compute the horizontal extent of the horizontal scrollbar's thumb
9270     * within the horizontal range. This value is used to compute the length
9271     * of the thumb within the scrollbar's track.</p>
9272     *
9273     * <p>The range is expressed in arbitrary units that must be the same as the
9274     * units used by {@link #computeHorizontalScrollRange()} and
9275     * {@link #computeHorizontalScrollOffset()}.</p>
9276     *
9277     * <p>The default extent is the drawing width of this view.</p>
9278     *
9279     * @return the horizontal extent of the scrollbar's thumb
9280     *
9281     * @see #computeHorizontalScrollRange()
9282     * @see #computeHorizontalScrollOffset()
9283     * @see android.widget.ScrollBarDrawable
9284     */
9285    protected int computeHorizontalScrollExtent() {
9286        return getWidth();
9287    }
9288
9289    /**
9290     * <p>Compute the vertical range that the vertical scrollbar represents.</p>
9291     *
9292     * <p>The range is expressed in arbitrary units that must be the same as the
9293     * units used by {@link #computeVerticalScrollExtent()} and
9294     * {@link #computeVerticalScrollOffset()}.</p>
9295     *
9296     * @return the total vertical range represented by the vertical scrollbar
9297     *
9298     * <p>The default range is the drawing height of this view.</p>
9299     *
9300     * @see #computeVerticalScrollExtent()
9301     * @see #computeVerticalScrollOffset()
9302     * @see android.widget.ScrollBarDrawable
9303     */
9304    protected int computeVerticalScrollRange() {
9305        return getHeight();
9306    }
9307
9308    /**
9309     * <p>Compute the vertical offset of the vertical scrollbar's thumb
9310     * within the horizontal range. This value is used to compute the position
9311     * of the thumb within the scrollbar's track.</p>
9312     *
9313     * <p>The range is expressed in arbitrary units that must be the same as the
9314     * units used by {@link #computeVerticalScrollRange()} and
9315     * {@link #computeVerticalScrollExtent()}.</p>
9316     *
9317     * <p>The default offset is the scroll offset of this view.</p>
9318     *
9319     * @return the vertical offset of the scrollbar's thumb
9320     *
9321     * @see #computeVerticalScrollRange()
9322     * @see #computeVerticalScrollExtent()
9323     * @see android.widget.ScrollBarDrawable
9324     */
9325    protected int computeVerticalScrollOffset() {
9326        return mScrollY;
9327    }
9328
9329    /**
9330     * <p>Compute the vertical extent of the horizontal scrollbar's thumb
9331     * within the vertical range. This value is used to compute the length
9332     * of the thumb within the scrollbar's track.</p>
9333     *
9334     * <p>The range is expressed in arbitrary units that must be the same as the
9335     * units used by {@link #computeVerticalScrollRange()} and
9336     * {@link #computeVerticalScrollOffset()}.</p>
9337     *
9338     * <p>The default extent is the drawing height of this view.</p>
9339     *
9340     * @return the vertical extent of the scrollbar's thumb
9341     *
9342     * @see #computeVerticalScrollRange()
9343     * @see #computeVerticalScrollOffset()
9344     * @see android.widget.ScrollBarDrawable
9345     */
9346    protected int computeVerticalScrollExtent() {
9347        return getHeight();
9348    }
9349
9350    /**
9351     * Check if this view can be scrolled horizontally in a certain direction.
9352     *
9353     * @param direction Negative to check scrolling left, positive to check scrolling right.
9354     * @return true if this view can be scrolled in the specified direction, false otherwise.
9355     */
9356    public boolean canScrollHorizontally(int direction) {
9357        final int offset = computeHorizontalScrollOffset();
9358        final int range = computeHorizontalScrollRange() - computeHorizontalScrollExtent();
9359        if (range == 0) return false;
9360        if (direction < 0) {
9361            return offset > 0;
9362        } else {
9363            return offset < range - 1;
9364        }
9365    }
9366
9367    /**
9368     * Check if this view can be scrolled vertically in a certain direction.
9369     *
9370     * @param direction Negative to check scrolling up, positive to check scrolling down.
9371     * @return true if this view can be scrolled in the specified direction, false otherwise.
9372     */
9373    public boolean canScrollVertically(int direction) {
9374        final int offset = computeVerticalScrollOffset();
9375        final int range = computeVerticalScrollRange() - computeVerticalScrollExtent();
9376        if (range == 0) return false;
9377        if (direction < 0) {
9378            return offset > 0;
9379        } else {
9380            return offset < range - 1;
9381        }
9382    }
9383
9384    /**
9385     * <p>Request the drawing of the horizontal and the vertical scrollbar. The
9386     * scrollbars are painted only if they have been awakened first.</p>
9387     *
9388     * @param canvas the canvas on which to draw the scrollbars
9389     *
9390     * @see #awakenScrollBars(int)
9391     */
9392    protected final void onDrawScrollBars(Canvas canvas) {
9393        // scrollbars are drawn only when the animation is running
9394        final ScrollabilityCache cache = mScrollCache;
9395        if (cache != null) {
9396
9397            int state = cache.state;
9398
9399            if (state == ScrollabilityCache.OFF) {
9400                return;
9401            }
9402
9403            boolean invalidate = false;
9404
9405            if (state == ScrollabilityCache.FADING) {
9406                // We're fading -- get our fade interpolation
9407                if (cache.interpolatorValues == null) {
9408                    cache.interpolatorValues = new float[1];
9409                }
9410
9411                float[] values = cache.interpolatorValues;
9412
9413                // Stops the animation if we're done
9414                if (cache.scrollBarInterpolator.timeToValues(values) ==
9415                        Interpolator.Result.FREEZE_END) {
9416                    cache.state = ScrollabilityCache.OFF;
9417                } else {
9418                    cache.scrollBar.setAlpha(Math.round(values[0]));
9419                }
9420
9421                // This will make the scroll bars inval themselves after
9422                // drawing. We only want this when we're fading so that
9423                // we prevent excessive redraws
9424                invalidate = true;
9425            } else {
9426                // We're just on -- but we may have been fading before so
9427                // reset alpha
9428                cache.scrollBar.setAlpha(255);
9429            }
9430
9431
9432            final int viewFlags = mViewFlags;
9433
9434            final boolean drawHorizontalScrollBar =
9435                (viewFlags & SCROLLBARS_HORIZONTAL) == SCROLLBARS_HORIZONTAL;
9436            final boolean drawVerticalScrollBar =
9437                (viewFlags & SCROLLBARS_VERTICAL) == SCROLLBARS_VERTICAL
9438                && !isVerticalScrollBarHidden();
9439
9440            if (drawVerticalScrollBar || drawHorizontalScrollBar) {
9441                final int width = mRight - mLeft;
9442                final int height = mBottom - mTop;
9443
9444                final ScrollBarDrawable scrollBar = cache.scrollBar;
9445
9446                final int scrollX = mScrollX;
9447                final int scrollY = mScrollY;
9448                final int inside = (viewFlags & SCROLLBARS_OUTSIDE_MASK) == 0 ? ~0 : 0;
9449
9450                int left, top, right, bottom;
9451
9452                if (drawHorizontalScrollBar) {
9453                    int size = scrollBar.getSize(false);
9454                    if (size <= 0) {
9455                        size = cache.scrollBarSize;
9456                    }
9457
9458                    scrollBar.setParameters(computeHorizontalScrollRange(),
9459                                            computeHorizontalScrollOffset(),
9460                                            computeHorizontalScrollExtent(), false);
9461                    final int verticalScrollBarGap = drawVerticalScrollBar ?
9462                            getVerticalScrollbarWidth() : 0;
9463                    top = scrollY + height - size - (mUserPaddingBottom & inside);
9464                    left = scrollX + (mPaddingLeft & inside);
9465                    right = scrollX + width - (mUserPaddingRight & inside) - verticalScrollBarGap;
9466                    bottom = top + size;
9467                    onDrawHorizontalScrollBar(canvas, scrollBar, left, top, right, bottom);
9468                    if (invalidate) {
9469                        invalidate(left, top, right, bottom);
9470                    }
9471                }
9472
9473                if (drawVerticalScrollBar) {
9474                    int size = scrollBar.getSize(true);
9475                    if (size <= 0) {
9476                        size = cache.scrollBarSize;
9477                    }
9478
9479                    scrollBar.setParameters(computeVerticalScrollRange(),
9480                                            computeVerticalScrollOffset(),
9481                                            computeVerticalScrollExtent(), true);
9482                    switch (mVerticalScrollbarPosition) {
9483                        default:
9484                        case SCROLLBAR_POSITION_DEFAULT:
9485                        case SCROLLBAR_POSITION_RIGHT:
9486                            left = scrollX + width - size - (mUserPaddingRight & inside);
9487                            break;
9488                        case SCROLLBAR_POSITION_LEFT:
9489                            left = scrollX + (mUserPaddingLeft & inside);
9490                            break;
9491                    }
9492                    top = scrollY + (mPaddingTop & inside);
9493                    right = left + size;
9494                    bottom = scrollY + height - (mUserPaddingBottom & inside);
9495                    onDrawVerticalScrollBar(canvas, scrollBar, left, top, right, bottom);
9496                    if (invalidate) {
9497                        invalidate(left, top, right, bottom);
9498                    }
9499                }
9500            }
9501        }
9502    }
9503
9504    /**
9505     * Override this if the vertical scrollbar needs to be hidden in a subclass, like when
9506     * FastScroller is visible.
9507     * @return whether to temporarily hide the vertical scrollbar
9508     * @hide
9509     */
9510    protected boolean isVerticalScrollBarHidden() {
9511        return false;
9512    }
9513
9514    /**
9515     * <p>Draw the horizontal scrollbar if
9516     * {@link #isHorizontalScrollBarEnabled()} returns true.</p>
9517     *
9518     * @param canvas the canvas on which to draw the scrollbar
9519     * @param scrollBar the scrollbar's drawable
9520     *
9521     * @see #isHorizontalScrollBarEnabled()
9522     * @see #computeHorizontalScrollRange()
9523     * @see #computeHorizontalScrollExtent()
9524     * @see #computeHorizontalScrollOffset()
9525     * @see android.widget.ScrollBarDrawable
9526     * @hide
9527     */
9528    protected void onDrawHorizontalScrollBar(Canvas canvas, Drawable scrollBar,
9529            int l, int t, int r, int b) {
9530        scrollBar.setBounds(l, t, r, b);
9531        scrollBar.draw(canvas);
9532    }
9533
9534    /**
9535     * <p>Draw the vertical scrollbar if {@link #isVerticalScrollBarEnabled()}
9536     * returns true.</p>
9537     *
9538     * @param canvas the canvas on which to draw the scrollbar
9539     * @param scrollBar the scrollbar's drawable
9540     *
9541     * @see #isVerticalScrollBarEnabled()
9542     * @see #computeVerticalScrollRange()
9543     * @see #computeVerticalScrollExtent()
9544     * @see #computeVerticalScrollOffset()
9545     * @see android.widget.ScrollBarDrawable
9546     * @hide
9547     */
9548    protected void onDrawVerticalScrollBar(Canvas canvas, Drawable scrollBar,
9549            int l, int t, int r, int b) {
9550        scrollBar.setBounds(l, t, r, b);
9551        scrollBar.draw(canvas);
9552    }
9553
9554    /**
9555     * Implement this to do your drawing.
9556     *
9557     * @param canvas the canvas on which the background will be drawn
9558     */
9559    protected void onDraw(Canvas canvas) {
9560    }
9561
9562    /*
9563     * Caller is responsible for calling requestLayout if necessary.
9564     * (This allows addViewInLayout to not request a new layout.)
9565     */
9566    void assignParent(ViewParent parent) {
9567        if (mParent == null) {
9568            mParent = parent;
9569        } else if (parent == null) {
9570            mParent = null;
9571        } else {
9572            throw new RuntimeException("view " + this + " being added, but"
9573                    + " it already has a parent");
9574        }
9575    }
9576
9577    /**
9578     * This is called when the view is attached to a window.  At this point it
9579     * has a Surface and will start drawing.  Note that this function is
9580     * guaranteed to be called before {@link #onDraw(android.graphics.Canvas)},
9581     * however it may be called any time before the first onDraw -- including
9582     * before or after {@link #onMeasure(int, int)}.
9583     *
9584     * @see #onDetachedFromWindow()
9585     */
9586    protected void onAttachedToWindow() {
9587        if ((mPrivateFlags & REQUEST_TRANSPARENT_REGIONS) != 0) {
9588            mParent.requestTransparentRegion(this);
9589        }
9590        if ((mPrivateFlags & AWAKEN_SCROLL_BARS_ON_ATTACH) != 0) {
9591            initialAwakenScrollBars();
9592            mPrivateFlags &= ~AWAKEN_SCROLL_BARS_ON_ATTACH;
9593        }
9594        jumpDrawablesToCurrentState();
9595        // Order is important here: LayoutDirection MUST be resolved before Padding
9596        // and TextDirection
9597        resolveLayoutDirectionIfNeeded();
9598        resolvePadding();
9599        resolveTextDirection();
9600        if (isFocused()) {
9601            InputMethodManager imm = InputMethodManager.peekInstance();
9602            imm.focusIn(this);
9603        }
9604    }
9605
9606    /**
9607     * Resolve and cache the layout direction. LTR is set initially. This is implicitly supposing
9608     * that the parent directionality can and will be resolved before its children.
9609     */
9610    private void resolveLayoutDirectionIfNeeded() {
9611        // Do not resolve if it is not needed
9612        if ((mPrivateFlags2 & LAYOUT_DIRECTION_RESOLVED) == LAYOUT_DIRECTION_RESOLVED) return;
9613
9614        // Clear any previous layout direction resolution
9615        mPrivateFlags2 &= ~LAYOUT_DIRECTION_RESOLVED_RTL;
9616
9617        // Set resolved depending on layout direction
9618        switch (getLayoutDirection()) {
9619            case LAYOUT_DIRECTION_INHERIT:
9620                // We cannot do the resolution if there is no parent
9621                if (mParent == null) return;
9622
9623                // If this is root view, no need to look at parent's layout dir.
9624                if (mParent instanceof ViewGroup) {
9625                    ViewGroup viewGroup = ((ViewGroup) mParent);
9626
9627                    // Check if the parent view group can resolve
9628                    if (! viewGroup.canResolveLayoutDirection()) {
9629                        return;
9630                    }
9631                    if (viewGroup.getResolvedLayoutDirection() == LAYOUT_DIRECTION_RTL) {
9632                        mPrivateFlags2 |= LAYOUT_DIRECTION_RESOLVED_RTL;
9633                    }
9634                }
9635                break;
9636            case LAYOUT_DIRECTION_RTL:
9637                mPrivateFlags2 |= LAYOUT_DIRECTION_RESOLVED_RTL;
9638                break;
9639            case LAYOUT_DIRECTION_LOCALE:
9640                if(isLayoutDirectionRtl(Locale.getDefault())) {
9641                    mPrivateFlags2 |= LAYOUT_DIRECTION_RESOLVED_RTL;
9642                }
9643                break;
9644            default:
9645                // Nothing to do, LTR by default
9646        }
9647
9648        // Set to resolved
9649        mPrivateFlags2 |= LAYOUT_DIRECTION_RESOLVED;
9650        onResolvedLayoutDirectionChanged();
9651        // Resolve padding
9652        resolvePadding();
9653    }
9654
9655    /**
9656     * Called when layout direction has been resolved.
9657     *
9658     * The default implementation does nothing.
9659     */
9660    public void onResolvedLayoutDirectionChanged() {
9661    }
9662
9663    /**
9664     * Resolve padding depending on layout direction.
9665     */
9666    public void resolvePadding() {
9667        // If the user specified the absolute padding (either with android:padding or
9668        // android:paddingLeft/Top/Right/Bottom), use this padding, otherwise
9669        // use the default padding or the padding from the background drawable
9670        // (stored at this point in mPadding*)
9671        int resolvedLayoutDirection = getResolvedLayoutDirection();
9672        switch (resolvedLayoutDirection) {
9673            case LAYOUT_DIRECTION_RTL:
9674                // Start user padding override Right user padding. Otherwise, if Right user
9675                // padding is not defined, use the default Right padding. If Right user padding
9676                // is defined, just use it.
9677                if (mUserPaddingStart >= 0) {
9678                    mUserPaddingRight = mUserPaddingStart;
9679                } else if (mUserPaddingRight < 0) {
9680                    mUserPaddingRight = mPaddingRight;
9681                }
9682                if (mUserPaddingEnd >= 0) {
9683                    mUserPaddingLeft = mUserPaddingEnd;
9684                } else if (mUserPaddingLeft < 0) {
9685                    mUserPaddingLeft = mPaddingLeft;
9686                }
9687                break;
9688            case LAYOUT_DIRECTION_LTR:
9689            default:
9690                // Start user padding override Left user padding. Otherwise, if Left user
9691                // padding is not defined, use the default left padding. If Left user padding
9692                // is defined, just use it.
9693                if (mUserPaddingStart >= 0) {
9694                    mUserPaddingLeft = mUserPaddingStart;
9695                } else if (mUserPaddingLeft < 0) {
9696                    mUserPaddingLeft = mPaddingLeft;
9697                }
9698                if (mUserPaddingEnd >= 0) {
9699                    mUserPaddingRight = mUserPaddingEnd;
9700                } else if (mUserPaddingRight < 0) {
9701                    mUserPaddingRight = mPaddingRight;
9702                }
9703        }
9704
9705        mUserPaddingBottom = (mUserPaddingBottom >= 0) ? mUserPaddingBottom : mPaddingBottom;
9706
9707        if(isPaddingRelative()) {
9708            setPaddingRelative(mUserPaddingStart, mPaddingTop, mUserPaddingEnd, mUserPaddingBottom);
9709        } else {
9710            recomputePadding();
9711        }
9712        onPaddingChanged(resolvedLayoutDirection);
9713    }
9714
9715    /**
9716     * Resolve padding depending on the layout direction. Subclasses that care about
9717     * padding resolution should override this method. The default implementation does
9718     * nothing.
9719     *
9720     * @param layoutDirection the direction of the layout
9721     *
9722     * {@link #LAYOUT_DIRECTION_LTR}
9723     * {@link #LAYOUT_DIRECTION_RTL}
9724     */
9725    public void onPaddingChanged(int layoutDirection) {
9726    }
9727
9728    /**
9729     * Check if layout direction resolution can be done.
9730     *
9731     * @return true if layout direction resolution can be done otherwise return false.
9732     */
9733    public boolean canResolveLayoutDirection() {
9734        switch (getLayoutDirection()) {
9735            case LAYOUT_DIRECTION_INHERIT:
9736                return (mParent != null);
9737            default:
9738                return true;
9739        }
9740    }
9741
9742    /**
9743     * Reset the resolved layout direction. Will call {@link View#onResolvedLayoutDirectionReset}
9744     * when reset is done.
9745     */
9746    public void resetResolvedLayoutDirection() {
9747        // Reset the current View resolution
9748        mPrivateFlags2 &= ~LAYOUT_DIRECTION_RESOLVED;
9749        onResolvedLayoutDirectionReset();
9750        // Reset also the text direction
9751        resetResolvedTextDirection();
9752    }
9753
9754    /**
9755     * Called during reset of resolved layout direction.
9756     *
9757     * Subclasses need to override this method to clear cached information that depends on the
9758     * resolved layout direction, or to inform child views that inherit their layout direction.
9759     *
9760     * The default implementation does nothing.
9761     */
9762    public void onResolvedLayoutDirectionReset() {
9763    }
9764
9765    /**
9766     * Check if a Locale uses an RTL script.
9767     *
9768     * @param locale Locale to check
9769     * @return true if the Locale uses an RTL script.
9770     */
9771    protected static boolean isLayoutDirectionRtl(Locale locale) {
9772        return (LAYOUT_DIRECTION_RTL == LocaleUtil.getLayoutDirectionFromLocale(locale));
9773    }
9774
9775    /**
9776     * This is called when the view is detached from a window.  At this point it
9777     * no longer has a surface for drawing.
9778     *
9779     * @see #onAttachedToWindow()
9780     */
9781    protected void onDetachedFromWindow() {
9782        mPrivateFlags &= ~CANCEL_NEXT_UP_EVENT;
9783
9784        removeUnsetPressCallback();
9785        removeLongPressCallback();
9786        removePerformClickCallback();
9787        removeSendViewScrolledAccessibilityEventCallback();
9788
9789        destroyDrawingCache();
9790
9791        destroyLayer();
9792
9793        if (mDisplayList != null) {
9794            mDisplayList.invalidate();
9795        }
9796
9797        if (mAttachInfo != null) {
9798            mAttachInfo.mViewRootImpl.cancelInvalidate(this);
9799        }
9800
9801        mCurrentAnimation = null;
9802
9803        resetResolvedLayoutDirection();
9804    }
9805
9806    /**
9807     * @return The number of times this view has been attached to a window
9808     */
9809    protected int getWindowAttachCount() {
9810        return mWindowAttachCount;
9811    }
9812
9813    /**
9814     * Retrieve a unique token identifying the window this view is attached to.
9815     * @return Return the window's token for use in
9816     * {@link WindowManager.LayoutParams#token WindowManager.LayoutParams.token}.
9817     */
9818    public IBinder getWindowToken() {
9819        return mAttachInfo != null ? mAttachInfo.mWindowToken : null;
9820    }
9821
9822    /**
9823     * Retrieve a unique token identifying the top-level "real" window of
9824     * the window that this view is attached to.  That is, this is like
9825     * {@link #getWindowToken}, except if the window this view in is a panel
9826     * window (attached to another containing window), then the token of
9827     * the containing window is returned instead.
9828     *
9829     * @return Returns the associated window token, either
9830     * {@link #getWindowToken()} or the containing window's token.
9831     */
9832    public IBinder getApplicationWindowToken() {
9833        AttachInfo ai = mAttachInfo;
9834        if (ai != null) {
9835            IBinder appWindowToken = ai.mPanelParentWindowToken;
9836            if (appWindowToken == null) {
9837                appWindowToken = ai.mWindowToken;
9838            }
9839            return appWindowToken;
9840        }
9841        return null;
9842    }
9843
9844    /**
9845     * Retrieve private session object this view hierarchy is using to
9846     * communicate with the window manager.
9847     * @return the session object to communicate with the window manager
9848     */
9849    /*package*/ IWindowSession getWindowSession() {
9850        return mAttachInfo != null ? mAttachInfo.mSession : null;
9851    }
9852
9853    /**
9854     * @param info the {@link android.view.View.AttachInfo} to associated with
9855     *        this view
9856     */
9857    void dispatchAttachedToWindow(AttachInfo info, int visibility) {
9858        //System.out.println("Attached! " + this);
9859        mAttachInfo = info;
9860        mWindowAttachCount++;
9861        // We will need to evaluate the drawable state at least once.
9862        mPrivateFlags |= DRAWABLE_STATE_DIRTY;
9863        if (mFloatingTreeObserver != null) {
9864            info.mTreeObserver.merge(mFloatingTreeObserver);
9865            mFloatingTreeObserver = null;
9866        }
9867        if ((mPrivateFlags&SCROLL_CONTAINER) != 0) {
9868            mAttachInfo.mScrollContainers.add(this);
9869            mPrivateFlags |= SCROLL_CONTAINER_ADDED;
9870        }
9871        performCollectViewAttributes(visibility);
9872        onAttachedToWindow();
9873
9874        ListenerInfo li = mListenerInfo;
9875        final CopyOnWriteArrayList<OnAttachStateChangeListener> listeners =
9876                li != null ? li.mOnAttachStateChangeListeners : null;
9877        if (listeners != null && listeners.size() > 0) {
9878            // NOTE: because of the use of CopyOnWriteArrayList, we *must* use an iterator to
9879            // perform the dispatching. The iterator is a safe guard against listeners that
9880            // could mutate the list by calling the various add/remove methods. This prevents
9881            // the array from being modified while we iterate it.
9882            for (OnAttachStateChangeListener listener : listeners) {
9883                listener.onViewAttachedToWindow(this);
9884            }
9885        }
9886
9887        int vis = info.mWindowVisibility;
9888        if (vis != GONE) {
9889            onWindowVisibilityChanged(vis);
9890        }
9891        if ((mPrivateFlags&DRAWABLE_STATE_DIRTY) != 0) {
9892            // If nobody has evaluated the drawable state yet, then do it now.
9893            refreshDrawableState();
9894        }
9895    }
9896
9897    void dispatchDetachedFromWindow() {
9898        AttachInfo info = mAttachInfo;
9899        if (info != null) {
9900            int vis = info.mWindowVisibility;
9901            if (vis != GONE) {
9902                onWindowVisibilityChanged(GONE);
9903            }
9904        }
9905
9906        onDetachedFromWindow();
9907
9908        ListenerInfo li = mListenerInfo;
9909        final CopyOnWriteArrayList<OnAttachStateChangeListener> listeners =
9910                li != null ? li.mOnAttachStateChangeListeners : null;
9911        if (listeners != null && listeners.size() > 0) {
9912            // NOTE: because of the use of CopyOnWriteArrayList, we *must* use an iterator to
9913            // perform the dispatching. The iterator is a safe guard against listeners that
9914            // could mutate the list by calling the various add/remove methods. This prevents
9915            // the array from being modified while we iterate it.
9916            for (OnAttachStateChangeListener listener : listeners) {
9917                listener.onViewDetachedFromWindow(this);
9918            }
9919        }
9920
9921        if ((mPrivateFlags & SCROLL_CONTAINER_ADDED) != 0) {
9922            mAttachInfo.mScrollContainers.remove(this);
9923            mPrivateFlags &= ~SCROLL_CONTAINER_ADDED;
9924        }
9925
9926        mAttachInfo = null;
9927    }
9928
9929    /**
9930     * Store this view hierarchy's frozen state into the given container.
9931     *
9932     * @param container The SparseArray in which to save the view's state.
9933     *
9934     * @see #restoreHierarchyState(android.util.SparseArray)
9935     * @see #dispatchSaveInstanceState(android.util.SparseArray)
9936     * @see #onSaveInstanceState()
9937     */
9938    public void saveHierarchyState(SparseArray<Parcelable> container) {
9939        dispatchSaveInstanceState(container);
9940    }
9941
9942    /**
9943     * Called by {@link #saveHierarchyState(android.util.SparseArray)} to store the state for
9944     * this view and its children. May be overridden to modify how freezing happens to a
9945     * view's children; for example, some views may want to not store state for their children.
9946     *
9947     * @param container The SparseArray in which to save the view's state.
9948     *
9949     * @see #dispatchRestoreInstanceState(android.util.SparseArray)
9950     * @see #saveHierarchyState(android.util.SparseArray)
9951     * @see #onSaveInstanceState()
9952     */
9953    protected void dispatchSaveInstanceState(SparseArray<Parcelable> container) {
9954        if (mID != NO_ID && (mViewFlags & SAVE_DISABLED_MASK) == 0) {
9955            mPrivateFlags &= ~SAVE_STATE_CALLED;
9956            Parcelable state = onSaveInstanceState();
9957            if ((mPrivateFlags & SAVE_STATE_CALLED) == 0) {
9958                throw new IllegalStateException(
9959                        "Derived class did not call super.onSaveInstanceState()");
9960            }
9961            if (state != null) {
9962                // Log.i("View", "Freezing #" + Integer.toHexString(mID)
9963                // + ": " + state);
9964                container.put(mID, state);
9965            }
9966        }
9967    }
9968
9969    /**
9970     * Hook allowing a view to generate a representation of its internal state
9971     * that can later be used to create a new instance with that same state.
9972     * This state should only contain information that is not persistent or can
9973     * not be reconstructed later. For example, you will never store your
9974     * current position on screen because that will be computed again when a
9975     * new instance of the view is placed in its view hierarchy.
9976     * <p>
9977     * Some examples of things you may store here: the current cursor position
9978     * in a text view (but usually not the text itself since that is stored in a
9979     * content provider or other persistent storage), the currently selected
9980     * item in a list view.
9981     *
9982     * @return Returns a Parcelable object containing the view's current dynamic
9983     *         state, or null if there is nothing interesting to save. The
9984     *         default implementation returns null.
9985     * @see #onRestoreInstanceState(android.os.Parcelable)
9986     * @see #saveHierarchyState(android.util.SparseArray)
9987     * @see #dispatchSaveInstanceState(android.util.SparseArray)
9988     * @see #setSaveEnabled(boolean)
9989     */
9990    protected Parcelable onSaveInstanceState() {
9991        mPrivateFlags |= SAVE_STATE_CALLED;
9992        return BaseSavedState.EMPTY_STATE;
9993    }
9994
9995    /**
9996     * Restore this view hierarchy's frozen state from the given container.
9997     *
9998     * @param container The SparseArray which holds previously frozen states.
9999     *
10000     * @see #saveHierarchyState(android.util.SparseArray)
10001     * @see #dispatchRestoreInstanceState(android.util.SparseArray)
10002     * @see #onRestoreInstanceState(android.os.Parcelable)
10003     */
10004    public void restoreHierarchyState(SparseArray<Parcelable> container) {
10005        dispatchRestoreInstanceState(container);
10006    }
10007
10008    /**
10009     * Called by {@link #restoreHierarchyState(android.util.SparseArray)} to retrieve the
10010     * state for this view and its children. May be overridden to modify how restoring
10011     * happens to a view's children; for example, some views may want to not store state
10012     * for their children.
10013     *
10014     * @param container The SparseArray which holds previously saved state.
10015     *
10016     * @see #dispatchSaveInstanceState(android.util.SparseArray)
10017     * @see #restoreHierarchyState(android.util.SparseArray)
10018     * @see #onRestoreInstanceState(android.os.Parcelable)
10019     */
10020    protected void dispatchRestoreInstanceState(SparseArray<Parcelable> container) {
10021        if (mID != NO_ID) {
10022            Parcelable state = container.get(mID);
10023            if (state != null) {
10024                // Log.i("View", "Restoreing #" + Integer.toHexString(mID)
10025                // + ": " + state);
10026                mPrivateFlags &= ~SAVE_STATE_CALLED;
10027                onRestoreInstanceState(state);
10028                if ((mPrivateFlags & SAVE_STATE_CALLED) == 0) {
10029                    throw new IllegalStateException(
10030                            "Derived class did not call super.onRestoreInstanceState()");
10031                }
10032            }
10033        }
10034    }
10035
10036    /**
10037     * Hook allowing a view to re-apply a representation of its internal state that had previously
10038     * been generated by {@link #onSaveInstanceState}. This function will never be called with a
10039     * null state.
10040     *
10041     * @param state The frozen state that had previously been returned by
10042     *        {@link #onSaveInstanceState}.
10043     *
10044     * @see #onSaveInstanceState()
10045     * @see #restoreHierarchyState(android.util.SparseArray)
10046     * @see #dispatchRestoreInstanceState(android.util.SparseArray)
10047     */
10048    protected void onRestoreInstanceState(Parcelable state) {
10049        mPrivateFlags |= SAVE_STATE_CALLED;
10050        if (state != BaseSavedState.EMPTY_STATE && state != null) {
10051            throw new IllegalArgumentException("Wrong state class, expecting View State but "
10052                    + "received " + state.getClass().toString() + " instead. This usually happens "
10053                    + "when two views of different type have the same id in the same hierarchy. "
10054                    + "This view's id is " + ViewDebug.resolveId(mContext, getId()) + ". Make sure "
10055                    + "other views do not use the same id.");
10056        }
10057    }
10058
10059    /**
10060     * <p>Return the time at which the drawing of the view hierarchy started.</p>
10061     *
10062     * @return the drawing start time in milliseconds
10063     */
10064    public long getDrawingTime() {
10065        return mAttachInfo != null ? mAttachInfo.mDrawingTime : 0;
10066    }
10067
10068    /**
10069     * <p>Enables or disables the duplication of the parent's state into this view. When
10070     * duplication is enabled, this view gets its drawable state from its parent rather
10071     * than from its own internal properties.</p>
10072     *
10073     * <p>Note: in the current implementation, setting this property to true after the
10074     * view was added to a ViewGroup might have no effect at all. This property should
10075     * always be used from XML or set to true before adding this view to a ViewGroup.</p>
10076     *
10077     * <p>Note: if this view's parent addStateFromChildren property is enabled and this
10078     * property is enabled, an exception will be thrown.</p>
10079     *
10080     * <p>Note: if the child view uses and updates additionnal states which are unknown to the
10081     * parent, these states should not be affected by this method.</p>
10082     *
10083     * @param enabled True to enable duplication of the parent's drawable state, false
10084     *                to disable it.
10085     *
10086     * @see #getDrawableState()
10087     * @see #isDuplicateParentStateEnabled()
10088     */
10089    public void setDuplicateParentStateEnabled(boolean enabled) {
10090        setFlags(enabled ? DUPLICATE_PARENT_STATE : 0, DUPLICATE_PARENT_STATE);
10091    }
10092
10093    /**
10094     * <p>Indicates whether this duplicates its drawable state from its parent.</p>
10095     *
10096     * @return True if this view's drawable state is duplicated from the parent,
10097     *         false otherwise
10098     *
10099     * @see #getDrawableState()
10100     * @see #setDuplicateParentStateEnabled(boolean)
10101     */
10102    public boolean isDuplicateParentStateEnabled() {
10103        return (mViewFlags & DUPLICATE_PARENT_STATE) == DUPLICATE_PARENT_STATE;
10104    }
10105
10106    /**
10107     * <p>Specifies the type of layer backing this view. The layer can be
10108     * {@link #LAYER_TYPE_NONE disabled}, {@link #LAYER_TYPE_SOFTWARE software} or
10109     * {@link #LAYER_TYPE_HARDWARE hardware}.</p>
10110     *
10111     * <p>A layer is associated with an optional {@link android.graphics.Paint}
10112     * instance that controls how the layer is composed on screen. The following
10113     * properties of the paint are taken into account when composing the layer:</p>
10114     * <ul>
10115     * <li>{@link android.graphics.Paint#getAlpha() Translucency (alpha)}</li>
10116     * <li>{@link android.graphics.Paint#getXfermode() Blending mode}</li>
10117     * <li>{@link android.graphics.Paint#getColorFilter() Color filter}</li>
10118     * </ul>
10119     *
10120     * <p>If this view has an alpha value set to < 1.0 by calling
10121     * {@link #setAlpha(float)}, the alpha value of the layer's paint is replaced by
10122     * this view's alpha value. Calling {@link #setAlpha(float)} is therefore
10123     * equivalent to setting a hardware layer on this view and providing a paint with
10124     * the desired alpha value.<p>
10125     *
10126     * <p>Refer to the documentation of {@link #LAYER_TYPE_NONE disabled},
10127     * {@link #LAYER_TYPE_SOFTWARE software} and {@link #LAYER_TYPE_HARDWARE hardware}
10128     * for more information on when and how to use layers.</p>
10129     *
10130     * @param layerType The ype of layer to use with this view, must be one of
10131     *        {@link #LAYER_TYPE_NONE}, {@link #LAYER_TYPE_SOFTWARE} or
10132     *        {@link #LAYER_TYPE_HARDWARE}
10133     * @param paint The paint used to compose the layer. This argument is optional
10134     *        and can be null. It is ignored when the layer type is
10135     *        {@link #LAYER_TYPE_NONE}
10136     *
10137     * @see #getLayerType()
10138     * @see #LAYER_TYPE_NONE
10139     * @see #LAYER_TYPE_SOFTWARE
10140     * @see #LAYER_TYPE_HARDWARE
10141     * @see #setAlpha(float)
10142     *
10143     * @attr ref android.R.styleable#View_layerType
10144     */
10145    public void setLayerType(int layerType, Paint paint) {
10146        if (layerType < LAYER_TYPE_NONE || layerType > LAYER_TYPE_HARDWARE) {
10147            throw new IllegalArgumentException("Layer type can only be one of: LAYER_TYPE_NONE, "
10148                    + "LAYER_TYPE_SOFTWARE or LAYER_TYPE_HARDWARE");
10149        }
10150
10151        if (layerType == mLayerType) {
10152            if (layerType != LAYER_TYPE_NONE && paint != mLayerPaint) {
10153                mLayerPaint = paint == null ? new Paint() : paint;
10154                invalidateParentCaches();
10155                invalidate(true);
10156            }
10157            return;
10158        }
10159
10160        // Destroy any previous software drawing cache if needed
10161        switch (mLayerType) {
10162            case LAYER_TYPE_HARDWARE:
10163                destroyLayer();
10164                // fall through - non-accelerated views may use software layer mechanism instead
10165            case LAYER_TYPE_SOFTWARE:
10166                destroyDrawingCache();
10167                break;
10168            default:
10169                break;
10170        }
10171
10172        mLayerType = layerType;
10173        final boolean layerDisabled = mLayerType == LAYER_TYPE_NONE;
10174        mLayerPaint = layerDisabled ? null : (paint == null ? new Paint() : paint);
10175        mLocalDirtyRect = layerDisabled ? null : new Rect();
10176
10177        invalidateParentCaches();
10178        invalidate(true);
10179    }
10180
10181    /**
10182     * Indicates whether this view has a static layer. A view with layer type
10183     * {@link #LAYER_TYPE_NONE} is a static layer. Other types of layers are
10184     * dynamic.
10185     */
10186    boolean hasStaticLayer() {
10187        return true;
10188    }
10189
10190    /**
10191     * Indicates what type of layer is currently associated with this view. By default
10192     * a view does not have a layer, and the layer type is {@link #LAYER_TYPE_NONE}.
10193     * Refer to the documentation of {@link #setLayerType(int, android.graphics.Paint)}
10194     * for more information on the different types of layers.
10195     *
10196     * @return {@link #LAYER_TYPE_NONE}, {@link #LAYER_TYPE_SOFTWARE} or
10197     *         {@link #LAYER_TYPE_HARDWARE}
10198     *
10199     * @see #setLayerType(int, android.graphics.Paint)
10200     * @see #buildLayer()
10201     * @see #LAYER_TYPE_NONE
10202     * @see #LAYER_TYPE_SOFTWARE
10203     * @see #LAYER_TYPE_HARDWARE
10204     */
10205    public int getLayerType() {
10206        return mLayerType;
10207    }
10208
10209    /**
10210     * Forces this view's layer to be created and this view to be rendered
10211     * into its layer. If this view's layer type is set to {@link #LAYER_TYPE_NONE},
10212     * invoking this method will have no effect.
10213     *
10214     * This method can for instance be used to render a view into its layer before
10215     * starting an animation. If this view is complex, rendering into the layer
10216     * before starting the animation will avoid skipping frames.
10217     *
10218     * @throws IllegalStateException If this view is not attached to a window
10219     *
10220     * @see #setLayerType(int, android.graphics.Paint)
10221     */
10222    public void buildLayer() {
10223        if (mLayerType == LAYER_TYPE_NONE) return;
10224
10225        if (mAttachInfo == null) {
10226            throw new IllegalStateException("This view must be attached to a window first");
10227        }
10228
10229        switch (mLayerType) {
10230            case LAYER_TYPE_HARDWARE:
10231                if (mAttachInfo.mHardwareRenderer != null &&
10232                        mAttachInfo.mHardwareRenderer.isEnabled() &&
10233                        mAttachInfo.mHardwareRenderer.validate()) {
10234                    getHardwareLayer();
10235                }
10236                break;
10237            case LAYER_TYPE_SOFTWARE:
10238                buildDrawingCache(true);
10239                break;
10240        }
10241    }
10242
10243    // Make sure the HardwareRenderer.validate() was invoked before calling this method
10244    void flushLayer() {
10245        if (mLayerType == LAYER_TYPE_HARDWARE && mHardwareLayer != null) {
10246            mHardwareLayer.flush();
10247        }
10248    }
10249
10250    /**
10251     * <p>Returns a hardware layer that can be used to draw this view again
10252     * without executing its draw method.</p>
10253     *
10254     * @return A HardwareLayer ready to render, or null if an error occurred.
10255     */
10256    HardwareLayer getHardwareLayer() {
10257        if (mAttachInfo == null || mAttachInfo.mHardwareRenderer == null ||
10258                !mAttachInfo.mHardwareRenderer.isEnabled()) {
10259            return null;
10260        }
10261
10262        if (!mAttachInfo.mHardwareRenderer.validate()) return null;
10263
10264        final int width = mRight - mLeft;
10265        final int height = mBottom - mTop;
10266
10267        if (width == 0 || height == 0) {
10268            return null;
10269        }
10270
10271        if ((mPrivateFlags & DRAWING_CACHE_VALID) == 0 || mHardwareLayer == null) {
10272            if (mHardwareLayer == null) {
10273                mHardwareLayer = mAttachInfo.mHardwareRenderer.createHardwareLayer(
10274                        width, height, isOpaque());
10275                mLocalDirtyRect.setEmpty();
10276            } else if (mHardwareLayer.getWidth() != width || mHardwareLayer.getHeight() != height) {
10277                mHardwareLayer.resize(width, height);
10278                mLocalDirtyRect.setEmpty();
10279            }
10280
10281            // The layer is not valid if the underlying GPU resources cannot be allocated
10282            if (!mHardwareLayer.isValid()) {
10283                return null;
10284            }
10285
10286            mHardwareLayer.redraw(getDisplayList(), mLocalDirtyRect);
10287            mLocalDirtyRect.setEmpty();
10288        }
10289
10290        return mHardwareLayer;
10291    }
10292
10293    /**
10294     * Destroys this View's hardware layer if possible.
10295     *
10296     * @return True if the layer was destroyed, false otherwise.
10297     *
10298     * @see #setLayerType(int, android.graphics.Paint)
10299     * @see #LAYER_TYPE_HARDWARE
10300     */
10301    boolean destroyLayer() {
10302        if (mHardwareLayer != null) {
10303            AttachInfo info = mAttachInfo;
10304            if (info != null && info.mHardwareRenderer != null &&
10305                    info.mHardwareRenderer.isEnabled() && info.mHardwareRenderer.validate()) {
10306                mHardwareLayer.destroy();
10307                mHardwareLayer = null;
10308
10309                invalidate(true);
10310                invalidateParentCaches();
10311            }
10312            return true;
10313        }
10314        return false;
10315    }
10316
10317    /**
10318     * Destroys all hardware rendering resources. This method is invoked
10319     * when the system needs to reclaim resources. Upon execution of this
10320     * method, you should free any OpenGL resources created by the view.
10321     *
10322     * Note: you <strong>must</strong> call
10323     * <code>super.destroyHardwareResources()</code> when overriding
10324     * this method.
10325     *
10326     * @hide
10327     */
10328    protected void destroyHardwareResources() {
10329        destroyLayer();
10330    }
10331
10332    /**
10333     * <p>Enables or disables the drawing cache. When the drawing cache is enabled, the next call
10334     * to {@link #getDrawingCache()} or {@link #buildDrawingCache()} will draw the view in a
10335     * bitmap. Calling {@link #draw(android.graphics.Canvas)} will not draw from the cache when
10336     * the cache is enabled. To benefit from the cache, you must request the drawing cache by
10337     * calling {@link #getDrawingCache()} and draw it on screen if the returned bitmap is not
10338     * null.</p>
10339     *
10340     * <p>Enabling the drawing cache is similar to
10341     * {@link #setLayerType(int, android.graphics.Paint) setting a layer} when hardware
10342     * acceleration is turned off. When hardware acceleration is turned on, enabling the
10343     * drawing cache has no effect on rendering because the system uses a different mechanism
10344     * for acceleration which ignores the flag. If you want to use a Bitmap for the view, even
10345     * when hardware acceleration is enabled, see {@link #setLayerType(int, android.graphics.Paint)}
10346     * for information on how to enable software and hardware layers.</p>
10347     *
10348     * <p>This API can be used to manually generate
10349     * a bitmap copy of this view, by setting the flag to <code>true</code> and calling
10350     * {@link #getDrawingCache()}.</p>
10351     *
10352     * @param enabled true to enable the drawing cache, false otherwise
10353     *
10354     * @see #isDrawingCacheEnabled()
10355     * @see #getDrawingCache()
10356     * @see #buildDrawingCache()
10357     * @see #setLayerType(int, android.graphics.Paint)
10358     */
10359    public void setDrawingCacheEnabled(boolean enabled) {
10360        mCachingFailed = false;
10361        setFlags(enabled ? DRAWING_CACHE_ENABLED : 0, DRAWING_CACHE_ENABLED);
10362    }
10363
10364    /**
10365     * <p>Indicates whether the drawing cache is enabled for this view.</p>
10366     *
10367     * @return true if the drawing cache is enabled
10368     *
10369     * @see #setDrawingCacheEnabled(boolean)
10370     * @see #getDrawingCache()
10371     */
10372    @ViewDebug.ExportedProperty(category = "drawing")
10373    public boolean isDrawingCacheEnabled() {
10374        return (mViewFlags & DRAWING_CACHE_ENABLED) == DRAWING_CACHE_ENABLED;
10375    }
10376
10377    /**
10378     * Debugging utility which recursively outputs the dirty state of a view and its
10379     * descendants.
10380     *
10381     * @hide
10382     */
10383    @SuppressWarnings({"UnusedDeclaration"})
10384    public void outputDirtyFlags(String indent, boolean clear, int clearMask) {
10385        Log.d("View", indent + this + "             DIRTY(" + (mPrivateFlags & View.DIRTY_MASK) +
10386                ") DRAWN(" + (mPrivateFlags & DRAWN) + ")" + " CACHE_VALID(" +
10387                (mPrivateFlags & View.DRAWING_CACHE_VALID) +
10388                ") INVALIDATED(" + (mPrivateFlags & INVALIDATED) + ")");
10389        if (clear) {
10390            mPrivateFlags &= clearMask;
10391        }
10392        if (this instanceof ViewGroup) {
10393            ViewGroup parent = (ViewGroup) this;
10394            final int count = parent.getChildCount();
10395            for (int i = 0; i < count; i++) {
10396                final View child = parent.getChildAt(i);
10397                child.outputDirtyFlags(indent + "  ", clear, clearMask);
10398            }
10399        }
10400    }
10401
10402    /**
10403     * This method is used by ViewGroup to cause its children to restore or recreate their
10404     * display lists. It is called by getDisplayList() when the parent ViewGroup does not need
10405     * to recreate its own display list, which would happen if it went through the normal
10406     * draw/dispatchDraw mechanisms.
10407     *
10408     * @hide
10409     */
10410    protected void dispatchGetDisplayList() {}
10411
10412    /**
10413     * A view that is not attached or hardware accelerated cannot create a display list.
10414     * This method checks these conditions and returns the appropriate result.
10415     *
10416     * @return true if view has the ability to create a display list, false otherwise.
10417     *
10418     * @hide
10419     */
10420    public boolean canHaveDisplayList() {
10421        return !(mAttachInfo == null || mAttachInfo.mHardwareRenderer == null);
10422    }
10423
10424    /**
10425     * @return The HardwareRenderer associated with that view or null if hardware rendering
10426     * is not supported or this this has not been attached to a window.
10427     *
10428     * @hide
10429     */
10430    public HardwareRenderer getHardwareRenderer() {
10431        if (mAttachInfo != null) {
10432            return mAttachInfo.mHardwareRenderer;
10433        }
10434        return null;
10435    }
10436
10437    /**
10438     * <p>Returns a display list that can be used to draw this view again
10439     * without executing its draw method.</p>
10440     *
10441     * @return A DisplayList ready to replay, or null if caching is not enabled.
10442     *
10443     * @hide
10444     */
10445    public DisplayList getDisplayList() {
10446        if (!canHaveDisplayList()) {
10447            return null;
10448        }
10449
10450        if (((mPrivateFlags & DRAWING_CACHE_VALID) == 0 ||
10451                mDisplayList == null || !mDisplayList.isValid() ||
10452                mRecreateDisplayList)) {
10453            // Don't need to recreate the display list, just need to tell our
10454            // children to restore/recreate theirs
10455            if (mDisplayList != null && mDisplayList.isValid() &&
10456                    !mRecreateDisplayList) {
10457                mPrivateFlags |= DRAWN | DRAWING_CACHE_VALID;
10458                mPrivateFlags &= ~DIRTY_MASK;
10459                dispatchGetDisplayList();
10460
10461                return mDisplayList;
10462            }
10463
10464            // If we got here, we're recreating it. Mark it as such to ensure that
10465            // we copy in child display lists into ours in drawChild()
10466            mRecreateDisplayList = true;
10467            if (mDisplayList == null) {
10468                final String name = getClass().getSimpleName();
10469                mDisplayList = mAttachInfo.mHardwareRenderer.createDisplayList(name);
10470                // If we're creating a new display list, make sure our parent gets invalidated
10471                // since they will need to recreate their display list to account for this
10472                // new child display list.
10473                invalidateParentCaches();
10474            }
10475
10476            final HardwareCanvas canvas = mDisplayList.start();
10477            int restoreCount = 0;
10478            try {
10479                int width = mRight - mLeft;
10480                int height = mBottom - mTop;
10481
10482                canvas.setViewport(width, height);
10483                // The dirty rect should always be null for a display list
10484                canvas.onPreDraw(null);
10485
10486                computeScroll();
10487
10488                restoreCount = canvas.save();
10489                canvas.translate(-mScrollX, -mScrollY);
10490                mPrivateFlags |= DRAWN | DRAWING_CACHE_VALID;
10491                mPrivateFlags &= ~DIRTY_MASK;
10492
10493                // Fast path for layouts with no backgrounds
10494                if ((mPrivateFlags & SKIP_DRAW) == SKIP_DRAW) {
10495                    dispatchDraw(canvas);
10496                } else {
10497                    draw(canvas);
10498                }
10499            } finally {
10500                canvas.restoreToCount(restoreCount);
10501                canvas.onPostDraw();
10502
10503                mDisplayList.end();
10504            }
10505        } else {
10506            mPrivateFlags |= DRAWN | DRAWING_CACHE_VALID;
10507            mPrivateFlags &= ~DIRTY_MASK;
10508        }
10509
10510        return mDisplayList;
10511    }
10512
10513    /**
10514     * <p>Calling this method is equivalent to calling <code>getDrawingCache(false)</code>.</p>
10515     *
10516     * @return A non-scaled bitmap representing this view or null if cache is disabled.
10517     *
10518     * @see #getDrawingCache(boolean)
10519     */
10520    public Bitmap getDrawingCache() {
10521        return getDrawingCache(false);
10522    }
10523
10524    /**
10525     * <p>Returns the bitmap in which this view drawing is cached. The returned bitmap
10526     * is null when caching is disabled. If caching is enabled and the cache is not ready,
10527     * this method will create it. Calling {@link #draw(android.graphics.Canvas)} will not
10528     * draw from the cache when the cache is enabled. To benefit from the cache, you must
10529     * request the drawing cache by calling this method and draw it on screen if the
10530     * returned bitmap is not null.</p>
10531     *
10532     * <p>Note about auto scaling in compatibility mode: When auto scaling is not enabled,
10533     * this method will create a bitmap of the same size as this view. Because this bitmap
10534     * will be drawn scaled by the parent ViewGroup, the result on screen might show
10535     * scaling artifacts. To avoid such artifacts, you should call this method by setting
10536     * the auto scaling to true. Doing so, however, will generate a bitmap of a different
10537     * size than the view. This implies that your application must be able to handle this
10538     * size.</p>
10539     *
10540     * @param autoScale Indicates whether the generated bitmap should be scaled based on
10541     *        the current density of the screen when the application is in compatibility
10542     *        mode.
10543     *
10544     * @return A bitmap representing this view or null if cache is disabled.
10545     *
10546     * @see #setDrawingCacheEnabled(boolean)
10547     * @see #isDrawingCacheEnabled()
10548     * @see #buildDrawingCache(boolean)
10549     * @see #destroyDrawingCache()
10550     */
10551    public Bitmap getDrawingCache(boolean autoScale) {
10552        if ((mViewFlags & WILL_NOT_CACHE_DRAWING) == WILL_NOT_CACHE_DRAWING) {
10553            return null;
10554        }
10555        if ((mViewFlags & DRAWING_CACHE_ENABLED) == DRAWING_CACHE_ENABLED) {
10556            buildDrawingCache(autoScale);
10557        }
10558        return autoScale ? mDrawingCache : mUnscaledDrawingCache;
10559    }
10560
10561    /**
10562     * <p>Frees the resources used by the drawing cache. If you call
10563     * {@link #buildDrawingCache()} manually without calling
10564     * {@link #setDrawingCacheEnabled(boolean) setDrawingCacheEnabled(true)}, you
10565     * should cleanup the cache with this method afterwards.</p>
10566     *
10567     * @see #setDrawingCacheEnabled(boolean)
10568     * @see #buildDrawingCache()
10569     * @see #getDrawingCache()
10570     */
10571    public void destroyDrawingCache() {
10572        if (mDrawingCache != null) {
10573            mDrawingCache.recycle();
10574            mDrawingCache = null;
10575        }
10576        if (mUnscaledDrawingCache != null) {
10577            mUnscaledDrawingCache.recycle();
10578            mUnscaledDrawingCache = null;
10579        }
10580    }
10581
10582    /**
10583     * Setting a solid background color for the drawing cache's bitmaps will improve
10584     * performance and memory usage. Note, though that this should only be used if this
10585     * view will always be drawn on top of a solid color.
10586     *
10587     * @param color The background color to use for the drawing cache's bitmap
10588     *
10589     * @see #setDrawingCacheEnabled(boolean)
10590     * @see #buildDrawingCache()
10591     * @see #getDrawingCache()
10592     */
10593    public void setDrawingCacheBackgroundColor(int color) {
10594        if (color != mDrawingCacheBackgroundColor) {
10595            mDrawingCacheBackgroundColor = color;
10596            mPrivateFlags &= ~DRAWING_CACHE_VALID;
10597        }
10598    }
10599
10600    /**
10601     * @see #setDrawingCacheBackgroundColor(int)
10602     *
10603     * @return The background color to used for the drawing cache's bitmap
10604     */
10605    public int getDrawingCacheBackgroundColor() {
10606        return mDrawingCacheBackgroundColor;
10607    }
10608
10609    /**
10610     * <p>Calling this method is equivalent to calling <code>buildDrawingCache(false)</code>.</p>
10611     *
10612     * @see #buildDrawingCache(boolean)
10613     */
10614    public void buildDrawingCache() {
10615        buildDrawingCache(false);
10616    }
10617
10618    /**
10619     * <p>Forces the drawing cache to be built if the drawing cache is invalid.</p>
10620     *
10621     * <p>If you call {@link #buildDrawingCache()} manually without calling
10622     * {@link #setDrawingCacheEnabled(boolean) setDrawingCacheEnabled(true)}, you
10623     * should cleanup the cache by calling {@link #destroyDrawingCache()} afterwards.</p>
10624     *
10625     * <p>Note about auto scaling in compatibility mode: When auto scaling is not enabled,
10626     * this method will create a bitmap of the same size as this view. Because this bitmap
10627     * will be drawn scaled by the parent ViewGroup, the result on screen might show
10628     * scaling artifacts. To avoid such artifacts, you should call this method by setting
10629     * the auto scaling to true. Doing so, however, will generate a bitmap of a different
10630     * size than the view. This implies that your application must be able to handle this
10631     * size.</p>
10632     *
10633     * <p>You should avoid calling this method when hardware acceleration is enabled. If
10634     * you do not need the drawing cache bitmap, calling this method will increase memory
10635     * usage and cause the view to be rendered in software once, thus negatively impacting
10636     * performance.</p>
10637     *
10638     * @see #getDrawingCache()
10639     * @see #destroyDrawingCache()
10640     */
10641    public void buildDrawingCache(boolean autoScale) {
10642        if ((mPrivateFlags & DRAWING_CACHE_VALID) == 0 || (autoScale ?
10643                mDrawingCache == null : mUnscaledDrawingCache == null)) {
10644            mCachingFailed = false;
10645
10646            if (ViewDebug.TRACE_HIERARCHY) {
10647                ViewDebug.trace(this, ViewDebug.HierarchyTraceType.BUILD_CACHE);
10648            }
10649
10650            int width = mRight - mLeft;
10651            int height = mBottom - mTop;
10652
10653            final AttachInfo attachInfo = mAttachInfo;
10654            final boolean scalingRequired = attachInfo != null && attachInfo.mScalingRequired;
10655
10656            if (autoScale && scalingRequired) {
10657                width = (int) ((width * attachInfo.mApplicationScale) + 0.5f);
10658                height = (int) ((height * attachInfo.mApplicationScale) + 0.5f);
10659            }
10660
10661            final int drawingCacheBackgroundColor = mDrawingCacheBackgroundColor;
10662            final boolean opaque = drawingCacheBackgroundColor != 0 || isOpaque();
10663            final boolean use32BitCache = attachInfo != null && attachInfo.mUse32BitDrawingCache;
10664
10665            if (width <= 0 || height <= 0 ||
10666                     // Projected bitmap size in bytes
10667                    (width * height * (opaque && !use32BitCache ? 2 : 4) >
10668                            ViewConfiguration.get(mContext).getScaledMaximumDrawingCacheSize())) {
10669                destroyDrawingCache();
10670                mCachingFailed = true;
10671                return;
10672            }
10673
10674            boolean clear = true;
10675            Bitmap bitmap = autoScale ? mDrawingCache : mUnscaledDrawingCache;
10676
10677            if (bitmap == null || bitmap.getWidth() != width || bitmap.getHeight() != height) {
10678                Bitmap.Config quality;
10679                if (!opaque) {
10680                    // Never pick ARGB_4444 because it looks awful
10681                    // Keep the DRAWING_CACHE_QUALITY_LOW flag just in case
10682                    switch (mViewFlags & DRAWING_CACHE_QUALITY_MASK) {
10683                        case DRAWING_CACHE_QUALITY_AUTO:
10684                            quality = Bitmap.Config.ARGB_8888;
10685                            break;
10686                        case DRAWING_CACHE_QUALITY_LOW:
10687                            quality = Bitmap.Config.ARGB_8888;
10688                            break;
10689                        case DRAWING_CACHE_QUALITY_HIGH:
10690                            quality = Bitmap.Config.ARGB_8888;
10691                            break;
10692                        default:
10693                            quality = Bitmap.Config.ARGB_8888;
10694                            break;
10695                    }
10696                } else {
10697                    // Optimization for translucent windows
10698                    // If the window is translucent, use a 32 bits bitmap to benefit from memcpy()
10699                    quality = use32BitCache ? Bitmap.Config.ARGB_8888 : Bitmap.Config.RGB_565;
10700                }
10701
10702                // Try to cleanup memory
10703                if (bitmap != null) bitmap.recycle();
10704
10705                try {
10706                    bitmap = Bitmap.createBitmap(width, height, quality);
10707                    bitmap.setDensity(getResources().getDisplayMetrics().densityDpi);
10708                    if (autoScale) {
10709                        mDrawingCache = bitmap;
10710                    } else {
10711                        mUnscaledDrawingCache = bitmap;
10712                    }
10713                    if (opaque && use32BitCache) bitmap.setHasAlpha(false);
10714                } catch (OutOfMemoryError e) {
10715                    // If there is not enough memory to create the bitmap cache, just
10716                    // ignore the issue as bitmap caches are not required to draw the
10717                    // view hierarchy
10718                    if (autoScale) {
10719                        mDrawingCache = null;
10720                    } else {
10721                        mUnscaledDrawingCache = null;
10722                    }
10723                    mCachingFailed = true;
10724                    return;
10725                }
10726
10727                clear = drawingCacheBackgroundColor != 0;
10728            }
10729
10730            Canvas canvas;
10731            if (attachInfo != null) {
10732                canvas = attachInfo.mCanvas;
10733                if (canvas == null) {
10734                    canvas = new Canvas();
10735                }
10736                canvas.setBitmap(bitmap);
10737                // Temporarily clobber the cached Canvas in case one of our children
10738                // is also using a drawing cache. Without this, the children would
10739                // steal the canvas by attaching their own bitmap to it and bad, bad
10740                // thing would happen (invisible views, corrupted drawings, etc.)
10741                attachInfo.mCanvas = null;
10742            } else {
10743                // This case should hopefully never or seldom happen
10744                canvas = new Canvas(bitmap);
10745            }
10746
10747            if (clear) {
10748                bitmap.eraseColor(drawingCacheBackgroundColor);
10749            }
10750
10751            computeScroll();
10752            final int restoreCount = canvas.save();
10753
10754            if (autoScale && scalingRequired) {
10755                final float scale = attachInfo.mApplicationScale;
10756                canvas.scale(scale, scale);
10757            }
10758
10759            canvas.translate(-mScrollX, -mScrollY);
10760
10761            mPrivateFlags |= DRAWN;
10762            if (mAttachInfo == null || !mAttachInfo.mHardwareAccelerated ||
10763                    mLayerType != LAYER_TYPE_NONE) {
10764                mPrivateFlags |= DRAWING_CACHE_VALID;
10765            }
10766
10767            // Fast path for layouts with no backgrounds
10768            if ((mPrivateFlags & SKIP_DRAW) == SKIP_DRAW) {
10769                if (ViewDebug.TRACE_HIERARCHY) {
10770                    ViewDebug.trace(this, ViewDebug.HierarchyTraceType.DRAW);
10771                }
10772                mPrivateFlags &= ~DIRTY_MASK;
10773                dispatchDraw(canvas);
10774            } else {
10775                draw(canvas);
10776            }
10777
10778            canvas.restoreToCount(restoreCount);
10779            canvas.setBitmap(null);
10780
10781            if (attachInfo != null) {
10782                // Restore the cached Canvas for our siblings
10783                attachInfo.mCanvas = canvas;
10784            }
10785        }
10786    }
10787
10788    /**
10789     * Create a snapshot of the view into a bitmap.  We should probably make
10790     * some form of this public, but should think about the API.
10791     */
10792    Bitmap createSnapshot(Bitmap.Config quality, int backgroundColor, boolean skipChildren) {
10793        int width = mRight - mLeft;
10794        int height = mBottom - mTop;
10795
10796        final AttachInfo attachInfo = mAttachInfo;
10797        final float scale = attachInfo != null ? attachInfo.mApplicationScale : 1.0f;
10798        width = (int) ((width * scale) + 0.5f);
10799        height = (int) ((height * scale) + 0.5f);
10800
10801        Bitmap bitmap = Bitmap.createBitmap(width > 0 ? width : 1, height > 0 ? height : 1, quality);
10802        if (bitmap == null) {
10803            throw new OutOfMemoryError();
10804        }
10805
10806        Resources resources = getResources();
10807        if (resources != null) {
10808            bitmap.setDensity(resources.getDisplayMetrics().densityDpi);
10809        }
10810
10811        Canvas canvas;
10812        if (attachInfo != null) {
10813            canvas = attachInfo.mCanvas;
10814            if (canvas == null) {
10815                canvas = new Canvas();
10816            }
10817            canvas.setBitmap(bitmap);
10818            // Temporarily clobber the cached Canvas in case one of our children
10819            // is also using a drawing cache. Without this, the children would
10820            // steal the canvas by attaching their own bitmap to it and bad, bad
10821            // things would happen (invisible views, corrupted drawings, etc.)
10822            attachInfo.mCanvas = null;
10823        } else {
10824            // This case should hopefully never or seldom happen
10825            canvas = new Canvas(bitmap);
10826        }
10827
10828        if ((backgroundColor & 0xff000000) != 0) {
10829            bitmap.eraseColor(backgroundColor);
10830        }
10831
10832        computeScroll();
10833        final int restoreCount = canvas.save();
10834        canvas.scale(scale, scale);
10835        canvas.translate(-mScrollX, -mScrollY);
10836
10837        // Temporarily remove the dirty mask
10838        int flags = mPrivateFlags;
10839        mPrivateFlags &= ~DIRTY_MASK;
10840
10841        // Fast path for layouts with no backgrounds
10842        if ((mPrivateFlags & SKIP_DRAW) == SKIP_DRAW) {
10843            dispatchDraw(canvas);
10844        } else {
10845            draw(canvas);
10846        }
10847
10848        mPrivateFlags = flags;
10849
10850        canvas.restoreToCount(restoreCount);
10851        canvas.setBitmap(null);
10852
10853        if (attachInfo != null) {
10854            // Restore the cached Canvas for our siblings
10855            attachInfo.mCanvas = canvas;
10856        }
10857
10858        return bitmap;
10859    }
10860
10861    /**
10862     * Indicates whether this View is currently in edit mode. A View is usually
10863     * in edit mode when displayed within a developer tool. For instance, if
10864     * this View is being drawn by a visual user interface builder, this method
10865     * should return true.
10866     *
10867     * Subclasses should check the return value of this method to provide
10868     * different behaviors if their normal behavior might interfere with the
10869     * host environment. For instance: the class spawns a thread in its
10870     * constructor, the drawing code relies on device-specific features, etc.
10871     *
10872     * This method is usually checked in the drawing code of custom widgets.
10873     *
10874     * @return True if this View is in edit mode, false otherwise.
10875     */
10876    public boolean isInEditMode() {
10877        return false;
10878    }
10879
10880    /**
10881     * If the View draws content inside its padding and enables fading edges,
10882     * it needs to support padding offsets. Padding offsets are added to the
10883     * fading edges to extend the length of the fade so that it covers pixels
10884     * drawn inside the padding.
10885     *
10886     * Subclasses of this class should override this method if they need
10887     * to draw content inside the padding.
10888     *
10889     * @return True if padding offset must be applied, false otherwise.
10890     *
10891     * @see #getLeftPaddingOffset()
10892     * @see #getRightPaddingOffset()
10893     * @see #getTopPaddingOffset()
10894     * @see #getBottomPaddingOffset()
10895     *
10896     * @since CURRENT
10897     */
10898    protected boolean isPaddingOffsetRequired() {
10899        return false;
10900    }
10901
10902    /**
10903     * Amount by which to extend the left fading region. Called only when
10904     * {@link #isPaddingOffsetRequired()} returns true.
10905     *
10906     * @return The left padding offset in pixels.
10907     *
10908     * @see #isPaddingOffsetRequired()
10909     *
10910     * @since CURRENT
10911     */
10912    protected int getLeftPaddingOffset() {
10913        return 0;
10914    }
10915
10916    /**
10917     * Amount by which to extend the right fading region. Called only when
10918     * {@link #isPaddingOffsetRequired()} returns true.
10919     *
10920     * @return The right padding offset in pixels.
10921     *
10922     * @see #isPaddingOffsetRequired()
10923     *
10924     * @since CURRENT
10925     */
10926    protected int getRightPaddingOffset() {
10927        return 0;
10928    }
10929
10930    /**
10931     * Amount by which to extend the top fading region. Called only when
10932     * {@link #isPaddingOffsetRequired()} returns true.
10933     *
10934     * @return The top padding offset in pixels.
10935     *
10936     * @see #isPaddingOffsetRequired()
10937     *
10938     * @since CURRENT
10939     */
10940    protected int getTopPaddingOffset() {
10941        return 0;
10942    }
10943
10944    /**
10945     * Amount by which to extend the bottom fading region. Called only when
10946     * {@link #isPaddingOffsetRequired()} returns true.
10947     *
10948     * @return The bottom padding offset in pixels.
10949     *
10950     * @see #isPaddingOffsetRequired()
10951     *
10952     * @since CURRENT
10953     */
10954    protected int getBottomPaddingOffset() {
10955        return 0;
10956    }
10957
10958    /**
10959     * @hide
10960     * @param offsetRequired
10961     */
10962    protected int getFadeTop(boolean offsetRequired) {
10963        int top = mPaddingTop;
10964        if (offsetRequired) top += getTopPaddingOffset();
10965        return top;
10966    }
10967
10968    /**
10969     * @hide
10970     * @param offsetRequired
10971     */
10972    protected int getFadeHeight(boolean offsetRequired) {
10973        int padding = mPaddingTop;
10974        if (offsetRequired) padding += getTopPaddingOffset();
10975        return mBottom - mTop - mPaddingBottom - padding;
10976    }
10977
10978    /**
10979     * <p>Indicates whether this view is attached to an hardware accelerated
10980     * window or not.</p>
10981     *
10982     * <p>Even if this method returns true, it does not mean that every call
10983     * to {@link #draw(android.graphics.Canvas)} will be made with an hardware
10984     * accelerated {@link android.graphics.Canvas}. For instance, if this view
10985     * is drawn onto an offscren {@link android.graphics.Bitmap} and its
10986     * window is hardware accelerated,
10987     * {@link android.graphics.Canvas#isHardwareAccelerated()} will likely
10988     * return false, and this method will return true.</p>
10989     *
10990     * @return True if the view is attached to a window and the window is
10991     *         hardware accelerated; false in any other case.
10992     */
10993    public boolean isHardwareAccelerated() {
10994        return mAttachInfo != null && mAttachInfo.mHardwareAccelerated;
10995    }
10996
10997    /**
10998     * Utility function, called by draw(canvas, parent, drawingTime) to handle the less common
10999     * case of an active Animation being run on the view.
11000     */
11001    private boolean drawAnimation(ViewGroup parent, long drawingTime,
11002            Animation a, boolean scalingRequired) {
11003        Transformation invalidationTransform;
11004        final int flags = parent.mGroupFlags;
11005        final boolean initialized = a.isInitialized();
11006        if (!initialized) {
11007            a.initialize(mRight - mLeft, mBottom - mTop, getWidth(), getHeight());
11008            a.initializeInvalidateRegion(0, 0, mRight - mLeft, mBottom - mTop);
11009            onAnimationStart();
11010        }
11011
11012        boolean more = a.getTransformation(drawingTime, parent.mChildTransformation, 1f);
11013        if (scalingRequired && mAttachInfo.mApplicationScale != 1f) {
11014            if (parent.mInvalidationTransformation == null) {
11015                parent.mInvalidationTransformation = new Transformation();
11016            }
11017            invalidationTransform = parent.mInvalidationTransformation;
11018            a.getTransformation(drawingTime, invalidationTransform, 1f);
11019        } else {
11020            invalidationTransform = parent.mChildTransformation;
11021        }
11022        if (more) {
11023            if (!a.willChangeBounds()) {
11024                if ((flags & (parent.FLAG_OPTIMIZE_INVALIDATE | parent.FLAG_ANIMATION_DONE)) ==
11025                        parent.FLAG_OPTIMIZE_INVALIDATE) {
11026                    parent.mGroupFlags |= parent.FLAG_INVALIDATE_REQUIRED;
11027                } else if ((flags & parent.FLAG_INVALIDATE_REQUIRED) == 0) {
11028                    // The child need to draw an animation, potentially offscreen, so
11029                    // make sure we do not cancel invalidate requests
11030                    parent.mPrivateFlags |= DRAW_ANIMATION;
11031                    parent.invalidate(mLeft, mTop, mRight, mBottom);
11032                }
11033            } else {
11034                if (parent.mInvalidateRegion == null) {
11035                    parent.mInvalidateRegion = new RectF();
11036                }
11037                final RectF region = parent.mInvalidateRegion;
11038                a.getInvalidateRegion(0, 0, mRight - mLeft, mBottom - mTop, region,
11039                        invalidationTransform);
11040
11041                // The child need to draw an animation, potentially offscreen, so
11042                // make sure we do not cancel invalidate requests
11043                parent.mPrivateFlags |= DRAW_ANIMATION;
11044
11045                final int left = mLeft + (int) region.left;
11046                final int top = mTop + (int) region.top;
11047                parent.invalidate(left, top, left + (int) (region.width() + .5f),
11048                        top + (int) (region.height() + .5f));
11049            }
11050        }
11051        return more;
11052    }
11053
11054    /**
11055     * This method is called by ViewGroup.drawChild() to have each child view draw itself.
11056     * This draw() method is an implementation detail and is not intended to be overridden or
11057     * to be called from anywhere else other than ViewGroup.drawChild().
11058     */
11059    boolean draw(Canvas canvas, ViewGroup parent, long drawingTime) {
11060        boolean more = false;
11061        final boolean childHasIdentityMatrix = hasIdentityMatrix();
11062        final int flags = parent.mGroupFlags;
11063
11064        if ((flags & parent.FLAG_CLEAR_TRANSFORMATION) == parent.FLAG_CLEAR_TRANSFORMATION) {
11065            parent.mChildTransformation.clear();
11066            parent.mGroupFlags &= ~parent.FLAG_CLEAR_TRANSFORMATION;
11067        }
11068
11069        Transformation transformToApply = null;
11070        boolean concatMatrix = false;
11071
11072        boolean scalingRequired = false;
11073        boolean caching;
11074        int layerType = parent.mDrawLayers ? getLayerType() : LAYER_TYPE_NONE;
11075
11076        final boolean hardwareAccelerated = canvas.isHardwareAccelerated();
11077        if ((flags & parent.FLAG_CHILDREN_DRAWN_WITH_CACHE) == parent.FLAG_CHILDREN_DRAWN_WITH_CACHE ||
11078                (flags & parent.FLAG_ALWAYS_DRAWN_WITH_CACHE) == parent.FLAG_ALWAYS_DRAWN_WITH_CACHE) {
11079            caching = true;
11080            if (mAttachInfo != null) scalingRequired = mAttachInfo.mScalingRequired;
11081        } else {
11082            caching = (layerType != LAYER_TYPE_NONE) || hardwareAccelerated;
11083        }
11084
11085        final Animation a = getAnimation();
11086        if (a != null) {
11087            more = drawAnimation(parent, drawingTime, a, scalingRequired);
11088            concatMatrix = a.willChangeTransformationMatrix();
11089            transformToApply = parent.mChildTransformation;
11090        } else if ((flags & parent.FLAG_SUPPORT_STATIC_TRANSFORMATIONS) ==
11091                parent.FLAG_SUPPORT_STATIC_TRANSFORMATIONS) {
11092            final boolean hasTransform =
11093                    parent.getChildStaticTransformation(this, parent.mChildTransformation);
11094            if (hasTransform) {
11095                final int transformType = parent.mChildTransformation.getTransformationType();
11096                transformToApply = transformType != Transformation.TYPE_IDENTITY ?
11097                        parent.mChildTransformation : null;
11098                concatMatrix = (transformType & Transformation.TYPE_MATRIX) != 0;
11099            }
11100        }
11101
11102        concatMatrix |= !childHasIdentityMatrix;
11103
11104        // Sets the flag as early as possible to allow draw() implementations
11105        // to call invalidate() successfully when doing animations
11106        mPrivateFlags |= DRAWN;
11107
11108        if (!concatMatrix && canvas.quickReject(mLeft, mTop, mRight, mBottom, Canvas.EdgeType.BW) &&
11109                (mPrivateFlags & DRAW_ANIMATION) == 0) {
11110            return more;
11111        }
11112
11113        if (hardwareAccelerated) {
11114            // Clear INVALIDATED flag to allow invalidation to occur during rendering, but
11115            // retain the flag's value temporarily in the mRecreateDisplayList flag
11116            mRecreateDisplayList = (mPrivateFlags & INVALIDATED) == INVALIDATED;
11117            mPrivateFlags &= ~INVALIDATED;
11118        }
11119
11120        computeScroll();
11121
11122        final int sx = mScrollX;
11123        final int sy = mScrollY;
11124
11125        DisplayList displayList = null;
11126        Bitmap cache = null;
11127        boolean hasDisplayList = false;
11128        if (caching) {
11129            if (!hardwareAccelerated) {
11130                if (layerType != LAYER_TYPE_NONE) {
11131                    layerType = LAYER_TYPE_SOFTWARE;
11132                    buildDrawingCache(true);
11133                }
11134                cache = getDrawingCache(true);
11135            } else {
11136                switch (layerType) {
11137                    case LAYER_TYPE_SOFTWARE:
11138                        buildDrawingCache(true);
11139                        cache = getDrawingCache(true);
11140                        break;
11141                    case LAYER_TYPE_NONE:
11142                        // Delay getting the display list until animation-driven alpha values are
11143                        // set up and possibly passed on to the view
11144                        hasDisplayList = canHaveDisplayList();
11145                        break;
11146                }
11147            }
11148        }
11149
11150        final boolean hasNoCache = cache == null || hasDisplayList;
11151        final boolean offsetForScroll = cache == null && !hasDisplayList &&
11152                layerType != LAYER_TYPE_HARDWARE;
11153
11154        final int restoreTo = canvas.save();
11155        if (offsetForScroll) {
11156            canvas.translate(mLeft - sx, mTop - sy);
11157        } else {
11158            canvas.translate(mLeft, mTop);
11159            if (scalingRequired) {
11160                // mAttachInfo cannot be null, otherwise scalingRequired == false
11161                final float scale = 1.0f / mAttachInfo.mApplicationScale;
11162                canvas.scale(scale, scale);
11163            }
11164        }
11165
11166        float alpha = getAlpha();
11167        if (transformToApply != null || alpha < 1.0f || !hasIdentityMatrix()) {
11168            if (transformToApply != null || !childHasIdentityMatrix) {
11169                int transX = 0;
11170                int transY = 0;
11171
11172                if (offsetForScroll) {
11173                    transX = -sx;
11174                    transY = -sy;
11175                }
11176
11177                if (transformToApply != null) {
11178                    if (concatMatrix) {
11179                        // Undo the scroll translation, apply the transformation matrix,
11180                        // then redo the scroll translate to get the correct result.
11181                        canvas.translate(-transX, -transY);
11182                        canvas.concat(transformToApply.getMatrix());
11183                        canvas.translate(transX, transY);
11184                        parent.mGroupFlags |= parent.FLAG_CLEAR_TRANSFORMATION;
11185                    }
11186
11187                    float transformAlpha = transformToApply.getAlpha();
11188                    if (transformAlpha < 1.0f) {
11189                        alpha *= transformToApply.getAlpha();
11190                        parent.mGroupFlags |= parent.FLAG_CLEAR_TRANSFORMATION;
11191                    }
11192                }
11193
11194                if (!childHasIdentityMatrix) {
11195                    canvas.translate(-transX, -transY);
11196                    canvas.concat(getMatrix());
11197                    canvas.translate(transX, transY);
11198                }
11199            }
11200
11201            if (alpha < 1.0f) {
11202                parent.mGroupFlags |= parent.FLAG_CLEAR_TRANSFORMATION;
11203                if (hasNoCache) {
11204                    final int multipliedAlpha = (int) (255 * alpha);
11205                    if (!onSetAlpha(multipliedAlpha)) {
11206                        int layerFlags = Canvas.HAS_ALPHA_LAYER_SAVE_FLAG;
11207                        if ((flags & parent.FLAG_CLIP_CHILDREN) == parent.FLAG_CLIP_CHILDREN ||
11208                                layerType != LAYER_TYPE_NONE) {
11209                            layerFlags |= Canvas.CLIP_TO_LAYER_SAVE_FLAG;
11210                        }
11211                        if (layerType == LAYER_TYPE_NONE) {
11212                            final int scrollX = hasDisplayList ? 0 : sx;
11213                            final int scrollY = hasDisplayList ? 0 : sy;
11214                            canvas.saveLayerAlpha(scrollX, scrollY, scrollX + mRight - mLeft,
11215                                    scrollY + mBottom - mTop, multipliedAlpha, layerFlags);
11216                        }
11217                    } else {
11218                        // Alpha is handled by the child directly, clobber the layer's alpha
11219                        mPrivateFlags |= ALPHA_SET;
11220                    }
11221                }
11222            }
11223        } else if ((mPrivateFlags & ALPHA_SET) == ALPHA_SET) {
11224            onSetAlpha(255);
11225            mPrivateFlags &= ~ALPHA_SET;
11226        }
11227
11228        if ((flags & parent.FLAG_CLIP_CHILDREN) == parent.FLAG_CLIP_CHILDREN) {
11229            if (offsetForScroll) {
11230                canvas.clipRect(sx, sy, sx + (mRight - mLeft), sy + (mBottom - mTop));
11231            } else {
11232                if (!scalingRequired || cache == null) {
11233                    canvas.clipRect(0, 0, mRight - mLeft, mBottom - mTop);
11234                } else {
11235                    canvas.clipRect(0, 0, cache.getWidth(), cache.getHeight());
11236                }
11237            }
11238        }
11239
11240        if (hasDisplayList) {
11241            displayList = getDisplayList();
11242            if (!displayList.isValid()) {
11243                // Uncommon, but possible. If a view is removed from the hierarchy during the call
11244                // to getDisplayList(), the display list will be marked invalid and we should not
11245                // try to use it again.
11246                displayList = null;
11247                hasDisplayList = false;
11248            }
11249        }
11250
11251        if (hasNoCache) {
11252            boolean layerRendered = false;
11253            if (layerType == LAYER_TYPE_HARDWARE) {
11254                final HardwareLayer layer = getHardwareLayer();
11255                if (layer != null && layer.isValid()) {
11256                    mLayerPaint.setAlpha((int) (alpha * 255));
11257                    ((HardwareCanvas) canvas).drawHardwareLayer(layer, 0, 0, mLayerPaint);
11258                    layerRendered = true;
11259                } else {
11260                    final int scrollX = hasDisplayList ? 0 : sx;
11261                    final int scrollY = hasDisplayList ? 0 : sy;
11262                    canvas.saveLayer(scrollX, scrollY,
11263                            scrollX + mRight - mLeft, scrollY + mBottom - mTop, mLayerPaint,
11264                            Canvas.HAS_ALPHA_LAYER_SAVE_FLAG | Canvas.CLIP_TO_LAYER_SAVE_FLAG);
11265                }
11266            }
11267
11268            if (!layerRendered) {
11269                if (!hasDisplayList) {
11270                    // Fast path for layouts with no backgrounds
11271                    if ((mPrivateFlags & SKIP_DRAW) == SKIP_DRAW) {
11272                        if (ViewDebug.TRACE_HIERARCHY) {
11273                            ViewDebug.trace(parent, ViewDebug.HierarchyTraceType.DRAW);
11274                        }
11275                        mPrivateFlags &= ~DIRTY_MASK;
11276                        dispatchDraw(canvas);
11277                    } else {
11278                        draw(canvas);
11279                    }
11280                } else {
11281                    mPrivateFlags &= ~DIRTY_MASK;
11282                    ((HardwareCanvas) canvas).drawDisplayList(displayList,
11283                            mRight - mLeft, mBottom - mTop, null, flags);
11284                }
11285            }
11286        } else if (cache != null) {
11287            mPrivateFlags &= ~DIRTY_MASK;
11288            Paint cachePaint;
11289
11290            if (layerType == LAYER_TYPE_NONE) {
11291                cachePaint = parent.mCachePaint;
11292                if (cachePaint == null) {
11293                    cachePaint = new Paint();
11294                    cachePaint.setDither(false);
11295                    parent.mCachePaint = cachePaint;
11296                }
11297                if (alpha < 1.0f) {
11298                    cachePaint.setAlpha((int) (alpha * 255));
11299                    parent.mGroupFlags |= parent.FLAG_ALPHA_LOWER_THAN_ONE;
11300                } else if  ((flags & parent.FLAG_ALPHA_LOWER_THAN_ONE) ==
11301                        parent.FLAG_ALPHA_LOWER_THAN_ONE) {
11302                    cachePaint.setAlpha(255);
11303                    parent.mGroupFlags &= ~parent.FLAG_ALPHA_LOWER_THAN_ONE;
11304                }
11305            } else {
11306                cachePaint = mLayerPaint;
11307                cachePaint.setAlpha((int) (alpha * 255));
11308            }
11309            canvas.drawBitmap(cache, 0.0f, 0.0f, cachePaint);
11310        }
11311
11312        canvas.restoreToCount(restoreTo);
11313
11314        if (a != null && !more) {
11315            if (!hardwareAccelerated && !a.getFillAfter()) {
11316                onSetAlpha(255);
11317            }
11318            parent.finishAnimatingView(this, a);
11319        }
11320
11321        if (more && hardwareAccelerated) {
11322            // invalidation is the trigger to recreate display lists, so if we're using
11323            // display lists to render, force an invalidate to allow the animation to
11324            // continue drawing another frame
11325            parent.invalidate(true);
11326            if (a.hasAlpha() && (mPrivateFlags & ALPHA_SET) == ALPHA_SET) {
11327                // alpha animations should cause the child to recreate its display list
11328                invalidate(true);
11329            }
11330        }
11331
11332        mRecreateDisplayList = false;
11333
11334        return more;
11335    }
11336
11337    /**
11338     * Manually render this view (and all of its children) to the given Canvas.
11339     * The view must have already done a full layout before this function is
11340     * called.  When implementing a view, implement
11341     * {@link #onDraw(android.graphics.Canvas)} instead of overriding this method.
11342     * If you do need to override this method, call the superclass version.
11343     *
11344     * @param canvas The Canvas to which the View is rendered.
11345     */
11346    public void draw(Canvas canvas) {
11347        if (ViewDebug.TRACE_HIERARCHY) {
11348            ViewDebug.trace(this, ViewDebug.HierarchyTraceType.DRAW);
11349        }
11350
11351        final int privateFlags = mPrivateFlags;
11352        final boolean dirtyOpaque = (privateFlags & DIRTY_MASK) == DIRTY_OPAQUE &&
11353                (mAttachInfo == null || !mAttachInfo.mIgnoreDirtyState);
11354        mPrivateFlags = (privateFlags & ~DIRTY_MASK) | DRAWN;
11355
11356        /*
11357         * Draw traversal performs several drawing steps which must be executed
11358         * in the appropriate order:
11359         *
11360         *      1. Draw the background
11361         *      2. If necessary, save the canvas' layers to prepare for fading
11362         *      3. Draw view's content
11363         *      4. Draw children
11364         *      5. If necessary, draw the fading edges and restore layers
11365         *      6. Draw decorations (scrollbars for instance)
11366         */
11367
11368        // Step 1, draw the background, if needed
11369        int saveCount;
11370
11371        if (!dirtyOpaque) {
11372            final Drawable background = mBGDrawable;
11373            if (background != null) {
11374                final int scrollX = mScrollX;
11375                final int scrollY = mScrollY;
11376
11377                if (mBackgroundSizeChanged) {
11378                    background.setBounds(0, 0,  mRight - mLeft, mBottom - mTop);
11379                    mBackgroundSizeChanged = false;
11380                }
11381
11382                if ((scrollX | scrollY) == 0) {
11383                    background.draw(canvas);
11384                } else {
11385                    canvas.translate(scrollX, scrollY);
11386                    background.draw(canvas);
11387                    canvas.translate(-scrollX, -scrollY);
11388                }
11389            }
11390        }
11391
11392        // skip step 2 & 5 if possible (common case)
11393        final int viewFlags = mViewFlags;
11394        boolean horizontalEdges = (viewFlags & FADING_EDGE_HORIZONTAL) != 0;
11395        boolean verticalEdges = (viewFlags & FADING_EDGE_VERTICAL) != 0;
11396        if (!verticalEdges && !horizontalEdges) {
11397            // Step 3, draw the content
11398            if (!dirtyOpaque) onDraw(canvas);
11399
11400            // Step 4, draw the children
11401            dispatchDraw(canvas);
11402
11403            // Step 6, draw decorations (scrollbars)
11404            onDrawScrollBars(canvas);
11405
11406            // we're done...
11407            return;
11408        }
11409
11410        /*
11411         * Here we do the full fledged routine...
11412         * (this is an uncommon case where speed matters less,
11413         * this is why we repeat some of the tests that have been
11414         * done above)
11415         */
11416
11417        boolean drawTop = false;
11418        boolean drawBottom = false;
11419        boolean drawLeft = false;
11420        boolean drawRight = false;
11421
11422        float topFadeStrength = 0.0f;
11423        float bottomFadeStrength = 0.0f;
11424        float leftFadeStrength = 0.0f;
11425        float rightFadeStrength = 0.0f;
11426
11427        // Step 2, save the canvas' layers
11428        int paddingLeft = mPaddingLeft;
11429
11430        final boolean offsetRequired = isPaddingOffsetRequired();
11431        if (offsetRequired) {
11432            paddingLeft += getLeftPaddingOffset();
11433        }
11434
11435        int left = mScrollX + paddingLeft;
11436        int right = left + mRight - mLeft - mPaddingRight - paddingLeft;
11437        int top = mScrollY + getFadeTop(offsetRequired);
11438        int bottom = top + getFadeHeight(offsetRequired);
11439
11440        if (offsetRequired) {
11441            right += getRightPaddingOffset();
11442            bottom += getBottomPaddingOffset();
11443        }
11444
11445        final ScrollabilityCache scrollabilityCache = mScrollCache;
11446        final float fadeHeight = scrollabilityCache.fadingEdgeLength;
11447        int length = (int) fadeHeight;
11448
11449        // clip the fade length if top and bottom fades overlap
11450        // overlapping fades produce odd-looking artifacts
11451        if (verticalEdges && (top + length > bottom - length)) {
11452            length = (bottom - top) / 2;
11453        }
11454
11455        // also clip horizontal fades if necessary
11456        if (horizontalEdges && (left + length > right - length)) {
11457            length = (right - left) / 2;
11458        }
11459
11460        if (verticalEdges) {
11461            topFadeStrength = Math.max(0.0f, Math.min(1.0f, getTopFadingEdgeStrength()));
11462            drawTop = topFadeStrength * fadeHeight > 1.0f;
11463            bottomFadeStrength = Math.max(0.0f, Math.min(1.0f, getBottomFadingEdgeStrength()));
11464            drawBottom = bottomFadeStrength * fadeHeight > 1.0f;
11465        }
11466
11467        if (horizontalEdges) {
11468            leftFadeStrength = Math.max(0.0f, Math.min(1.0f, getLeftFadingEdgeStrength()));
11469            drawLeft = leftFadeStrength * fadeHeight > 1.0f;
11470            rightFadeStrength = Math.max(0.0f, Math.min(1.0f, getRightFadingEdgeStrength()));
11471            drawRight = rightFadeStrength * fadeHeight > 1.0f;
11472        }
11473
11474        saveCount = canvas.getSaveCount();
11475
11476        int solidColor = getSolidColor();
11477        if (solidColor == 0) {
11478            final int flags = Canvas.HAS_ALPHA_LAYER_SAVE_FLAG;
11479
11480            if (drawTop) {
11481                canvas.saveLayer(left, top, right, top + length, null, flags);
11482            }
11483
11484            if (drawBottom) {
11485                canvas.saveLayer(left, bottom - length, right, bottom, null, flags);
11486            }
11487
11488            if (drawLeft) {
11489                canvas.saveLayer(left, top, left + length, bottom, null, flags);
11490            }
11491
11492            if (drawRight) {
11493                canvas.saveLayer(right - length, top, right, bottom, null, flags);
11494            }
11495        } else {
11496            scrollabilityCache.setFadeColor(solidColor);
11497        }
11498
11499        // Step 3, draw the content
11500        if (!dirtyOpaque) onDraw(canvas);
11501
11502        // Step 4, draw the children
11503        dispatchDraw(canvas);
11504
11505        // Step 5, draw the fade effect and restore layers
11506        final Paint p = scrollabilityCache.paint;
11507        final Matrix matrix = scrollabilityCache.matrix;
11508        final Shader fade = scrollabilityCache.shader;
11509
11510        if (drawTop) {
11511            matrix.setScale(1, fadeHeight * topFadeStrength);
11512            matrix.postTranslate(left, top);
11513            fade.setLocalMatrix(matrix);
11514            canvas.drawRect(left, top, right, top + length, p);
11515        }
11516
11517        if (drawBottom) {
11518            matrix.setScale(1, fadeHeight * bottomFadeStrength);
11519            matrix.postRotate(180);
11520            matrix.postTranslate(left, bottom);
11521            fade.setLocalMatrix(matrix);
11522            canvas.drawRect(left, bottom - length, right, bottom, p);
11523        }
11524
11525        if (drawLeft) {
11526            matrix.setScale(1, fadeHeight * leftFadeStrength);
11527            matrix.postRotate(-90);
11528            matrix.postTranslate(left, top);
11529            fade.setLocalMatrix(matrix);
11530            canvas.drawRect(left, top, left + length, bottom, p);
11531        }
11532
11533        if (drawRight) {
11534            matrix.setScale(1, fadeHeight * rightFadeStrength);
11535            matrix.postRotate(90);
11536            matrix.postTranslate(right, top);
11537            fade.setLocalMatrix(matrix);
11538            canvas.drawRect(right - length, top, right, bottom, p);
11539        }
11540
11541        canvas.restoreToCount(saveCount);
11542
11543        // Step 6, draw decorations (scrollbars)
11544        onDrawScrollBars(canvas);
11545    }
11546
11547    /**
11548     * Override this if your view is known to always be drawn on top of a solid color background,
11549     * and needs to draw fading edges. Returning a non-zero color enables the view system to
11550     * optimize the drawing of the fading edges. If you do return a non-zero color, the alpha
11551     * should be set to 0xFF.
11552     *
11553     * @see #setVerticalFadingEdgeEnabled(boolean)
11554     * @see #setHorizontalFadingEdgeEnabled(boolean)
11555     *
11556     * @return The known solid color background for this view, or 0 if the color may vary
11557     */
11558    @ViewDebug.ExportedProperty(category = "drawing")
11559    public int getSolidColor() {
11560        return 0;
11561    }
11562
11563    /**
11564     * Build a human readable string representation of the specified view flags.
11565     *
11566     * @param flags the view flags to convert to a string
11567     * @return a String representing the supplied flags
11568     */
11569    private static String printFlags(int flags) {
11570        String output = "";
11571        int numFlags = 0;
11572        if ((flags & FOCUSABLE_MASK) == FOCUSABLE) {
11573            output += "TAKES_FOCUS";
11574            numFlags++;
11575        }
11576
11577        switch (flags & VISIBILITY_MASK) {
11578        case INVISIBLE:
11579            if (numFlags > 0) {
11580                output += " ";
11581            }
11582            output += "INVISIBLE";
11583            // USELESS HERE numFlags++;
11584            break;
11585        case GONE:
11586            if (numFlags > 0) {
11587                output += " ";
11588            }
11589            output += "GONE";
11590            // USELESS HERE numFlags++;
11591            break;
11592        default:
11593            break;
11594        }
11595        return output;
11596    }
11597
11598    /**
11599     * Build a human readable string representation of the specified private
11600     * view flags.
11601     *
11602     * @param privateFlags the private view flags to convert to a string
11603     * @return a String representing the supplied flags
11604     */
11605    private static String printPrivateFlags(int privateFlags) {
11606        String output = "";
11607        int numFlags = 0;
11608
11609        if ((privateFlags & WANTS_FOCUS) == WANTS_FOCUS) {
11610            output += "WANTS_FOCUS";
11611            numFlags++;
11612        }
11613
11614        if ((privateFlags & FOCUSED) == FOCUSED) {
11615            if (numFlags > 0) {
11616                output += " ";
11617            }
11618            output += "FOCUSED";
11619            numFlags++;
11620        }
11621
11622        if ((privateFlags & SELECTED) == SELECTED) {
11623            if (numFlags > 0) {
11624                output += " ";
11625            }
11626            output += "SELECTED";
11627            numFlags++;
11628        }
11629
11630        if ((privateFlags & IS_ROOT_NAMESPACE) == IS_ROOT_NAMESPACE) {
11631            if (numFlags > 0) {
11632                output += " ";
11633            }
11634            output += "IS_ROOT_NAMESPACE";
11635            numFlags++;
11636        }
11637
11638        if ((privateFlags & HAS_BOUNDS) == HAS_BOUNDS) {
11639            if (numFlags > 0) {
11640                output += " ";
11641            }
11642            output += "HAS_BOUNDS";
11643            numFlags++;
11644        }
11645
11646        if ((privateFlags & DRAWN) == DRAWN) {
11647            if (numFlags > 0) {
11648                output += " ";
11649            }
11650            output += "DRAWN";
11651            // USELESS HERE numFlags++;
11652        }
11653        return output;
11654    }
11655
11656    /**
11657     * <p>Indicates whether or not this view's layout will be requested during
11658     * the next hierarchy layout pass.</p>
11659     *
11660     * @return true if the layout will be forced during next layout pass
11661     */
11662    public boolean isLayoutRequested() {
11663        return (mPrivateFlags & FORCE_LAYOUT) == FORCE_LAYOUT;
11664    }
11665
11666    /**
11667     * Assign a size and position to a view and all of its
11668     * descendants
11669     *
11670     * <p>This is the second phase of the layout mechanism.
11671     * (The first is measuring). In this phase, each parent calls
11672     * layout on all of its children to position them.
11673     * This is typically done using the child measurements
11674     * that were stored in the measure pass().</p>
11675     *
11676     * <p>Derived classes should not override this method.
11677     * Derived classes with children should override
11678     * onLayout. In that method, they should
11679     * call layout on each of their children.</p>
11680     *
11681     * @param l Left position, relative to parent
11682     * @param t Top position, relative to parent
11683     * @param r Right position, relative to parent
11684     * @param b Bottom position, relative to parent
11685     */
11686    @SuppressWarnings({"unchecked"})
11687    public void layout(int l, int t, int r, int b) {
11688        int oldL = mLeft;
11689        int oldT = mTop;
11690        int oldB = mBottom;
11691        int oldR = mRight;
11692        boolean changed = setFrame(l, t, r, b);
11693        if (changed || (mPrivateFlags & LAYOUT_REQUIRED) == LAYOUT_REQUIRED) {
11694            if (ViewDebug.TRACE_HIERARCHY) {
11695                ViewDebug.trace(this, ViewDebug.HierarchyTraceType.ON_LAYOUT);
11696            }
11697
11698            onLayout(changed, l, t, r, b);
11699            mPrivateFlags &= ~LAYOUT_REQUIRED;
11700
11701            ListenerInfo li = mListenerInfo;
11702            if (li != null && li.mOnLayoutChangeListeners != null) {
11703                ArrayList<OnLayoutChangeListener> listenersCopy =
11704                        (ArrayList<OnLayoutChangeListener>)li.mOnLayoutChangeListeners.clone();
11705                int numListeners = listenersCopy.size();
11706                for (int i = 0; i < numListeners; ++i) {
11707                    listenersCopy.get(i).onLayoutChange(this, l, t, r, b, oldL, oldT, oldR, oldB);
11708                }
11709            }
11710        }
11711        mPrivateFlags &= ~FORCE_LAYOUT;
11712    }
11713
11714    /**
11715     * Called from layout when this view should
11716     * assign a size and position to each of its children.
11717     *
11718     * Derived classes with children should override
11719     * this method and call layout on each of
11720     * their children.
11721     * @param changed This is a new size or position for this view
11722     * @param left Left position, relative to parent
11723     * @param top Top position, relative to parent
11724     * @param right Right position, relative to parent
11725     * @param bottom Bottom position, relative to parent
11726     */
11727    protected void onLayout(boolean changed, int left, int top, int right, int bottom) {
11728    }
11729
11730    /**
11731     * Assign a size and position to this view.
11732     *
11733     * This is called from layout.
11734     *
11735     * @param left Left position, relative to parent
11736     * @param top Top position, relative to parent
11737     * @param right Right position, relative to parent
11738     * @param bottom Bottom position, relative to parent
11739     * @return true if the new size and position are different than the
11740     *         previous ones
11741     * {@hide}
11742     */
11743    protected boolean setFrame(int left, int top, int right, int bottom) {
11744        boolean changed = false;
11745
11746        if (DBG) {
11747            Log.d("View", this + " View.setFrame(" + left + "," + top + ","
11748                    + right + "," + bottom + ")");
11749        }
11750
11751        if (mLeft != left || mRight != right || mTop != top || mBottom != bottom) {
11752            changed = true;
11753
11754            // Remember our drawn bit
11755            int drawn = mPrivateFlags & DRAWN;
11756
11757            int oldWidth = mRight - mLeft;
11758            int oldHeight = mBottom - mTop;
11759            int newWidth = right - left;
11760            int newHeight = bottom - top;
11761            boolean sizeChanged = (newWidth != oldWidth) || (newHeight != oldHeight);
11762
11763            // Invalidate our old position
11764            invalidate(sizeChanged);
11765
11766            mLeft = left;
11767            mTop = top;
11768            mRight = right;
11769            mBottom = bottom;
11770
11771            mPrivateFlags |= HAS_BOUNDS;
11772
11773
11774            if (sizeChanged) {
11775                if ((mPrivateFlags & PIVOT_EXPLICITLY_SET) == 0) {
11776                    // A change in dimension means an auto-centered pivot point changes, too
11777                    if (mTransformationInfo != null) {
11778                        mTransformationInfo.mMatrixDirty = true;
11779                    }
11780                }
11781                onSizeChanged(newWidth, newHeight, oldWidth, oldHeight);
11782            }
11783
11784            if ((mViewFlags & VISIBILITY_MASK) == VISIBLE) {
11785                // If we are visible, force the DRAWN bit to on so that
11786                // this invalidate will go through (at least to our parent).
11787                // This is because someone may have invalidated this view
11788                // before this call to setFrame came in, thereby clearing
11789                // the DRAWN bit.
11790                mPrivateFlags |= DRAWN;
11791                invalidate(sizeChanged);
11792                // parent display list may need to be recreated based on a change in the bounds
11793                // of any child
11794                invalidateParentCaches();
11795            }
11796
11797            // Reset drawn bit to original value (invalidate turns it off)
11798            mPrivateFlags |= drawn;
11799
11800            mBackgroundSizeChanged = true;
11801        }
11802        return changed;
11803    }
11804
11805    /**
11806     * Finalize inflating a view from XML.  This is called as the last phase
11807     * of inflation, after all child views have been added.
11808     *
11809     * <p>Even if the subclass overrides onFinishInflate, they should always be
11810     * sure to call the super method, so that we get called.
11811     */
11812    protected void onFinishInflate() {
11813    }
11814
11815    /**
11816     * Returns the resources associated with this view.
11817     *
11818     * @return Resources object.
11819     */
11820    public Resources getResources() {
11821        return mResources;
11822    }
11823
11824    /**
11825     * Invalidates the specified Drawable.
11826     *
11827     * @param drawable the drawable to invalidate
11828     */
11829    public void invalidateDrawable(Drawable drawable) {
11830        if (verifyDrawable(drawable)) {
11831            final Rect dirty = drawable.getBounds();
11832            final int scrollX = mScrollX;
11833            final int scrollY = mScrollY;
11834
11835            invalidate(dirty.left + scrollX, dirty.top + scrollY,
11836                    dirty.right + scrollX, dirty.bottom + scrollY);
11837        }
11838    }
11839
11840    /**
11841     * Schedules an action on a drawable to occur at a specified time.
11842     *
11843     * @param who the recipient of the action
11844     * @param what the action to run on the drawable
11845     * @param when the time at which the action must occur. Uses the
11846     *        {@link SystemClock#uptimeMillis} timebase.
11847     */
11848    public void scheduleDrawable(Drawable who, Runnable what, long when) {
11849        if (verifyDrawable(who) && what != null) {
11850            if (mAttachInfo != null) {
11851                mAttachInfo.mHandler.postAtTime(what, who, when);
11852            } else {
11853                ViewRootImpl.getRunQueue().postDelayed(what, when - SystemClock.uptimeMillis());
11854            }
11855        }
11856    }
11857
11858    /**
11859     * Cancels a scheduled action on a drawable.
11860     *
11861     * @param who the recipient of the action
11862     * @param what the action to cancel
11863     */
11864    public void unscheduleDrawable(Drawable who, Runnable what) {
11865        if (verifyDrawable(who) && what != null) {
11866            if (mAttachInfo != null) {
11867                mAttachInfo.mHandler.removeCallbacks(what, who);
11868            } else {
11869                ViewRootImpl.getRunQueue().removeCallbacks(what);
11870            }
11871        }
11872    }
11873
11874    /**
11875     * Unschedule any events associated with the given Drawable.  This can be
11876     * used when selecting a new Drawable into a view, so that the previous
11877     * one is completely unscheduled.
11878     *
11879     * @param who The Drawable to unschedule.
11880     *
11881     * @see #drawableStateChanged
11882     */
11883    public void unscheduleDrawable(Drawable who) {
11884        if (mAttachInfo != null) {
11885            mAttachInfo.mHandler.removeCallbacksAndMessages(who);
11886        }
11887    }
11888
11889    /**
11890    * Return the layout direction of a given Drawable.
11891    *
11892    * @param who the Drawable to query
11893    */
11894    public int getResolvedLayoutDirection(Drawable who) {
11895        return (who == mBGDrawable) ? getResolvedLayoutDirection() : LAYOUT_DIRECTION_DEFAULT;
11896    }
11897
11898    /**
11899     * If your view subclass is displaying its own Drawable objects, it should
11900     * override this function and return true for any Drawable it is
11901     * displaying.  This allows animations for those drawables to be
11902     * scheduled.
11903     *
11904     * <p>Be sure to call through to the super class when overriding this
11905     * function.
11906     *
11907     * @param who The Drawable to verify.  Return true if it is one you are
11908     *            displaying, else return the result of calling through to the
11909     *            super class.
11910     *
11911     * @return boolean If true than the Drawable is being displayed in the
11912     *         view; else false and it is not allowed to animate.
11913     *
11914     * @see #unscheduleDrawable(android.graphics.drawable.Drawable)
11915     * @see #drawableStateChanged()
11916     */
11917    protected boolean verifyDrawable(Drawable who) {
11918        return who == mBGDrawable;
11919    }
11920
11921    /**
11922     * This function is called whenever the state of the view changes in such
11923     * a way that it impacts the state of drawables being shown.
11924     *
11925     * <p>Be sure to call through to the superclass when overriding this
11926     * function.
11927     *
11928     * @see Drawable#setState(int[])
11929     */
11930    protected void drawableStateChanged() {
11931        Drawable d = mBGDrawable;
11932        if (d != null && d.isStateful()) {
11933            d.setState(getDrawableState());
11934        }
11935    }
11936
11937    /**
11938     * Call this to force a view to update its drawable state. This will cause
11939     * drawableStateChanged to be called on this view. Views that are interested
11940     * in the new state should call getDrawableState.
11941     *
11942     * @see #drawableStateChanged
11943     * @see #getDrawableState
11944     */
11945    public void refreshDrawableState() {
11946        mPrivateFlags |= DRAWABLE_STATE_DIRTY;
11947        drawableStateChanged();
11948
11949        ViewParent parent = mParent;
11950        if (parent != null) {
11951            parent.childDrawableStateChanged(this);
11952        }
11953    }
11954
11955    /**
11956     * Return an array of resource IDs of the drawable states representing the
11957     * current state of the view.
11958     *
11959     * @return The current drawable state
11960     *
11961     * @see Drawable#setState(int[])
11962     * @see #drawableStateChanged()
11963     * @see #onCreateDrawableState(int)
11964     */
11965    public final int[] getDrawableState() {
11966        if ((mDrawableState != null) && ((mPrivateFlags & DRAWABLE_STATE_DIRTY) == 0)) {
11967            return mDrawableState;
11968        } else {
11969            mDrawableState = onCreateDrawableState(0);
11970            mPrivateFlags &= ~DRAWABLE_STATE_DIRTY;
11971            return mDrawableState;
11972        }
11973    }
11974
11975    /**
11976     * Generate the new {@link android.graphics.drawable.Drawable} state for
11977     * this view. This is called by the view
11978     * system when the cached Drawable state is determined to be invalid.  To
11979     * retrieve the current state, you should use {@link #getDrawableState}.
11980     *
11981     * @param extraSpace if non-zero, this is the number of extra entries you
11982     * would like in the returned array in which you can place your own
11983     * states.
11984     *
11985     * @return Returns an array holding the current {@link Drawable} state of
11986     * the view.
11987     *
11988     * @see #mergeDrawableStates(int[], int[])
11989     */
11990    protected int[] onCreateDrawableState(int extraSpace) {
11991        if ((mViewFlags & DUPLICATE_PARENT_STATE) == DUPLICATE_PARENT_STATE &&
11992                mParent instanceof View) {
11993            return ((View) mParent).onCreateDrawableState(extraSpace);
11994        }
11995
11996        int[] drawableState;
11997
11998        int privateFlags = mPrivateFlags;
11999
12000        int viewStateIndex = 0;
12001        if ((privateFlags & PRESSED) != 0) viewStateIndex |= VIEW_STATE_PRESSED;
12002        if ((mViewFlags & ENABLED_MASK) == ENABLED) viewStateIndex |= VIEW_STATE_ENABLED;
12003        if (isFocused()) viewStateIndex |= VIEW_STATE_FOCUSED;
12004        if ((privateFlags & SELECTED) != 0) viewStateIndex |= VIEW_STATE_SELECTED;
12005        if (hasWindowFocus()) viewStateIndex |= VIEW_STATE_WINDOW_FOCUSED;
12006        if ((privateFlags & ACTIVATED) != 0) viewStateIndex |= VIEW_STATE_ACTIVATED;
12007        if (mAttachInfo != null && mAttachInfo.mHardwareAccelerationRequested &&
12008                HardwareRenderer.isAvailable()) {
12009            // This is set if HW acceleration is requested, even if the current
12010            // process doesn't allow it.  This is just to allow app preview
12011            // windows to better match their app.
12012            viewStateIndex |= VIEW_STATE_ACCELERATED;
12013        }
12014        if ((privateFlags & HOVERED) != 0) viewStateIndex |= VIEW_STATE_HOVERED;
12015
12016        final int privateFlags2 = mPrivateFlags2;
12017        if ((privateFlags2 & DRAG_CAN_ACCEPT) != 0) viewStateIndex |= VIEW_STATE_DRAG_CAN_ACCEPT;
12018        if ((privateFlags2 & DRAG_HOVERED) != 0) viewStateIndex |= VIEW_STATE_DRAG_HOVERED;
12019
12020        drawableState = VIEW_STATE_SETS[viewStateIndex];
12021
12022        //noinspection ConstantIfStatement
12023        if (false) {
12024            Log.i("View", "drawableStateIndex=" + viewStateIndex);
12025            Log.i("View", toString()
12026                    + " pressed=" + ((privateFlags & PRESSED) != 0)
12027                    + " en=" + ((mViewFlags & ENABLED_MASK) == ENABLED)
12028                    + " fo=" + hasFocus()
12029                    + " sl=" + ((privateFlags & SELECTED) != 0)
12030                    + " wf=" + hasWindowFocus()
12031                    + ": " + Arrays.toString(drawableState));
12032        }
12033
12034        if (extraSpace == 0) {
12035            return drawableState;
12036        }
12037
12038        final int[] fullState;
12039        if (drawableState != null) {
12040            fullState = new int[drawableState.length + extraSpace];
12041            System.arraycopy(drawableState, 0, fullState, 0, drawableState.length);
12042        } else {
12043            fullState = new int[extraSpace];
12044        }
12045
12046        return fullState;
12047    }
12048
12049    /**
12050     * Merge your own state values in <var>additionalState</var> into the base
12051     * state values <var>baseState</var> that were returned by
12052     * {@link #onCreateDrawableState(int)}.
12053     *
12054     * @param baseState The base state values returned by
12055     * {@link #onCreateDrawableState(int)}, which will be modified to also hold your
12056     * own additional state values.
12057     *
12058     * @param additionalState The additional state values you would like
12059     * added to <var>baseState</var>; this array is not modified.
12060     *
12061     * @return As a convenience, the <var>baseState</var> array you originally
12062     * passed into the function is returned.
12063     *
12064     * @see #onCreateDrawableState(int)
12065     */
12066    protected static int[] mergeDrawableStates(int[] baseState, int[] additionalState) {
12067        final int N = baseState.length;
12068        int i = N - 1;
12069        while (i >= 0 && baseState[i] == 0) {
12070            i--;
12071        }
12072        System.arraycopy(additionalState, 0, baseState, i + 1, additionalState.length);
12073        return baseState;
12074    }
12075
12076    /**
12077     * Call {@link Drawable#jumpToCurrentState() Drawable.jumpToCurrentState()}
12078     * on all Drawable objects associated with this view.
12079     */
12080    public void jumpDrawablesToCurrentState() {
12081        if (mBGDrawable != null) {
12082            mBGDrawable.jumpToCurrentState();
12083        }
12084    }
12085
12086    /**
12087     * Sets the background color for this view.
12088     * @param color the color of the background
12089     */
12090    @RemotableViewMethod
12091    public void setBackgroundColor(int color) {
12092        if (mBGDrawable instanceof ColorDrawable) {
12093            ((ColorDrawable) mBGDrawable).setColor(color);
12094        } else {
12095            setBackgroundDrawable(new ColorDrawable(color));
12096        }
12097    }
12098
12099    /**
12100     * Set the background to a given resource. The resource should refer to
12101     * a Drawable object or 0 to remove the background.
12102     * @param resid The identifier of the resource.
12103     * @attr ref android.R.styleable#View_background
12104     */
12105    @RemotableViewMethod
12106    public void setBackgroundResource(int resid) {
12107        if (resid != 0 && resid == mBackgroundResource) {
12108            return;
12109        }
12110
12111        Drawable d= null;
12112        if (resid != 0) {
12113            d = mResources.getDrawable(resid);
12114        }
12115        setBackgroundDrawable(d);
12116
12117        mBackgroundResource = resid;
12118    }
12119
12120    /**
12121     * Set the background to a given Drawable, or remove the background. If the
12122     * background has padding, this View's padding is set to the background's
12123     * padding. However, when a background is removed, this View's padding isn't
12124     * touched. If setting the padding is desired, please use
12125     * {@link #setPadding(int, int, int, int)}.
12126     *
12127     * @param d The Drawable to use as the background, or null to remove the
12128     *        background
12129     */
12130    public void setBackgroundDrawable(Drawable d) {
12131        if (d == mBGDrawable) {
12132            return;
12133        }
12134
12135        boolean requestLayout = false;
12136
12137        mBackgroundResource = 0;
12138
12139        /*
12140         * Regardless of whether we're setting a new background or not, we want
12141         * to clear the previous drawable.
12142         */
12143        if (mBGDrawable != null) {
12144            mBGDrawable.setCallback(null);
12145            unscheduleDrawable(mBGDrawable);
12146        }
12147
12148        if (d != null) {
12149            Rect padding = sThreadLocal.get();
12150            if (padding == null) {
12151                padding = new Rect();
12152                sThreadLocal.set(padding);
12153            }
12154            if (d.getPadding(padding)) {
12155                switch (d.getResolvedLayoutDirectionSelf()) {
12156                    case LAYOUT_DIRECTION_RTL:
12157                        setPadding(padding.right, padding.top, padding.left, padding.bottom);
12158                        break;
12159                    case LAYOUT_DIRECTION_LTR:
12160                    default:
12161                        setPadding(padding.left, padding.top, padding.right, padding.bottom);
12162                }
12163            }
12164
12165            // Compare the minimum sizes of the old Drawable and the new.  If there isn't an old or
12166            // if it has a different minimum size, we should layout again
12167            if (mBGDrawable == null || mBGDrawable.getMinimumHeight() != d.getMinimumHeight() ||
12168                    mBGDrawable.getMinimumWidth() != d.getMinimumWidth()) {
12169                requestLayout = true;
12170            }
12171
12172            d.setCallback(this);
12173            if (d.isStateful()) {
12174                d.setState(getDrawableState());
12175            }
12176            d.setVisible(getVisibility() == VISIBLE, false);
12177            mBGDrawable = d;
12178
12179            if ((mPrivateFlags & SKIP_DRAW) != 0) {
12180                mPrivateFlags &= ~SKIP_DRAW;
12181                mPrivateFlags |= ONLY_DRAWS_BACKGROUND;
12182                requestLayout = true;
12183            }
12184        } else {
12185            /* Remove the background */
12186            mBGDrawable = null;
12187
12188            if ((mPrivateFlags & ONLY_DRAWS_BACKGROUND) != 0) {
12189                /*
12190                 * This view ONLY drew the background before and we're removing
12191                 * the background, so now it won't draw anything
12192                 * (hence we SKIP_DRAW)
12193                 */
12194                mPrivateFlags &= ~ONLY_DRAWS_BACKGROUND;
12195                mPrivateFlags |= SKIP_DRAW;
12196            }
12197
12198            /*
12199             * When the background is set, we try to apply its padding to this
12200             * View. When the background is removed, we don't touch this View's
12201             * padding. This is noted in the Javadocs. Hence, we don't need to
12202             * requestLayout(), the invalidate() below is sufficient.
12203             */
12204
12205            // The old background's minimum size could have affected this
12206            // View's layout, so let's requestLayout
12207            requestLayout = true;
12208        }
12209
12210        computeOpaqueFlags();
12211
12212        if (requestLayout) {
12213            requestLayout();
12214        }
12215
12216        mBackgroundSizeChanged = true;
12217        invalidate(true);
12218    }
12219
12220    /**
12221     * Gets the background drawable
12222     * @return The drawable used as the background for this view, if any.
12223     */
12224    public Drawable getBackground() {
12225        return mBGDrawable;
12226    }
12227
12228    /**
12229     * Sets the padding. The view may add on the space required to display
12230     * the scrollbars, depending on the style and visibility of the scrollbars.
12231     * So the values returned from {@link #getPaddingLeft}, {@link #getPaddingTop},
12232     * {@link #getPaddingRight} and {@link #getPaddingBottom} may be different
12233     * from the values set in this call.
12234     *
12235     * @attr ref android.R.styleable#View_padding
12236     * @attr ref android.R.styleable#View_paddingBottom
12237     * @attr ref android.R.styleable#View_paddingLeft
12238     * @attr ref android.R.styleable#View_paddingRight
12239     * @attr ref android.R.styleable#View_paddingTop
12240     * @param left the left padding in pixels
12241     * @param top the top padding in pixels
12242     * @param right the right padding in pixels
12243     * @param bottom the bottom padding in pixels
12244     */
12245    public void setPadding(int left, int top, int right, int bottom) {
12246        mUserPaddingStart = -1;
12247        mUserPaddingEnd = -1;
12248        mUserPaddingRelative = false;
12249
12250        internalSetPadding(left, top, right, bottom);
12251    }
12252
12253    private void internalSetPadding(int left, int top, int right, int bottom) {
12254        mUserPaddingLeft = left;
12255        mUserPaddingRight = right;
12256        mUserPaddingBottom = bottom;
12257
12258        final int viewFlags = mViewFlags;
12259        boolean changed = false;
12260
12261        // Common case is there are no scroll bars.
12262        if ((viewFlags & (SCROLLBARS_VERTICAL|SCROLLBARS_HORIZONTAL)) != 0) {
12263            if ((viewFlags & SCROLLBARS_VERTICAL) != 0) {
12264                final int offset = (viewFlags & SCROLLBARS_INSET_MASK) == 0
12265                        ? 0 : getVerticalScrollbarWidth();
12266                switch (mVerticalScrollbarPosition) {
12267                    case SCROLLBAR_POSITION_DEFAULT:
12268                        if (getResolvedLayoutDirection() == LAYOUT_DIRECTION_RTL) {
12269                            left += offset;
12270                        } else {
12271                            right += offset;
12272                        }
12273                        break;
12274                    case SCROLLBAR_POSITION_RIGHT:
12275                        right += offset;
12276                        break;
12277                    case SCROLLBAR_POSITION_LEFT:
12278                        left += offset;
12279                        break;
12280                }
12281            }
12282            if ((viewFlags & SCROLLBARS_HORIZONTAL) != 0) {
12283                bottom += (viewFlags & SCROLLBARS_INSET_MASK) == 0
12284                        ? 0 : getHorizontalScrollbarHeight();
12285            }
12286        }
12287
12288        if (mPaddingLeft != left) {
12289            changed = true;
12290            mPaddingLeft = left;
12291        }
12292        if (mPaddingTop != top) {
12293            changed = true;
12294            mPaddingTop = top;
12295        }
12296        if (mPaddingRight != right) {
12297            changed = true;
12298            mPaddingRight = right;
12299        }
12300        if (mPaddingBottom != bottom) {
12301            changed = true;
12302            mPaddingBottom = bottom;
12303        }
12304
12305        if (changed) {
12306            requestLayout();
12307        }
12308    }
12309
12310    /**
12311     * Sets the relative padding. The view may add on the space required to display
12312     * the scrollbars, depending on the style and visibility of the scrollbars.
12313     * So the values returned from {@link #getPaddingStart}, {@link #getPaddingTop},
12314     * {@link #getPaddingEnd} and {@link #getPaddingBottom} may be different
12315     * from the values set in this call.
12316     *
12317     * @attr ref android.R.styleable#View_padding
12318     * @attr ref android.R.styleable#View_paddingBottom
12319     * @attr ref android.R.styleable#View_paddingStart
12320     * @attr ref android.R.styleable#View_paddingEnd
12321     * @attr ref android.R.styleable#View_paddingTop
12322     * @param start the start padding in pixels
12323     * @param top the top padding in pixels
12324     * @param end the end padding in pixels
12325     * @param bottom the bottom padding in pixels
12326     */
12327    public void setPaddingRelative(int start, int top, int end, int bottom) {
12328        mUserPaddingStart = start;
12329        mUserPaddingEnd = end;
12330        mUserPaddingRelative = true;
12331
12332        switch(getResolvedLayoutDirection()) {
12333            case LAYOUT_DIRECTION_RTL:
12334                internalSetPadding(end, top, start, bottom);
12335                break;
12336            case LAYOUT_DIRECTION_LTR:
12337            default:
12338                internalSetPadding(start, top, end, bottom);
12339        }
12340    }
12341
12342    /**
12343     * Returns the top padding of this view.
12344     *
12345     * @return the top padding in pixels
12346     */
12347    public int getPaddingTop() {
12348        return mPaddingTop;
12349    }
12350
12351    /**
12352     * Returns the bottom padding of this view. If there are inset and enabled
12353     * scrollbars, this value may include the space required to display the
12354     * scrollbars as well.
12355     *
12356     * @return the bottom padding in pixels
12357     */
12358    public int getPaddingBottom() {
12359        return mPaddingBottom;
12360    }
12361
12362    /**
12363     * Returns the left padding of this view. If there are inset and enabled
12364     * scrollbars, this value may include the space required to display the
12365     * scrollbars as well.
12366     *
12367     * @return the left padding in pixels
12368     */
12369    public int getPaddingLeft() {
12370        return mPaddingLeft;
12371    }
12372
12373    /**
12374     * Returns the start padding of this view. If there are inset and enabled
12375     * scrollbars, this value may include the space required to display the
12376     * scrollbars as well.
12377     *
12378     * @return the start padding in pixels
12379     */
12380    public int getPaddingStart() {
12381        return (getResolvedLayoutDirection() == LAYOUT_DIRECTION_RTL) ?
12382                mPaddingRight : mPaddingLeft;
12383    }
12384
12385    /**
12386     * Returns the right padding of this view. If there are inset and enabled
12387     * scrollbars, this value may include the space required to display the
12388     * scrollbars as well.
12389     *
12390     * @return the right padding in pixels
12391     */
12392    public int getPaddingRight() {
12393        return mPaddingRight;
12394    }
12395
12396    /**
12397     * Returns the end padding of this view. If there are inset and enabled
12398     * scrollbars, this value may include the space required to display the
12399     * scrollbars as well.
12400     *
12401     * @return the end padding in pixels
12402     */
12403    public int getPaddingEnd() {
12404        return (getResolvedLayoutDirection() == LAYOUT_DIRECTION_RTL) ?
12405                mPaddingLeft : mPaddingRight;
12406    }
12407
12408    /**
12409     * Return if the padding as been set thru relative values
12410     * {@link #setPaddingRelative(int, int, int, int)} or thru
12411     * @attr ref android.R.styleable#View_paddingStart or
12412     * @attr ref android.R.styleable#View_paddingEnd
12413     *
12414     * @return true if the padding is relative or false if it is not.
12415     */
12416    public boolean isPaddingRelative() {
12417        return mUserPaddingRelative;
12418    }
12419
12420    /**
12421     * Changes the selection state of this view. A view can be selected or not.
12422     * Note that selection is not the same as focus. Views are typically
12423     * selected in the context of an AdapterView like ListView or GridView;
12424     * the selected view is the view that is highlighted.
12425     *
12426     * @param selected true if the view must be selected, false otherwise
12427     */
12428    public void setSelected(boolean selected) {
12429        if (((mPrivateFlags & SELECTED) != 0) != selected) {
12430            mPrivateFlags = (mPrivateFlags & ~SELECTED) | (selected ? SELECTED : 0);
12431            if (!selected) resetPressedState();
12432            invalidate(true);
12433            refreshDrawableState();
12434            dispatchSetSelected(selected);
12435        }
12436    }
12437
12438    /**
12439     * Dispatch setSelected to all of this View's children.
12440     *
12441     * @see #setSelected(boolean)
12442     *
12443     * @param selected The new selected state
12444     */
12445    protected void dispatchSetSelected(boolean selected) {
12446    }
12447
12448    /**
12449     * Indicates the selection state of this view.
12450     *
12451     * @return true if the view is selected, false otherwise
12452     */
12453    @ViewDebug.ExportedProperty
12454    public boolean isSelected() {
12455        return (mPrivateFlags & SELECTED) != 0;
12456    }
12457
12458    /**
12459     * Changes the activated state of this view. A view can be activated or not.
12460     * Note that activation is not the same as selection.  Selection is
12461     * a transient property, representing the view (hierarchy) the user is
12462     * currently interacting with.  Activation is a longer-term state that the
12463     * user can move views in and out of.  For example, in a list view with
12464     * single or multiple selection enabled, the views in the current selection
12465     * set are activated.  (Um, yeah, we are deeply sorry about the terminology
12466     * here.)  The activated state is propagated down to children of the view it
12467     * is set on.
12468     *
12469     * @param activated true if the view must be activated, false otherwise
12470     */
12471    public void setActivated(boolean activated) {
12472        if (((mPrivateFlags & ACTIVATED) != 0) != activated) {
12473            mPrivateFlags = (mPrivateFlags & ~ACTIVATED) | (activated ? ACTIVATED : 0);
12474            invalidate(true);
12475            refreshDrawableState();
12476            dispatchSetActivated(activated);
12477        }
12478    }
12479
12480    /**
12481     * Dispatch setActivated to all of this View's children.
12482     *
12483     * @see #setActivated(boolean)
12484     *
12485     * @param activated The new activated state
12486     */
12487    protected void dispatchSetActivated(boolean activated) {
12488    }
12489
12490    /**
12491     * Indicates the activation state of this view.
12492     *
12493     * @return true if the view is activated, false otherwise
12494     */
12495    @ViewDebug.ExportedProperty
12496    public boolean isActivated() {
12497        return (mPrivateFlags & ACTIVATED) != 0;
12498    }
12499
12500    /**
12501     * Returns the ViewTreeObserver for this view's hierarchy. The view tree
12502     * observer can be used to get notifications when global events, like
12503     * layout, happen.
12504     *
12505     * The returned ViewTreeObserver observer is not guaranteed to remain
12506     * valid for the lifetime of this View. If the caller of this method keeps
12507     * a long-lived reference to ViewTreeObserver, it should always check for
12508     * the return value of {@link ViewTreeObserver#isAlive()}.
12509     *
12510     * @return The ViewTreeObserver for this view's hierarchy.
12511     */
12512    public ViewTreeObserver getViewTreeObserver() {
12513        if (mAttachInfo != null) {
12514            return mAttachInfo.mTreeObserver;
12515        }
12516        if (mFloatingTreeObserver == null) {
12517            mFloatingTreeObserver = new ViewTreeObserver();
12518        }
12519        return mFloatingTreeObserver;
12520    }
12521
12522    /**
12523     * <p>Finds the topmost view in the current view hierarchy.</p>
12524     *
12525     * @return the topmost view containing this view
12526     */
12527    public View getRootView() {
12528        if (mAttachInfo != null) {
12529            final View v = mAttachInfo.mRootView;
12530            if (v != null) {
12531                return v;
12532            }
12533        }
12534
12535        View parent = this;
12536
12537        while (parent.mParent != null && parent.mParent instanceof View) {
12538            parent = (View) parent.mParent;
12539        }
12540
12541        return parent;
12542    }
12543
12544    /**
12545     * <p>Computes the coordinates of this view on the screen. The argument
12546     * must be an array of two integers. After the method returns, the array
12547     * contains the x and y location in that order.</p>
12548     *
12549     * @param location an array of two integers in which to hold the coordinates
12550     */
12551    public void getLocationOnScreen(int[] location) {
12552        getLocationInWindow(location);
12553
12554        final AttachInfo info = mAttachInfo;
12555        if (info != null) {
12556            location[0] += info.mWindowLeft;
12557            location[1] += info.mWindowTop;
12558        }
12559    }
12560
12561    /**
12562     * <p>Computes the coordinates of this view in its window. The argument
12563     * must be an array of two integers. After the method returns, the array
12564     * contains the x and y location in that order.</p>
12565     *
12566     * @param location an array of two integers in which to hold the coordinates
12567     */
12568    public void getLocationInWindow(int[] location) {
12569        if (location == null || location.length < 2) {
12570            throw new IllegalArgumentException("location must be an array of two integers");
12571        }
12572
12573        if (mAttachInfo == null) {
12574            // When the view is not attached to a window, this method does not make sense
12575            location[0] = location[1] = 0;
12576            return;
12577        }
12578
12579        float[] position = mAttachInfo.mTmpTransformLocation;
12580        position[0] = position[1] = 0.0f;
12581
12582        if (!hasIdentityMatrix()) {
12583            getMatrix().mapPoints(position);
12584        }
12585
12586        position[0] += mLeft;
12587        position[1] += mTop;
12588
12589        ViewParent viewParent = mParent;
12590        while (viewParent instanceof View) {
12591            final View view = (View) viewParent;
12592
12593            position[0] -= view.mScrollX;
12594            position[1] -= view.mScrollY;
12595
12596            if (!view.hasIdentityMatrix()) {
12597                view.getMatrix().mapPoints(position);
12598            }
12599
12600            position[0] += view.mLeft;
12601            position[1] += view.mTop;
12602
12603            viewParent = view.mParent;
12604        }
12605
12606        if (viewParent instanceof ViewRootImpl) {
12607            // *cough*
12608            final ViewRootImpl vr = (ViewRootImpl) viewParent;
12609            position[1] -= vr.mCurScrollY;
12610        }
12611
12612        location[0] = (int) (position[0] + 0.5f);
12613        location[1] = (int) (position[1] + 0.5f);
12614    }
12615
12616    /**
12617     * {@hide}
12618     * @param id the id of the view to be found
12619     * @return the view of the specified id, null if cannot be found
12620     */
12621    protected View findViewTraversal(int id) {
12622        if (id == mID) {
12623            return this;
12624        }
12625        return null;
12626    }
12627
12628    /**
12629     * {@hide}
12630     * @param tag the tag of the view to be found
12631     * @return the view of specified tag, null if cannot be found
12632     */
12633    protected View findViewWithTagTraversal(Object tag) {
12634        if (tag != null && tag.equals(mTag)) {
12635            return this;
12636        }
12637        return null;
12638    }
12639
12640    /**
12641     * {@hide}
12642     * @param predicate The predicate to evaluate.
12643     * @param childToSkip If not null, ignores this child during the recursive traversal.
12644     * @return The first view that matches the predicate or null.
12645     */
12646    protected View findViewByPredicateTraversal(Predicate<View> predicate, View childToSkip) {
12647        if (predicate.apply(this)) {
12648            return this;
12649        }
12650        return null;
12651    }
12652
12653    /**
12654     * Look for a child view with the given id.  If this view has the given
12655     * id, return this view.
12656     *
12657     * @param id The id to search for.
12658     * @return The view that has the given id in the hierarchy or null
12659     */
12660    public final View findViewById(int id) {
12661        if (id < 0) {
12662            return null;
12663        }
12664        return findViewTraversal(id);
12665    }
12666
12667    /**
12668     * Finds a view by its unuque and stable accessibility id.
12669     *
12670     * @param accessibilityId The searched accessibility id.
12671     * @return The found view.
12672     */
12673    final View findViewByAccessibilityId(int accessibilityId) {
12674        if (accessibilityId < 0) {
12675            return null;
12676        }
12677        return findViewByAccessibilityIdTraversal(accessibilityId);
12678    }
12679
12680    /**
12681     * Performs the traversal to find a view by its unuque and stable accessibility id.
12682     *
12683     * <strong>Note:</strong>This method does not stop at the root namespace
12684     * boundary since the user can touch the screen at an arbitrary location
12685     * potentially crossing the root namespace bounday which will send an
12686     * accessibility event to accessibility services and they should be able
12687     * to obtain the event source. Also accessibility ids are guaranteed to be
12688     * unique in the window.
12689     *
12690     * @param accessibilityId The accessibility id.
12691     * @return The found view.
12692     */
12693    View findViewByAccessibilityIdTraversal(int accessibilityId) {
12694        if (getAccessibilityViewId() == accessibilityId) {
12695            return this;
12696        }
12697        return null;
12698    }
12699
12700    /**
12701     * Look for a child view with the given tag.  If this view has the given
12702     * tag, return this view.
12703     *
12704     * @param tag The tag to search for, using "tag.equals(getTag())".
12705     * @return The View that has the given tag in the hierarchy or null
12706     */
12707    public final View findViewWithTag(Object tag) {
12708        if (tag == null) {
12709            return null;
12710        }
12711        return findViewWithTagTraversal(tag);
12712    }
12713
12714    /**
12715     * {@hide}
12716     * Look for a child view that matches the specified predicate.
12717     * If this view matches the predicate, return this view.
12718     *
12719     * @param predicate The predicate to evaluate.
12720     * @return The first view that matches the predicate or null.
12721     */
12722    public final View findViewByPredicate(Predicate<View> predicate) {
12723        return findViewByPredicateTraversal(predicate, null);
12724    }
12725
12726    /**
12727     * {@hide}
12728     * Look for a child view that matches the specified predicate,
12729     * starting with the specified view and its descendents and then
12730     * recusively searching the ancestors and siblings of that view
12731     * until this view is reached.
12732     *
12733     * This method is useful in cases where the predicate does not match
12734     * a single unique view (perhaps multiple views use the same id)
12735     * and we are trying to find the view that is "closest" in scope to the
12736     * starting view.
12737     *
12738     * @param start The view to start from.
12739     * @param predicate The predicate to evaluate.
12740     * @return The first view that matches the predicate or null.
12741     */
12742    public final View findViewByPredicateInsideOut(View start, Predicate<View> predicate) {
12743        View childToSkip = null;
12744        for (;;) {
12745            View view = start.findViewByPredicateTraversal(predicate, childToSkip);
12746            if (view != null || start == this) {
12747                return view;
12748            }
12749
12750            ViewParent parent = start.getParent();
12751            if (parent == null || !(parent instanceof View)) {
12752                return null;
12753            }
12754
12755            childToSkip = start;
12756            start = (View) parent;
12757        }
12758    }
12759
12760    /**
12761     * Sets the identifier for this view. The identifier does not have to be
12762     * unique in this view's hierarchy. The identifier should be a positive
12763     * number.
12764     *
12765     * @see #NO_ID
12766     * @see #getId()
12767     * @see #findViewById(int)
12768     *
12769     * @param id a number used to identify the view
12770     *
12771     * @attr ref android.R.styleable#View_id
12772     */
12773    public void setId(int id) {
12774        mID = id;
12775    }
12776
12777    /**
12778     * {@hide}
12779     *
12780     * @param isRoot true if the view belongs to the root namespace, false
12781     *        otherwise
12782     */
12783    public void setIsRootNamespace(boolean isRoot) {
12784        if (isRoot) {
12785            mPrivateFlags |= IS_ROOT_NAMESPACE;
12786        } else {
12787            mPrivateFlags &= ~IS_ROOT_NAMESPACE;
12788        }
12789    }
12790
12791    /**
12792     * {@hide}
12793     *
12794     * @return true if the view belongs to the root namespace, false otherwise
12795     */
12796    public boolean isRootNamespace() {
12797        return (mPrivateFlags&IS_ROOT_NAMESPACE) != 0;
12798    }
12799
12800    /**
12801     * Returns this view's identifier.
12802     *
12803     * @return a positive integer used to identify the view or {@link #NO_ID}
12804     *         if the view has no ID
12805     *
12806     * @see #setId(int)
12807     * @see #findViewById(int)
12808     * @attr ref android.R.styleable#View_id
12809     */
12810    @ViewDebug.CapturedViewProperty
12811    public int getId() {
12812        return mID;
12813    }
12814
12815    /**
12816     * Returns this view's tag.
12817     *
12818     * @return the Object stored in this view as a tag
12819     *
12820     * @see #setTag(Object)
12821     * @see #getTag(int)
12822     */
12823    @ViewDebug.ExportedProperty
12824    public Object getTag() {
12825        return mTag;
12826    }
12827
12828    /**
12829     * Sets the tag associated with this view. A tag can be used to mark
12830     * a view in its hierarchy and does not have to be unique within the
12831     * hierarchy. Tags can also be used to store data within a view without
12832     * resorting to another data structure.
12833     *
12834     * @param tag an Object to tag the view with
12835     *
12836     * @see #getTag()
12837     * @see #setTag(int, Object)
12838     */
12839    public void setTag(final Object tag) {
12840        mTag = tag;
12841    }
12842
12843    /**
12844     * Returns the tag associated with this view and the specified key.
12845     *
12846     * @param key The key identifying the tag
12847     *
12848     * @return the Object stored in this view as a tag
12849     *
12850     * @see #setTag(int, Object)
12851     * @see #getTag()
12852     */
12853    public Object getTag(int key) {
12854        if (mKeyedTags != null) return mKeyedTags.get(key);
12855        return null;
12856    }
12857
12858    /**
12859     * Sets a tag associated with this view and a key. A tag can be used
12860     * to mark a view in its hierarchy and does not have to be unique within
12861     * the hierarchy. Tags can also be used to store data within a view
12862     * without resorting to another data structure.
12863     *
12864     * The specified key should be an id declared in the resources of the
12865     * application to ensure it is unique (see the <a
12866     * href={@docRoot}guide/topics/resources/more-resources.html#Id">ID resource type</a>).
12867     * Keys identified as belonging to
12868     * the Android framework or not associated with any package will cause
12869     * an {@link IllegalArgumentException} to be thrown.
12870     *
12871     * @param key The key identifying the tag
12872     * @param tag An Object to tag the view with
12873     *
12874     * @throws IllegalArgumentException If they specified key is not valid
12875     *
12876     * @see #setTag(Object)
12877     * @see #getTag(int)
12878     */
12879    public void setTag(int key, final Object tag) {
12880        // If the package id is 0x00 or 0x01, it's either an undefined package
12881        // or a framework id
12882        if ((key >>> 24) < 2) {
12883            throw new IllegalArgumentException("The key must be an application-specific "
12884                    + "resource id.");
12885        }
12886
12887        setKeyedTag(key, tag);
12888    }
12889
12890    /**
12891     * Variation of {@link #setTag(int, Object)} that enforces the key to be a
12892     * framework id.
12893     *
12894     * @hide
12895     */
12896    public void setTagInternal(int key, Object tag) {
12897        if ((key >>> 24) != 0x1) {
12898            throw new IllegalArgumentException("The key must be a framework-specific "
12899                    + "resource id.");
12900        }
12901
12902        setKeyedTag(key, tag);
12903    }
12904
12905    private void setKeyedTag(int key, Object tag) {
12906        if (mKeyedTags == null) {
12907            mKeyedTags = new SparseArray<Object>();
12908        }
12909
12910        mKeyedTags.put(key, tag);
12911    }
12912
12913    /**
12914     * @param consistency The type of consistency. See ViewDebug for more information.
12915     *
12916     * @hide
12917     */
12918    protected boolean dispatchConsistencyCheck(int consistency) {
12919        return onConsistencyCheck(consistency);
12920    }
12921
12922    /**
12923     * Method that subclasses should implement to check their consistency. The type of
12924     * consistency check is indicated by the bit field passed as a parameter.
12925     *
12926     * @param consistency The type of consistency. See ViewDebug for more information.
12927     *
12928     * @throws IllegalStateException if the view is in an inconsistent state.
12929     *
12930     * @hide
12931     */
12932    protected boolean onConsistencyCheck(int consistency) {
12933        boolean result = true;
12934
12935        final boolean checkLayout = (consistency & ViewDebug.CONSISTENCY_LAYOUT) != 0;
12936        final boolean checkDrawing = (consistency & ViewDebug.CONSISTENCY_DRAWING) != 0;
12937
12938        if (checkLayout) {
12939            if (getParent() == null) {
12940                result = false;
12941                android.util.Log.d(ViewDebug.CONSISTENCY_LOG_TAG,
12942                        "View " + this + " does not have a parent.");
12943            }
12944
12945            if (mAttachInfo == null) {
12946                result = false;
12947                android.util.Log.d(ViewDebug.CONSISTENCY_LOG_TAG,
12948                        "View " + this + " is not attached to a window.");
12949            }
12950        }
12951
12952        if (checkDrawing) {
12953            // Do not check the DIRTY/DRAWN flags because views can call invalidate()
12954            // from their draw() method
12955
12956            if ((mPrivateFlags & DRAWN) != DRAWN &&
12957                    (mPrivateFlags & DRAWING_CACHE_VALID) == DRAWING_CACHE_VALID) {
12958                result = false;
12959                android.util.Log.d(ViewDebug.CONSISTENCY_LOG_TAG,
12960                        "View " + this + " was invalidated but its drawing cache is valid.");
12961            }
12962        }
12963
12964        return result;
12965    }
12966
12967    /**
12968     * Prints information about this view in the log output, with the tag
12969     * {@link #VIEW_LOG_TAG}.
12970     *
12971     * @hide
12972     */
12973    public void debug() {
12974        debug(0);
12975    }
12976
12977    /**
12978     * Prints information about this view in the log output, with the tag
12979     * {@link #VIEW_LOG_TAG}. Each line in the output is preceded with an
12980     * indentation defined by the <code>depth</code>.
12981     *
12982     * @param depth the indentation level
12983     *
12984     * @hide
12985     */
12986    protected void debug(int depth) {
12987        String output = debugIndent(depth - 1);
12988
12989        output += "+ " + this;
12990        int id = getId();
12991        if (id != -1) {
12992            output += " (id=" + id + ")";
12993        }
12994        Object tag = getTag();
12995        if (tag != null) {
12996            output += " (tag=" + tag + ")";
12997        }
12998        Log.d(VIEW_LOG_TAG, output);
12999
13000        if ((mPrivateFlags & FOCUSED) != 0) {
13001            output = debugIndent(depth) + " FOCUSED";
13002            Log.d(VIEW_LOG_TAG, output);
13003        }
13004
13005        output = debugIndent(depth);
13006        output += "frame={" + mLeft + ", " + mTop + ", " + mRight
13007                + ", " + mBottom + "} scroll={" + mScrollX + ", " + mScrollY
13008                + "} ";
13009        Log.d(VIEW_LOG_TAG, output);
13010
13011        if (mPaddingLeft != 0 || mPaddingTop != 0 || mPaddingRight != 0
13012                || mPaddingBottom != 0) {
13013            output = debugIndent(depth);
13014            output += "padding={" + mPaddingLeft + ", " + mPaddingTop
13015                    + ", " + mPaddingRight + ", " + mPaddingBottom + "}";
13016            Log.d(VIEW_LOG_TAG, output);
13017        }
13018
13019        output = debugIndent(depth);
13020        output += "mMeasureWidth=" + mMeasuredWidth +
13021                " mMeasureHeight=" + mMeasuredHeight;
13022        Log.d(VIEW_LOG_TAG, output);
13023
13024        output = debugIndent(depth);
13025        if (mLayoutParams == null) {
13026            output += "BAD! no layout params";
13027        } else {
13028            output = mLayoutParams.debug(output);
13029        }
13030        Log.d(VIEW_LOG_TAG, output);
13031
13032        output = debugIndent(depth);
13033        output += "flags={";
13034        output += View.printFlags(mViewFlags);
13035        output += "}";
13036        Log.d(VIEW_LOG_TAG, output);
13037
13038        output = debugIndent(depth);
13039        output += "privateFlags={";
13040        output += View.printPrivateFlags(mPrivateFlags);
13041        output += "}";
13042        Log.d(VIEW_LOG_TAG, output);
13043    }
13044
13045    /**
13046     * Creates an string of whitespaces used for indentation.
13047     *
13048     * @param depth the indentation level
13049     * @return a String containing (depth * 2 + 3) * 2 white spaces
13050     *
13051     * @hide
13052     */
13053    protected static String debugIndent(int depth) {
13054        StringBuilder spaces = new StringBuilder((depth * 2 + 3) * 2);
13055        for (int i = 0; i < (depth * 2) + 3; i++) {
13056            spaces.append(' ').append(' ');
13057        }
13058        return spaces.toString();
13059    }
13060
13061    /**
13062     * <p>Return the offset of the widget's text baseline from the widget's top
13063     * boundary. If this widget does not support baseline alignment, this
13064     * method returns -1. </p>
13065     *
13066     * @return the offset of the baseline within the widget's bounds or -1
13067     *         if baseline alignment is not supported
13068     */
13069    @ViewDebug.ExportedProperty(category = "layout")
13070    public int getBaseline() {
13071        return -1;
13072    }
13073
13074    /**
13075     * Call this when something has changed which has invalidated the
13076     * layout of this view. This will schedule a layout pass of the view
13077     * tree.
13078     */
13079    public void requestLayout() {
13080        if (ViewDebug.TRACE_HIERARCHY) {
13081            ViewDebug.trace(this, ViewDebug.HierarchyTraceType.REQUEST_LAYOUT);
13082        }
13083
13084        mPrivateFlags |= FORCE_LAYOUT;
13085        mPrivateFlags |= INVALIDATED;
13086
13087        if (mParent != null) {
13088            if (mLayoutParams != null) {
13089                mLayoutParams.onResolveLayoutDirection(getResolvedLayoutDirection());
13090            }
13091            if (!mParent.isLayoutRequested()) {
13092                mParent.requestLayout();
13093            }
13094        }
13095    }
13096
13097    /**
13098     * Forces this view to be laid out during the next layout pass.
13099     * This method does not call requestLayout() or forceLayout()
13100     * on the parent.
13101     */
13102    public void forceLayout() {
13103        mPrivateFlags |= FORCE_LAYOUT;
13104        mPrivateFlags |= INVALIDATED;
13105    }
13106
13107    /**
13108     * <p>
13109     * This is called to find out how big a view should be. The parent
13110     * supplies constraint information in the width and height parameters.
13111     * </p>
13112     *
13113     * <p>
13114     * The actual measurement work of a view is performed in
13115     * {@link #onMeasure(int, int)}, called by this method. Therefore, only
13116     * {@link #onMeasure(int, int)} can and must be overridden by subclasses.
13117     * </p>
13118     *
13119     *
13120     * @param widthMeasureSpec Horizontal space requirements as imposed by the
13121     *        parent
13122     * @param heightMeasureSpec Vertical space requirements as imposed by the
13123     *        parent
13124     *
13125     * @see #onMeasure(int, int)
13126     */
13127    public final void measure(int widthMeasureSpec, int heightMeasureSpec) {
13128        if ((mPrivateFlags & FORCE_LAYOUT) == FORCE_LAYOUT ||
13129                widthMeasureSpec != mOldWidthMeasureSpec ||
13130                heightMeasureSpec != mOldHeightMeasureSpec) {
13131
13132            // first clears the measured dimension flag
13133            mPrivateFlags &= ~MEASURED_DIMENSION_SET;
13134
13135            if (ViewDebug.TRACE_HIERARCHY) {
13136                ViewDebug.trace(this, ViewDebug.HierarchyTraceType.ON_MEASURE);
13137            }
13138
13139            // measure ourselves, this should set the measured dimension flag back
13140            onMeasure(widthMeasureSpec, heightMeasureSpec);
13141
13142            // flag not set, setMeasuredDimension() was not invoked, we raise
13143            // an exception to warn the developer
13144            if ((mPrivateFlags & MEASURED_DIMENSION_SET) != MEASURED_DIMENSION_SET) {
13145                throw new IllegalStateException("onMeasure() did not set the"
13146                        + " measured dimension by calling"
13147                        + " setMeasuredDimension()");
13148            }
13149
13150            mPrivateFlags |= LAYOUT_REQUIRED;
13151        }
13152
13153        mOldWidthMeasureSpec = widthMeasureSpec;
13154        mOldHeightMeasureSpec = heightMeasureSpec;
13155    }
13156
13157    /**
13158     * <p>
13159     * Measure the view and its content to determine the measured width and the
13160     * measured height. This method is invoked by {@link #measure(int, int)} and
13161     * should be overriden by subclasses to provide accurate and efficient
13162     * measurement of their contents.
13163     * </p>
13164     *
13165     * <p>
13166     * <strong>CONTRACT:</strong> When overriding this method, you
13167     * <em>must</em> call {@link #setMeasuredDimension(int, int)} to store the
13168     * measured width and height of this view. Failure to do so will trigger an
13169     * <code>IllegalStateException</code>, thrown by
13170     * {@link #measure(int, int)}. Calling the superclass'
13171     * {@link #onMeasure(int, int)} is a valid use.
13172     * </p>
13173     *
13174     * <p>
13175     * The base class implementation of measure defaults to the background size,
13176     * unless a larger size is allowed by the MeasureSpec. Subclasses should
13177     * override {@link #onMeasure(int, int)} to provide better measurements of
13178     * their content.
13179     * </p>
13180     *
13181     * <p>
13182     * If this method is overridden, it is the subclass's responsibility to make
13183     * sure the measured height and width are at least the view's minimum height
13184     * and width ({@link #getSuggestedMinimumHeight()} and
13185     * {@link #getSuggestedMinimumWidth()}).
13186     * </p>
13187     *
13188     * @param widthMeasureSpec horizontal space requirements as imposed by the parent.
13189     *                         The requirements are encoded with
13190     *                         {@link android.view.View.MeasureSpec}.
13191     * @param heightMeasureSpec vertical space requirements as imposed by the parent.
13192     *                         The requirements are encoded with
13193     *                         {@link android.view.View.MeasureSpec}.
13194     *
13195     * @see #getMeasuredWidth()
13196     * @see #getMeasuredHeight()
13197     * @see #setMeasuredDimension(int, int)
13198     * @see #getSuggestedMinimumHeight()
13199     * @see #getSuggestedMinimumWidth()
13200     * @see android.view.View.MeasureSpec#getMode(int)
13201     * @see android.view.View.MeasureSpec#getSize(int)
13202     */
13203    protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
13204        setMeasuredDimension(getDefaultSize(getSuggestedMinimumWidth(), widthMeasureSpec),
13205                getDefaultSize(getSuggestedMinimumHeight(), heightMeasureSpec));
13206    }
13207
13208    /**
13209     * <p>This mehod must be called by {@link #onMeasure(int, int)} to store the
13210     * measured width and measured height. Failing to do so will trigger an
13211     * exception at measurement time.</p>
13212     *
13213     * @param measuredWidth The measured width of this view.  May be a complex
13214     * bit mask as defined by {@link #MEASURED_SIZE_MASK} and
13215     * {@link #MEASURED_STATE_TOO_SMALL}.
13216     * @param measuredHeight The measured height of this view.  May be a complex
13217     * bit mask as defined by {@link #MEASURED_SIZE_MASK} and
13218     * {@link #MEASURED_STATE_TOO_SMALL}.
13219     */
13220    protected final void setMeasuredDimension(int measuredWidth, int measuredHeight) {
13221        mMeasuredWidth = measuredWidth;
13222        mMeasuredHeight = measuredHeight;
13223
13224        mPrivateFlags |= MEASURED_DIMENSION_SET;
13225    }
13226
13227    /**
13228     * Merge two states as returned by {@link #getMeasuredState()}.
13229     * @param curState The current state as returned from a view or the result
13230     * of combining multiple views.
13231     * @param newState The new view state to combine.
13232     * @return Returns a new integer reflecting the combination of the two
13233     * states.
13234     */
13235    public static int combineMeasuredStates(int curState, int newState) {
13236        return curState | newState;
13237    }
13238
13239    /**
13240     * Version of {@link #resolveSizeAndState(int, int, int)}
13241     * returning only the {@link #MEASURED_SIZE_MASK} bits of the result.
13242     */
13243    public static int resolveSize(int size, int measureSpec) {
13244        return resolveSizeAndState(size, measureSpec, 0) & MEASURED_SIZE_MASK;
13245    }
13246
13247    /**
13248     * Utility to reconcile a desired size and state, with constraints imposed
13249     * by a MeasureSpec.  Will take the desired size, unless a different size
13250     * is imposed by the constraints.  The returned value is a compound integer,
13251     * with the resolved size in the {@link #MEASURED_SIZE_MASK} bits and
13252     * optionally the bit {@link #MEASURED_STATE_TOO_SMALL} set if the resulting
13253     * size is smaller than the size the view wants to be.
13254     *
13255     * @param size How big the view wants to be
13256     * @param measureSpec Constraints imposed by the parent
13257     * @return Size information bit mask as defined by
13258     * {@link #MEASURED_SIZE_MASK} and {@link #MEASURED_STATE_TOO_SMALL}.
13259     */
13260    public static int resolveSizeAndState(int size, int measureSpec, int childMeasuredState) {
13261        int result = size;
13262        int specMode = MeasureSpec.getMode(measureSpec);
13263        int specSize =  MeasureSpec.getSize(measureSpec);
13264        switch (specMode) {
13265        case MeasureSpec.UNSPECIFIED:
13266            result = size;
13267            break;
13268        case MeasureSpec.AT_MOST:
13269            if (specSize < size) {
13270                result = specSize | MEASURED_STATE_TOO_SMALL;
13271            } else {
13272                result = size;
13273            }
13274            break;
13275        case MeasureSpec.EXACTLY:
13276            result = specSize;
13277            break;
13278        }
13279        return result | (childMeasuredState&MEASURED_STATE_MASK);
13280    }
13281
13282    /**
13283     * Utility to return a default size. Uses the supplied size if the
13284     * MeasureSpec imposed no constraints. Will get larger if allowed
13285     * by the MeasureSpec.
13286     *
13287     * @param size Default size for this view
13288     * @param measureSpec Constraints imposed by the parent
13289     * @return The size this view should be.
13290     */
13291    public static int getDefaultSize(int size, int measureSpec) {
13292        int result = size;
13293        int specMode = MeasureSpec.getMode(measureSpec);
13294        int specSize = MeasureSpec.getSize(measureSpec);
13295
13296        switch (specMode) {
13297        case MeasureSpec.UNSPECIFIED:
13298            result = size;
13299            break;
13300        case MeasureSpec.AT_MOST:
13301        case MeasureSpec.EXACTLY:
13302            result = specSize;
13303            break;
13304        }
13305        return result;
13306    }
13307
13308    /**
13309     * Returns the suggested minimum height that the view should use. This
13310     * returns the maximum of the view's minimum height
13311     * and the background's minimum height
13312     * ({@link android.graphics.drawable.Drawable#getMinimumHeight()}).
13313     * <p>
13314     * When being used in {@link #onMeasure(int, int)}, the caller should still
13315     * ensure the returned height is within the requirements of the parent.
13316     *
13317     * @return The suggested minimum height of the view.
13318     */
13319    protected int getSuggestedMinimumHeight() {
13320        int suggestedMinHeight = mMinHeight;
13321
13322        if (mBGDrawable != null) {
13323            final int bgMinHeight = mBGDrawable.getMinimumHeight();
13324            if (suggestedMinHeight < bgMinHeight) {
13325                suggestedMinHeight = bgMinHeight;
13326            }
13327        }
13328
13329        return suggestedMinHeight;
13330    }
13331
13332    /**
13333     * Returns the suggested minimum width that the view should use. This
13334     * returns the maximum of the view's minimum width)
13335     * and the background's minimum width
13336     *  ({@link android.graphics.drawable.Drawable#getMinimumWidth()}).
13337     * <p>
13338     * When being used in {@link #onMeasure(int, int)}, the caller should still
13339     * ensure the returned width is within the requirements of the parent.
13340     *
13341     * @return The suggested minimum width of the view.
13342     */
13343    protected int getSuggestedMinimumWidth() {
13344        int suggestedMinWidth = mMinWidth;
13345
13346        if (mBGDrawable != null) {
13347            final int bgMinWidth = mBGDrawable.getMinimumWidth();
13348            if (suggestedMinWidth < bgMinWidth) {
13349                suggestedMinWidth = bgMinWidth;
13350            }
13351        }
13352
13353        return suggestedMinWidth;
13354    }
13355
13356    /**
13357     * Sets the minimum height of the view. It is not guaranteed the view will
13358     * be able to achieve this minimum height (for example, if its parent layout
13359     * constrains it with less available height).
13360     *
13361     * @param minHeight The minimum height the view will try to be.
13362     */
13363    public void setMinimumHeight(int minHeight) {
13364        mMinHeight = minHeight;
13365    }
13366
13367    /**
13368     * Sets the minimum width of the view. It is not guaranteed the view will
13369     * be able to achieve this minimum width (for example, if its parent layout
13370     * constrains it with less available width).
13371     *
13372     * @param minWidth The minimum width the view will try to be.
13373     */
13374    public void setMinimumWidth(int minWidth) {
13375        mMinWidth = minWidth;
13376    }
13377
13378    /**
13379     * Get the animation currently associated with this view.
13380     *
13381     * @return The animation that is currently playing or
13382     *         scheduled to play for this view.
13383     */
13384    public Animation getAnimation() {
13385        return mCurrentAnimation;
13386    }
13387
13388    /**
13389     * Start the specified animation now.
13390     *
13391     * @param animation the animation to start now
13392     */
13393    public void startAnimation(Animation animation) {
13394        animation.setStartTime(Animation.START_ON_FIRST_FRAME);
13395        setAnimation(animation);
13396        invalidateParentCaches();
13397        invalidate(true);
13398    }
13399
13400    /**
13401     * Cancels any animations for this view.
13402     */
13403    public void clearAnimation() {
13404        if (mCurrentAnimation != null) {
13405            mCurrentAnimation.detach();
13406        }
13407        mCurrentAnimation = null;
13408        invalidateParentIfNeeded();
13409    }
13410
13411    /**
13412     * Sets the next animation to play for this view.
13413     * If you want the animation to play immediately, use
13414     * startAnimation. This method provides allows fine-grained
13415     * control over the start time and invalidation, but you
13416     * must make sure that 1) the animation has a start time set, and
13417     * 2) the view will be invalidated when the animation is supposed to
13418     * start.
13419     *
13420     * @param animation The next animation, or null.
13421     */
13422    public void setAnimation(Animation animation) {
13423        mCurrentAnimation = animation;
13424        if (animation != null) {
13425            animation.reset();
13426        }
13427    }
13428
13429    /**
13430     * Invoked by a parent ViewGroup to notify the start of the animation
13431     * currently associated with this view. If you override this method,
13432     * always call super.onAnimationStart();
13433     *
13434     * @see #setAnimation(android.view.animation.Animation)
13435     * @see #getAnimation()
13436     */
13437    protected void onAnimationStart() {
13438        mPrivateFlags |= ANIMATION_STARTED;
13439    }
13440
13441    /**
13442     * Invoked by a parent ViewGroup to notify the end of the animation
13443     * currently associated with this view. If you override this method,
13444     * always call super.onAnimationEnd();
13445     *
13446     * @see #setAnimation(android.view.animation.Animation)
13447     * @see #getAnimation()
13448     */
13449    protected void onAnimationEnd() {
13450        mPrivateFlags &= ~ANIMATION_STARTED;
13451    }
13452
13453    /**
13454     * Invoked if there is a Transform that involves alpha. Subclass that can
13455     * draw themselves with the specified alpha should return true, and then
13456     * respect that alpha when their onDraw() is called. If this returns false
13457     * then the view may be redirected to draw into an offscreen buffer to
13458     * fulfill the request, which will look fine, but may be slower than if the
13459     * subclass handles it internally. The default implementation returns false.
13460     *
13461     * @param alpha The alpha (0..255) to apply to the view's drawing
13462     * @return true if the view can draw with the specified alpha.
13463     */
13464    protected boolean onSetAlpha(int alpha) {
13465        return false;
13466    }
13467
13468    /**
13469     * This is used by the RootView to perform an optimization when
13470     * the view hierarchy contains one or several SurfaceView.
13471     * SurfaceView is always considered transparent, but its children are not,
13472     * therefore all View objects remove themselves from the global transparent
13473     * region (passed as a parameter to this function).
13474     *
13475     * @param region The transparent region for this ViewAncestor (window).
13476     *
13477     * @return Returns true if the effective visibility of the view at this
13478     * point is opaque, regardless of the transparent region; returns false
13479     * if it is possible for underlying windows to be seen behind the view.
13480     *
13481     * {@hide}
13482     */
13483    public boolean gatherTransparentRegion(Region region) {
13484        final AttachInfo attachInfo = mAttachInfo;
13485        if (region != null && attachInfo != null) {
13486            final int pflags = mPrivateFlags;
13487            if ((pflags & SKIP_DRAW) == 0) {
13488                // The SKIP_DRAW flag IS NOT set, so this view draws. We need to
13489                // remove it from the transparent region.
13490                final int[] location = attachInfo.mTransparentLocation;
13491                getLocationInWindow(location);
13492                region.op(location[0], location[1], location[0] + mRight - mLeft,
13493                        location[1] + mBottom - mTop, Region.Op.DIFFERENCE);
13494            } else if ((pflags & ONLY_DRAWS_BACKGROUND) != 0 && mBGDrawable != null) {
13495                // The ONLY_DRAWS_BACKGROUND flag IS set and the background drawable
13496                // exists, so we remove the background drawable's non-transparent
13497                // parts from this transparent region.
13498                applyDrawableToTransparentRegion(mBGDrawable, region);
13499            }
13500        }
13501        return true;
13502    }
13503
13504    /**
13505     * Play a sound effect for this view.
13506     *
13507     * <p>The framework will play sound effects for some built in actions, such as
13508     * clicking, but you may wish to play these effects in your widget,
13509     * for instance, for internal navigation.
13510     *
13511     * <p>The sound effect will only be played if sound effects are enabled by the user, and
13512     * {@link #isSoundEffectsEnabled()} is true.
13513     *
13514     * @param soundConstant One of the constants defined in {@link SoundEffectConstants}
13515     */
13516    public void playSoundEffect(int soundConstant) {
13517        if (mAttachInfo == null || mAttachInfo.mRootCallbacks == null || !isSoundEffectsEnabled()) {
13518            return;
13519        }
13520        mAttachInfo.mRootCallbacks.playSoundEffect(soundConstant);
13521    }
13522
13523    /**
13524     * BZZZTT!!1!
13525     *
13526     * <p>Provide haptic feedback to the user for this view.
13527     *
13528     * <p>The framework will provide haptic feedback for some built in actions,
13529     * such as long presses, but you may wish to provide feedback for your
13530     * own widget.
13531     *
13532     * <p>The feedback will only be performed if
13533     * {@link #isHapticFeedbackEnabled()} is true.
13534     *
13535     * @param feedbackConstant One of the constants defined in
13536     * {@link HapticFeedbackConstants}
13537     */
13538    public boolean performHapticFeedback(int feedbackConstant) {
13539        return performHapticFeedback(feedbackConstant, 0);
13540    }
13541
13542    /**
13543     * BZZZTT!!1!
13544     *
13545     * <p>Like {@link #performHapticFeedback(int)}, with additional options.
13546     *
13547     * @param feedbackConstant One of the constants defined in
13548     * {@link HapticFeedbackConstants}
13549     * @param flags Additional flags as per {@link HapticFeedbackConstants}.
13550     */
13551    public boolean performHapticFeedback(int feedbackConstant, int flags) {
13552        if (mAttachInfo == null) {
13553            return false;
13554        }
13555        //noinspection SimplifiableIfStatement
13556        if ((flags & HapticFeedbackConstants.FLAG_IGNORE_VIEW_SETTING) == 0
13557                && !isHapticFeedbackEnabled()) {
13558            return false;
13559        }
13560        return mAttachInfo.mRootCallbacks.performHapticFeedback(feedbackConstant,
13561                (flags & HapticFeedbackConstants.FLAG_IGNORE_GLOBAL_SETTING) != 0);
13562    }
13563
13564    /**
13565     * Request that the visibility of the status bar be changed.
13566     * @param visibility  Bitwise-or of flags {@link #SYSTEM_UI_FLAG_LOW_PROFILE} or
13567     * {@link #SYSTEM_UI_FLAG_HIDE_NAVIGATION}.
13568     */
13569    public void setSystemUiVisibility(int visibility) {
13570        if (visibility != mSystemUiVisibility) {
13571            mSystemUiVisibility = visibility;
13572            if (mParent != null && mAttachInfo != null && !mAttachInfo.mRecomputeGlobalAttributes) {
13573                mParent.recomputeViewAttributes(this);
13574            }
13575        }
13576    }
13577
13578    /**
13579     * Returns the status bar visibility that this view has requested.
13580     * @return  Bitwise-or of flags {@link #SYSTEM_UI_FLAG_LOW_PROFILE} or
13581     * {@link #SYSTEM_UI_FLAG_HIDE_NAVIGATION}.
13582     */
13583    public int getSystemUiVisibility() {
13584        return mSystemUiVisibility;
13585    }
13586
13587    /**
13588     * Set a listener to receive callbacks when the visibility of the system bar changes.
13589     * @param l  The {@link OnSystemUiVisibilityChangeListener} to receive callbacks.
13590     */
13591    public void setOnSystemUiVisibilityChangeListener(OnSystemUiVisibilityChangeListener l) {
13592        getListenerInfo().mOnSystemUiVisibilityChangeListener = l;
13593        if (mParent != null && mAttachInfo != null && !mAttachInfo.mRecomputeGlobalAttributes) {
13594            mParent.recomputeViewAttributes(this);
13595        }
13596    }
13597
13598    /**
13599     * Dispatch callbacks to {@link #setOnSystemUiVisibilityChangeListener} down
13600     * the view hierarchy.
13601     */
13602    public void dispatchSystemUiVisibilityChanged(int visibility) {
13603        ListenerInfo li = mListenerInfo;
13604        if (li != null && li.mOnSystemUiVisibilityChangeListener != null) {
13605            li.mOnSystemUiVisibilityChangeListener.onSystemUiVisibilityChange(
13606                    visibility & PUBLIC_STATUS_BAR_VISIBILITY_MASK);
13607        }
13608    }
13609
13610    void updateLocalSystemUiVisibility(int localValue, int localChanges) {
13611        int val = (mSystemUiVisibility&~localChanges) | (localValue&localChanges);
13612        if (val != mSystemUiVisibility) {
13613            setSystemUiVisibility(val);
13614        }
13615    }
13616
13617    /**
13618     * Creates an image that the system displays during the drag and drop
13619     * operation. This is called a &quot;drag shadow&quot;. The default implementation
13620     * for a DragShadowBuilder based on a View returns an image that has exactly the same
13621     * appearance as the given View. The default also positions the center of the drag shadow
13622     * directly under the touch point. If no View is provided (the constructor with no parameters
13623     * is used), and {@link #onProvideShadowMetrics(Point,Point) onProvideShadowMetrics()} and
13624     * {@link #onDrawShadow(Canvas) onDrawShadow()} are not overriden, then the
13625     * default is an invisible drag shadow.
13626     * <p>
13627     * You are not required to use the View you provide to the constructor as the basis of the
13628     * drag shadow. The {@link #onDrawShadow(Canvas) onDrawShadow()} method allows you to draw
13629     * anything you want as the drag shadow.
13630     * </p>
13631     * <p>
13632     *  You pass a DragShadowBuilder object to the system when you start the drag. The system
13633     *  calls {@link #onProvideShadowMetrics(Point,Point) onProvideShadowMetrics()} to get the
13634     *  size and position of the drag shadow. It uses this data to construct a
13635     *  {@link android.graphics.Canvas} object, then it calls {@link #onDrawShadow(Canvas) onDrawShadow()}
13636     *  so that your application can draw the shadow image in the Canvas.
13637     * </p>
13638     *
13639     * <div class="special reference">
13640     * <h3>Developer Guides</h3>
13641     * <p>For a guide to implementing drag and drop features, read the
13642     * <a href="{@docRoot}guide/topics/ui/drag-drop.html">Drag and Drop</a> developer guide.</p>
13643     * </div>
13644     */
13645    public static class DragShadowBuilder {
13646        private final WeakReference<View> mView;
13647
13648        /**
13649         * Constructs a shadow image builder based on a View. By default, the resulting drag
13650         * shadow will have the same appearance and dimensions as the View, with the touch point
13651         * over the center of the View.
13652         * @param view A View. Any View in scope can be used.
13653         */
13654        public DragShadowBuilder(View view) {
13655            mView = new WeakReference<View>(view);
13656        }
13657
13658        /**
13659         * Construct a shadow builder object with no associated View.  This
13660         * constructor variant is only useful when the {@link #onProvideShadowMetrics(Point, Point)}
13661         * and {@link #onDrawShadow(Canvas)} methods are also overridden in order
13662         * to supply the drag shadow's dimensions and appearance without
13663         * reference to any View object. If they are not overridden, then the result is an
13664         * invisible drag shadow.
13665         */
13666        public DragShadowBuilder() {
13667            mView = new WeakReference<View>(null);
13668        }
13669
13670        /**
13671         * Returns the View object that had been passed to the
13672         * {@link #View.DragShadowBuilder(View)}
13673         * constructor.  If that View parameter was {@code null} or if the
13674         * {@link #View.DragShadowBuilder()}
13675         * constructor was used to instantiate the builder object, this method will return
13676         * null.
13677         *
13678         * @return The View object associate with this builder object.
13679         */
13680        @SuppressWarnings({"JavadocReference"})
13681        final public View getView() {
13682            return mView.get();
13683        }
13684
13685        /**
13686         * Provides the metrics for the shadow image. These include the dimensions of
13687         * the shadow image, and the point within that shadow that should
13688         * be centered under the touch location while dragging.
13689         * <p>
13690         * The default implementation sets the dimensions of the shadow to be the
13691         * same as the dimensions of the View itself and centers the shadow under
13692         * the touch point.
13693         * </p>
13694         *
13695         * @param shadowSize A {@link android.graphics.Point} containing the width and height
13696         * of the shadow image. Your application must set {@link android.graphics.Point#x} to the
13697         * desired width and must set {@link android.graphics.Point#y} to the desired height of the
13698         * image.
13699         *
13700         * @param shadowTouchPoint A {@link android.graphics.Point} for the position within the
13701         * shadow image that should be underneath the touch point during the drag and drop
13702         * operation. Your application must set {@link android.graphics.Point#x} to the
13703         * X coordinate and {@link android.graphics.Point#y} to the Y coordinate of this position.
13704         */
13705        public void onProvideShadowMetrics(Point shadowSize, Point shadowTouchPoint) {
13706            final View view = mView.get();
13707            if (view != null) {
13708                shadowSize.set(view.getWidth(), view.getHeight());
13709                shadowTouchPoint.set(shadowSize.x / 2, shadowSize.y / 2);
13710            } else {
13711                Log.e(View.VIEW_LOG_TAG, "Asked for drag thumb metrics but no view");
13712            }
13713        }
13714
13715        /**
13716         * Draws the shadow image. The system creates the {@link android.graphics.Canvas} object
13717         * based on the dimensions it received from the
13718         * {@link #onProvideShadowMetrics(Point, Point)} callback.
13719         *
13720         * @param canvas A {@link android.graphics.Canvas} object in which to draw the shadow image.
13721         */
13722        public void onDrawShadow(Canvas canvas) {
13723            final View view = mView.get();
13724            if (view != null) {
13725                view.draw(canvas);
13726            } else {
13727                Log.e(View.VIEW_LOG_TAG, "Asked to draw drag shadow but no view");
13728            }
13729        }
13730    }
13731
13732    /**
13733     * Starts a drag and drop operation. When your application calls this method, it passes a
13734     * {@link android.view.View.DragShadowBuilder} object to the system. The
13735     * system calls this object's {@link DragShadowBuilder#onProvideShadowMetrics(Point, Point)}
13736     * to get metrics for the drag shadow, and then calls the object's
13737     * {@link DragShadowBuilder#onDrawShadow(Canvas)} to draw the drag shadow itself.
13738     * <p>
13739     *  Once the system has the drag shadow, it begins the drag and drop operation by sending
13740     *  drag events to all the View objects in your application that are currently visible. It does
13741     *  this either by calling the View object's drag listener (an implementation of
13742     *  {@link android.view.View.OnDragListener#onDrag(View,DragEvent) onDrag()} or by calling the
13743     *  View object's {@link android.view.View#onDragEvent(DragEvent) onDragEvent()} method.
13744     *  Both are passed a {@link android.view.DragEvent} object that has a
13745     *  {@link android.view.DragEvent#getAction()} value of
13746     *  {@link android.view.DragEvent#ACTION_DRAG_STARTED}.
13747     * </p>
13748     * <p>
13749     * Your application can invoke startDrag() on any attached View object. The View object does not
13750     * need to be the one used in {@link android.view.View.DragShadowBuilder}, nor does it need to
13751     * be related to the View the user selected for dragging.
13752     * </p>
13753     * @param data A {@link android.content.ClipData} object pointing to the data to be
13754     * transferred by the drag and drop operation.
13755     * @param shadowBuilder A {@link android.view.View.DragShadowBuilder} object for building the
13756     * drag shadow.
13757     * @param myLocalState An {@link java.lang.Object} containing local data about the drag and
13758     * drop operation. This Object is put into every DragEvent object sent by the system during the
13759     * current drag.
13760     * <p>
13761     * myLocalState is a lightweight mechanism for the sending information from the dragged View
13762     * to the target Views. For example, it can contain flags that differentiate between a
13763     * a copy operation and a move operation.
13764     * </p>
13765     * @param flags Flags that control the drag and drop operation. No flags are currently defined,
13766     * so the parameter should be set to 0.
13767     * @return {@code true} if the method completes successfully, or
13768     * {@code false} if it fails anywhere. Returning {@code false} means the system was unable to
13769     * do a drag, and so no drag operation is in progress.
13770     */
13771    public final boolean startDrag(ClipData data, DragShadowBuilder shadowBuilder,
13772            Object myLocalState, int flags) {
13773        if (ViewDebug.DEBUG_DRAG) {
13774            Log.d(VIEW_LOG_TAG, "startDrag: data=" + data + " flags=" + flags);
13775        }
13776        boolean okay = false;
13777
13778        Point shadowSize = new Point();
13779        Point shadowTouchPoint = new Point();
13780        shadowBuilder.onProvideShadowMetrics(shadowSize, shadowTouchPoint);
13781
13782        if ((shadowSize.x < 0) || (shadowSize.y < 0) ||
13783                (shadowTouchPoint.x < 0) || (shadowTouchPoint.y < 0)) {
13784            throw new IllegalStateException("Drag shadow dimensions must not be negative");
13785        }
13786
13787        if (ViewDebug.DEBUG_DRAG) {
13788            Log.d(VIEW_LOG_TAG, "drag shadow: width=" + shadowSize.x + " height=" + shadowSize.y
13789                    + " shadowX=" + shadowTouchPoint.x + " shadowY=" + shadowTouchPoint.y);
13790        }
13791        Surface surface = new Surface();
13792        try {
13793            IBinder token = mAttachInfo.mSession.prepareDrag(mAttachInfo.mWindow,
13794                    flags, shadowSize.x, shadowSize.y, surface);
13795            if (ViewDebug.DEBUG_DRAG) Log.d(VIEW_LOG_TAG, "prepareDrag returned token=" + token
13796                    + " surface=" + surface);
13797            if (token != null) {
13798                Canvas canvas = surface.lockCanvas(null);
13799                try {
13800                    canvas.drawColor(0, PorterDuff.Mode.CLEAR);
13801                    shadowBuilder.onDrawShadow(canvas);
13802                } finally {
13803                    surface.unlockCanvasAndPost(canvas);
13804                }
13805
13806                final ViewRootImpl root = getViewRootImpl();
13807
13808                // Cache the local state object for delivery with DragEvents
13809                root.setLocalDragState(myLocalState);
13810
13811                // repurpose 'shadowSize' for the last touch point
13812                root.getLastTouchPoint(shadowSize);
13813
13814                okay = mAttachInfo.mSession.performDrag(mAttachInfo.mWindow, token,
13815                        shadowSize.x, shadowSize.y,
13816                        shadowTouchPoint.x, shadowTouchPoint.y, data);
13817                if (ViewDebug.DEBUG_DRAG) Log.d(VIEW_LOG_TAG, "performDrag returned " + okay);
13818
13819                // Off and running!  Release our local surface instance; the drag
13820                // shadow surface is now managed by the system process.
13821                surface.release();
13822            }
13823        } catch (Exception e) {
13824            Log.e(VIEW_LOG_TAG, "Unable to initiate drag", e);
13825            surface.destroy();
13826        }
13827
13828        return okay;
13829    }
13830
13831    /**
13832     * Handles drag events sent by the system following a call to
13833     * {@link android.view.View#startDrag(ClipData,DragShadowBuilder,Object,int) startDrag()}.
13834     *<p>
13835     * When the system calls this method, it passes a
13836     * {@link android.view.DragEvent} object. A call to
13837     * {@link android.view.DragEvent#getAction()} returns one of the action type constants defined
13838     * in DragEvent. The method uses these to determine what is happening in the drag and drop
13839     * operation.
13840     * @param event The {@link android.view.DragEvent} sent by the system.
13841     * The {@link android.view.DragEvent#getAction()} method returns an action type constant defined
13842     * in DragEvent, indicating the type of drag event represented by this object.
13843     * @return {@code true} if the method was successful, otherwise {@code false}.
13844     * <p>
13845     *  The method should return {@code true} in response to an action type of
13846     *  {@link android.view.DragEvent#ACTION_DRAG_STARTED} to receive drag events for the current
13847     *  operation.
13848     * </p>
13849     * <p>
13850     *  The method should also return {@code true} in response to an action type of
13851     *  {@link android.view.DragEvent#ACTION_DROP} if it consumed the drop, or
13852     *  {@code false} if it didn't.
13853     * </p>
13854     */
13855    public boolean onDragEvent(DragEvent event) {
13856        return false;
13857    }
13858
13859    /**
13860     * Detects if this View is enabled and has a drag event listener.
13861     * If both are true, then it calls the drag event listener with the
13862     * {@link android.view.DragEvent} it received. If the drag event listener returns
13863     * {@code true}, then dispatchDragEvent() returns {@code true}.
13864     * <p>
13865     * For all other cases, the method calls the
13866     * {@link android.view.View#onDragEvent(DragEvent) onDragEvent()} drag event handler
13867     * method and returns its result.
13868     * </p>
13869     * <p>
13870     * This ensures that a drag event is always consumed, even if the View does not have a drag
13871     * event listener. However, if the View has a listener and the listener returns true, then
13872     * onDragEvent() is not called.
13873     * </p>
13874     */
13875    public boolean dispatchDragEvent(DragEvent event) {
13876        //noinspection SimplifiableIfStatement
13877        ListenerInfo li = mListenerInfo;
13878        if (li != null && li.mOnDragListener != null && (mViewFlags & ENABLED_MASK) == ENABLED
13879                && li.mOnDragListener.onDrag(this, event)) {
13880            return true;
13881        }
13882        return onDragEvent(event);
13883    }
13884
13885    boolean canAcceptDrag() {
13886        return (mPrivateFlags2 & DRAG_CAN_ACCEPT) != 0;
13887    }
13888
13889    /**
13890     * This needs to be a better API (NOT ON VIEW) before it is exposed.  If
13891     * it is ever exposed at all.
13892     * @hide
13893     */
13894    public void onCloseSystemDialogs(String reason) {
13895    }
13896
13897    /**
13898     * Given a Drawable whose bounds have been set to draw into this view,
13899     * update a Region being computed for
13900     * {@link #gatherTransparentRegion(android.graphics.Region)} so
13901     * that any non-transparent parts of the Drawable are removed from the
13902     * given transparent region.
13903     *
13904     * @param dr The Drawable whose transparency is to be applied to the region.
13905     * @param region A Region holding the current transparency information,
13906     * where any parts of the region that are set are considered to be
13907     * transparent.  On return, this region will be modified to have the
13908     * transparency information reduced by the corresponding parts of the
13909     * Drawable that are not transparent.
13910     * {@hide}
13911     */
13912    public void applyDrawableToTransparentRegion(Drawable dr, Region region) {
13913        if (DBG) {
13914            Log.i("View", "Getting transparent region for: " + this);
13915        }
13916        final Region r = dr.getTransparentRegion();
13917        final Rect db = dr.getBounds();
13918        final AttachInfo attachInfo = mAttachInfo;
13919        if (r != null && attachInfo != null) {
13920            final int w = getRight()-getLeft();
13921            final int h = getBottom()-getTop();
13922            if (db.left > 0) {
13923                //Log.i("VIEW", "Drawable left " + db.left + " > view 0");
13924                r.op(0, 0, db.left, h, Region.Op.UNION);
13925            }
13926            if (db.right < w) {
13927                //Log.i("VIEW", "Drawable right " + db.right + " < view " + w);
13928                r.op(db.right, 0, w, h, Region.Op.UNION);
13929            }
13930            if (db.top > 0) {
13931                //Log.i("VIEW", "Drawable top " + db.top + " > view 0");
13932                r.op(0, 0, w, db.top, Region.Op.UNION);
13933            }
13934            if (db.bottom < h) {
13935                //Log.i("VIEW", "Drawable bottom " + db.bottom + " < view " + h);
13936                r.op(0, db.bottom, w, h, Region.Op.UNION);
13937            }
13938            final int[] location = attachInfo.mTransparentLocation;
13939            getLocationInWindow(location);
13940            r.translate(location[0], location[1]);
13941            region.op(r, Region.Op.INTERSECT);
13942        } else {
13943            region.op(db, Region.Op.DIFFERENCE);
13944        }
13945    }
13946
13947    private void checkForLongClick(int delayOffset) {
13948        if ((mViewFlags & LONG_CLICKABLE) == LONG_CLICKABLE) {
13949            mHasPerformedLongPress = false;
13950
13951            if (mPendingCheckForLongPress == null) {
13952                mPendingCheckForLongPress = new CheckForLongPress();
13953            }
13954            mPendingCheckForLongPress.rememberWindowAttachCount();
13955            postDelayed(mPendingCheckForLongPress,
13956                    ViewConfiguration.getLongPressTimeout() - delayOffset);
13957        }
13958    }
13959
13960    /**
13961     * Inflate a view from an XML resource.  This convenience method wraps the {@link
13962     * LayoutInflater} class, which provides a full range of options for view inflation.
13963     *
13964     * @param context The Context object for your activity or application.
13965     * @param resource The resource ID to inflate
13966     * @param root A view group that will be the parent.  Used to properly inflate the
13967     * layout_* parameters.
13968     * @see LayoutInflater
13969     */
13970    public static View inflate(Context context, int resource, ViewGroup root) {
13971        LayoutInflater factory = LayoutInflater.from(context);
13972        return factory.inflate(resource, root);
13973    }
13974
13975    /**
13976     * Scroll the view with standard behavior for scrolling beyond the normal
13977     * content boundaries. Views that call this method should override
13978     * {@link #onOverScrolled(int, int, boolean, boolean)} to respond to the
13979     * results of an over-scroll operation.
13980     *
13981     * Views can use this method to handle any touch or fling-based scrolling.
13982     *
13983     * @param deltaX Change in X in pixels
13984     * @param deltaY Change in Y in pixels
13985     * @param scrollX Current X scroll value in pixels before applying deltaX
13986     * @param scrollY Current Y scroll value in pixels before applying deltaY
13987     * @param scrollRangeX Maximum content scroll range along the X axis
13988     * @param scrollRangeY Maximum content scroll range along the Y axis
13989     * @param maxOverScrollX Number of pixels to overscroll by in either direction
13990     *          along the X axis.
13991     * @param maxOverScrollY Number of pixels to overscroll by in either direction
13992     *          along the Y axis.
13993     * @param isTouchEvent true if this scroll operation is the result of a touch event.
13994     * @return true if scrolling was clamped to an over-scroll boundary along either
13995     *          axis, false otherwise.
13996     */
13997    @SuppressWarnings({"UnusedParameters"})
13998    protected boolean overScrollBy(int deltaX, int deltaY,
13999            int scrollX, int scrollY,
14000            int scrollRangeX, int scrollRangeY,
14001            int maxOverScrollX, int maxOverScrollY,
14002            boolean isTouchEvent) {
14003        final int overScrollMode = mOverScrollMode;
14004        final boolean canScrollHorizontal =
14005                computeHorizontalScrollRange() > computeHorizontalScrollExtent();
14006        final boolean canScrollVertical =
14007                computeVerticalScrollRange() > computeVerticalScrollExtent();
14008        final boolean overScrollHorizontal = overScrollMode == OVER_SCROLL_ALWAYS ||
14009                (overScrollMode == OVER_SCROLL_IF_CONTENT_SCROLLS && canScrollHorizontal);
14010        final boolean overScrollVertical = overScrollMode == OVER_SCROLL_ALWAYS ||
14011                (overScrollMode == OVER_SCROLL_IF_CONTENT_SCROLLS && canScrollVertical);
14012
14013        int newScrollX = scrollX + deltaX;
14014        if (!overScrollHorizontal) {
14015            maxOverScrollX = 0;
14016        }
14017
14018        int newScrollY = scrollY + deltaY;
14019        if (!overScrollVertical) {
14020            maxOverScrollY = 0;
14021        }
14022
14023        // Clamp values if at the limits and record
14024        final int left = -maxOverScrollX;
14025        final int right = maxOverScrollX + scrollRangeX;
14026        final int top = -maxOverScrollY;
14027        final int bottom = maxOverScrollY + scrollRangeY;
14028
14029        boolean clampedX = false;
14030        if (newScrollX > right) {
14031            newScrollX = right;
14032            clampedX = true;
14033        } else if (newScrollX < left) {
14034            newScrollX = left;
14035            clampedX = true;
14036        }
14037
14038        boolean clampedY = false;
14039        if (newScrollY > bottom) {
14040            newScrollY = bottom;
14041            clampedY = true;
14042        } else if (newScrollY < top) {
14043            newScrollY = top;
14044            clampedY = true;
14045        }
14046
14047        onOverScrolled(newScrollX, newScrollY, clampedX, clampedY);
14048
14049        return clampedX || clampedY;
14050    }
14051
14052    /**
14053     * Called by {@link #overScrollBy(int, int, int, int, int, int, int, int, boolean)} to
14054     * respond to the results of an over-scroll operation.
14055     *
14056     * @param scrollX New X scroll value in pixels
14057     * @param scrollY New Y scroll value in pixels
14058     * @param clampedX True if scrollX was clamped to an over-scroll boundary
14059     * @param clampedY True if scrollY was clamped to an over-scroll boundary
14060     */
14061    protected void onOverScrolled(int scrollX, int scrollY,
14062            boolean clampedX, boolean clampedY) {
14063        // Intentionally empty.
14064    }
14065
14066    /**
14067     * Returns the over-scroll mode for this view. The result will be
14068     * one of {@link #OVER_SCROLL_ALWAYS} (default), {@link #OVER_SCROLL_IF_CONTENT_SCROLLS}
14069     * (allow over-scrolling only if the view content is larger than the container),
14070     * or {@link #OVER_SCROLL_NEVER}.
14071     *
14072     * @return This view's over-scroll mode.
14073     */
14074    public int getOverScrollMode() {
14075        return mOverScrollMode;
14076    }
14077
14078    /**
14079     * Set the over-scroll mode for this view. Valid over-scroll modes are
14080     * {@link #OVER_SCROLL_ALWAYS} (default), {@link #OVER_SCROLL_IF_CONTENT_SCROLLS}
14081     * (allow over-scrolling only if the view content is larger than the container),
14082     * or {@link #OVER_SCROLL_NEVER}.
14083     *
14084     * Setting the over-scroll mode of a view will have an effect only if the
14085     * view is capable of scrolling.
14086     *
14087     * @param overScrollMode The new over-scroll mode for this view.
14088     */
14089    public void setOverScrollMode(int overScrollMode) {
14090        if (overScrollMode != OVER_SCROLL_ALWAYS &&
14091                overScrollMode != OVER_SCROLL_IF_CONTENT_SCROLLS &&
14092                overScrollMode != OVER_SCROLL_NEVER) {
14093            throw new IllegalArgumentException("Invalid overscroll mode " + overScrollMode);
14094        }
14095        mOverScrollMode = overScrollMode;
14096    }
14097
14098    /**
14099     * Gets a scale factor that determines the distance the view should scroll
14100     * vertically in response to {@link MotionEvent#ACTION_SCROLL}.
14101     * @return The vertical scroll scale factor.
14102     * @hide
14103     */
14104    protected float getVerticalScrollFactor() {
14105        if (mVerticalScrollFactor == 0) {
14106            TypedValue outValue = new TypedValue();
14107            if (!mContext.getTheme().resolveAttribute(
14108                    com.android.internal.R.attr.listPreferredItemHeight, outValue, true)) {
14109                throw new IllegalStateException(
14110                        "Expected theme to define listPreferredItemHeight.");
14111            }
14112            mVerticalScrollFactor = outValue.getDimension(
14113                    mContext.getResources().getDisplayMetrics());
14114        }
14115        return mVerticalScrollFactor;
14116    }
14117
14118    /**
14119     * Gets a scale factor that determines the distance the view should scroll
14120     * horizontally in response to {@link MotionEvent#ACTION_SCROLL}.
14121     * @return The horizontal scroll scale factor.
14122     * @hide
14123     */
14124    protected float getHorizontalScrollFactor() {
14125        // TODO: Should use something else.
14126        return getVerticalScrollFactor();
14127    }
14128
14129    /**
14130     * Return the value specifying the text direction or policy that was set with
14131     * {@link #setTextDirection(int)}.
14132     *
14133     * @return the defined text direction. It can be one of:
14134     *
14135     * {@link #TEXT_DIRECTION_INHERIT},
14136     * {@link #TEXT_DIRECTION_FIRST_STRONG}
14137     * {@link #TEXT_DIRECTION_ANY_RTL},
14138     * {@link #TEXT_DIRECTION_LTR},
14139     * {@link #TEXT_DIRECTION_RTL},
14140     * {@link #TEXT_DIRECTION_LOCALE},
14141     */
14142    public int getTextDirection() {
14143        return mTextDirection;
14144    }
14145
14146    /**
14147     * Set the text direction.
14148     *
14149     * @param textDirection the direction to set. Should be one of:
14150     *
14151     * {@link #TEXT_DIRECTION_INHERIT},
14152     * {@link #TEXT_DIRECTION_FIRST_STRONG}
14153     * {@link #TEXT_DIRECTION_ANY_RTL},
14154     * {@link #TEXT_DIRECTION_LTR},
14155     * {@link #TEXT_DIRECTION_RTL},
14156     * {@link #TEXT_DIRECTION_LOCALE},
14157     */
14158    public void setTextDirection(int textDirection) {
14159        if (textDirection != mTextDirection) {
14160            mTextDirection = textDirection;
14161            resetResolvedTextDirection();
14162            requestLayout();
14163        }
14164    }
14165
14166    /**
14167     * Return the resolved text direction.
14168     *
14169     * @return the resolved text direction. Return one of:
14170     *
14171     * {@link #TEXT_DIRECTION_FIRST_STRONG}
14172     * {@link #TEXT_DIRECTION_ANY_RTL},
14173     * {@link #TEXT_DIRECTION_LTR},
14174     * {@link #TEXT_DIRECTION_RTL},
14175     * {@link #TEXT_DIRECTION_LOCALE},
14176     */
14177    public int getResolvedTextDirection() {
14178        if (mResolvedTextDirection == TEXT_DIRECTION_INHERIT) {
14179            resolveTextDirection();
14180        }
14181        return mResolvedTextDirection;
14182    }
14183
14184    /**
14185     * Resolve the text direction. Will call {@link View#onResolvedTextDirectionChanged} when
14186     * resolution is done.
14187     */
14188    public void resolveTextDirection() {
14189        if (mResolvedTextDirection != TEXT_DIRECTION_INHERIT) {
14190            // Resolution has already been done.
14191            return;
14192        }
14193        if (mTextDirection != TEXT_DIRECTION_INHERIT) {
14194            mResolvedTextDirection = mTextDirection;
14195        } else if (mParent != null && mParent instanceof ViewGroup) {
14196            mResolvedTextDirection = ((ViewGroup) mParent).getResolvedTextDirection();
14197        } else {
14198            mResolvedTextDirection = TEXT_DIRECTION_FIRST_STRONG;
14199        }
14200        onResolvedTextDirectionChanged();
14201    }
14202
14203    /**
14204     * Called when text direction has been resolved. Subclasses that care about text direction
14205     * resolution should override this method.
14206     *
14207     * The default implementation does nothing.
14208     */
14209    public void onResolvedTextDirectionChanged() {
14210    }
14211
14212    /**
14213     * Reset resolved text direction. Text direction can be resolved with a call to
14214     * getResolvedTextDirection(). Will call {@link View#onResolvedTextDirectionReset} when
14215     * reset is done.
14216     */
14217    public void resetResolvedTextDirection() {
14218        mResolvedTextDirection = TEXT_DIRECTION_INHERIT;
14219        onResolvedTextDirectionReset();
14220    }
14221
14222    /**
14223     * Called when text direction is reset. Subclasses that care about text direction reset should
14224     * override this method and do a reset of the text direction of their children. The default
14225     * implementation does nothing.
14226     */
14227    public void onResolvedTextDirectionReset() {
14228    }
14229
14230    //
14231    // Properties
14232    //
14233    /**
14234     * A Property wrapper around the <code>alpha</code> functionality handled by the
14235     * {@link View#setAlpha(float)} and {@link View#getAlpha()} methods.
14236     */
14237    public static final Property<View, Float> ALPHA = new FloatProperty<View>("alpha") {
14238        @Override
14239        public void setValue(View object, float value) {
14240            object.setAlpha(value);
14241        }
14242
14243        @Override
14244        public Float get(View object) {
14245            return object.getAlpha();
14246        }
14247    };
14248
14249    /**
14250     * A Property wrapper around the <code>translationX</code> functionality handled by the
14251     * {@link View#setTranslationX(float)} and {@link View#getTranslationX()} methods.
14252     */
14253    public static final Property<View, Float> TRANSLATION_X = new FloatProperty<View>("translationX") {
14254        @Override
14255        public void setValue(View object, float value) {
14256            object.setTranslationX(value);
14257        }
14258
14259                @Override
14260        public Float get(View object) {
14261            return object.getTranslationX();
14262        }
14263    };
14264
14265    /**
14266     * A Property wrapper around the <code>translationY</code> functionality handled by the
14267     * {@link View#setTranslationY(float)} and {@link View#getTranslationY()} methods.
14268     */
14269    public static final Property<View, Float> TRANSLATION_Y = new FloatProperty<View>("translationY") {
14270        @Override
14271        public void setValue(View object, float value) {
14272            object.setTranslationY(value);
14273        }
14274
14275        @Override
14276        public Float get(View object) {
14277            return object.getTranslationY();
14278        }
14279    };
14280
14281    /**
14282     * A Property wrapper around the <code>x</code> functionality handled by the
14283     * {@link View#setX(float)} and {@link View#getX()} methods.
14284     */
14285    public static final Property<View, Float> X = new FloatProperty<View>("x") {
14286        @Override
14287        public void setValue(View object, float value) {
14288            object.setX(value);
14289        }
14290
14291        @Override
14292        public Float get(View object) {
14293            return object.getX();
14294        }
14295    };
14296
14297    /**
14298     * A Property wrapper around the <code>y</code> functionality handled by the
14299     * {@link View#setY(float)} and {@link View#getY()} methods.
14300     */
14301    public static final Property<View, Float> Y = new FloatProperty<View>("y") {
14302        @Override
14303        public void setValue(View object, float value) {
14304            object.setY(value);
14305        }
14306
14307        @Override
14308        public Float get(View object) {
14309            return object.getY();
14310        }
14311    };
14312
14313    /**
14314     * A Property wrapper around the <code>rotation</code> functionality handled by the
14315     * {@link View#setRotation(float)} and {@link View#getRotation()} methods.
14316     */
14317    public static final Property<View, Float> ROTATION = new FloatProperty<View>("rotation") {
14318        @Override
14319        public void setValue(View object, float value) {
14320            object.setRotation(value);
14321        }
14322
14323        @Override
14324        public Float get(View object) {
14325            return object.getRotation();
14326        }
14327    };
14328
14329    /**
14330     * A Property wrapper around the <code>rotationX</code> functionality handled by the
14331     * {@link View#setRotationX(float)} and {@link View#getRotationX()} methods.
14332     */
14333    public static final Property<View, Float> ROTATION_X = new FloatProperty<View>("rotationX") {
14334        @Override
14335        public void setValue(View object, float value) {
14336            object.setRotationX(value);
14337        }
14338
14339        @Override
14340        public Float get(View object) {
14341            return object.getRotationX();
14342        }
14343    };
14344
14345    /**
14346     * A Property wrapper around the <code>rotationY</code> functionality handled by the
14347     * {@link View#setRotationY(float)} and {@link View#getRotationY()} methods.
14348     */
14349    public static final Property<View, Float> ROTATION_Y = new FloatProperty<View>("rotationY") {
14350        @Override
14351        public void setValue(View object, float value) {
14352            object.setRotationY(value);
14353        }
14354
14355        @Override
14356        public Float get(View object) {
14357            return object.getRotationY();
14358        }
14359    };
14360
14361    /**
14362     * A Property wrapper around the <code>scaleX</code> functionality handled by the
14363     * {@link View#setScaleX(float)} and {@link View#getScaleX()} methods.
14364     */
14365    public static final Property<View, Float> SCALE_X = new FloatProperty<View>("scaleX") {
14366        @Override
14367        public void setValue(View object, float value) {
14368            object.setScaleX(value);
14369        }
14370
14371        @Override
14372        public Float get(View object) {
14373            return object.getScaleX();
14374        }
14375    };
14376
14377    /**
14378     * A Property wrapper around the <code>scaleY</code> functionality handled by the
14379     * {@link View#setScaleY(float)} and {@link View#getScaleY()} methods.
14380     */
14381    public static final Property<View, Float> SCALE_Y = new FloatProperty<View>("scaleY") {
14382        @Override
14383        public void setValue(View object, float value) {
14384            object.setScaleY(value);
14385        }
14386
14387        @Override
14388        public Float get(View object) {
14389            return object.getScaleY();
14390        }
14391    };
14392
14393    /**
14394     * A MeasureSpec encapsulates the layout requirements passed from parent to child.
14395     * Each MeasureSpec represents a requirement for either the width or the height.
14396     * A MeasureSpec is comprised of a size and a mode. There are three possible
14397     * modes:
14398     * <dl>
14399     * <dt>UNSPECIFIED</dt>
14400     * <dd>
14401     * The parent has not imposed any constraint on the child. It can be whatever size
14402     * it wants.
14403     * </dd>
14404     *
14405     * <dt>EXACTLY</dt>
14406     * <dd>
14407     * The parent has determined an exact size for the child. The child is going to be
14408     * given those bounds regardless of how big it wants to be.
14409     * </dd>
14410     *
14411     * <dt>AT_MOST</dt>
14412     * <dd>
14413     * The child can be as large as it wants up to the specified size.
14414     * </dd>
14415     * </dl>
14416     *
14417     * MeasureSpecs are implemented as ints to reduce object allocation. This class
14418     * is provided to pack and unpack the &lt;size, mode&gt; tuple into the int.
14419     */
14420    public static class MeasureSpec {
14421        private static final int MODE_SHIFT = 30;
14422        private static final int MODE_MASK  = 0x3 << MODE_SHIFT;
14423
14424        /**
14425         * Measure specification mode: The parent has not imposed any constraint
14426         * on the child. It can be whatever size it wants.
14427         */
14428        public static final int UNSPECIFIED = 0 << MODE_SHIFT;
14429
14430        /**
14431         * Measure specification mode: The parent has determined an exact size
14432         * for the child. The child is going to be given those bounds regardless
14433         * of how big it wants to be.
14434         */
14435        public static final int EXACTLY     = 1 << MODE_SHIFT;
14436
14437        /**
14438         * Measure specification mode: The child can be as large as it wants up
14439         * to the specified size.
14440         */
14441        public static final int AT_MOST     = 2 << MODE_SHIFT;
14442
14443        /**
14444         * Creates a measure specification based on the supplied size and mode.
14445         *
14446         * The mode must always be one of the following:
14447         * <ul>
14448         *  <li>{@link android.view.View.MeasureSpec#UNSPECIFIED}</li>
14449         *  <li>{@link android.view.View.MeasureSpec#EXACTLY}</li>
14450         *  <li>{@link android.view.View.MeasureSpec#AT_MOST}</li>
14451         * </ul>
14452         *
14453         * @param size the size of the measure specification
14454         * @param mode the mode of the measure specification
14455         * @return the measure specification based on size and mode
14456         */
14457        public static int makeMeasureSpec(int size, int mode) {
14458            return size + mode;
14459        }
14460
14461        /**
14462         * Extracts the mode from the supplied measure specification.
14463         *
14464         * @param measureSpec the measure specification to extract the mode from
14465         * @return {@link android.view.View.MeasureSpec#UNSPECIFIED},
14466         *         {@link android.view.View.MeasureSpec#AT_MOST} or
14467         *         {@link android.view.View.MeasureSpec#EXACTLY}
14468         */
14469        public static int getMode(int measureSpec) {
14470            return (measureSpec & MODE_MASK);
14471        }
14472
14473        /**
14474         * Extracts the size from the supplied measure specification.
14475         *
14476         * @param measureSpec the measure specification to extract the size from
14477         * @return the size in pixels defined in the supplied measure specification
14478         */
14479        public static int getSize(int measureSpec) {
14480            return (measureSpec & ~MODE_MASK);
14481        }
14482
14483        /**
14484         * Returns a String representation of the specified measure
14485         * specification.
14486         *
14487         * @param measureSpec the measure specification to convert to a String
14488         * @return a String with the following format: "MeasureSpec: MODE SIZE"
14489         */
14490        public static String toString(int measureSpec) {
14491            int mode = getMode(measureSpec);
14492            int size = getSize(measureSpec);
14493
14494            StringBuilder sb = new StringBuilder("MeasureSpec: ");
14495
14496            if (mode == UNSPECIFIED)
14497                sb.append("UNSPECIFIED ");
14498            else if (mode == EXACTLY)
14499                sb.append("EXACTLY ");
14500            else if (mode == AT_MOST)
14501                sb.append("AT_MOST ");
14502            else
14503                sb.append(mode).append(" ");
14504
14505            sb.append(size);
14506            return sb.toString();
14507        }
14508    }
14509
14510    class CheckForLongPress implements Runnable {
14511
14512        private int mOriginalWindowAttachCount;
14513
14514        public void run() {
14515            if (isPressed() && (mParent != null)
14516                    && mOriginalWindowAttachCount == mWindowAttachCount) {
14517                if (performLongClick()) {
14518                    mHasPerformedLongPress = true;
14519                }
14520            }
14521        }
14522
14523        public void rememberWindowAttachCount() {
14524            mOriginalWindowAttachCount = mWindowAttachCount;
14525        }
14526    }
14527
14528    private final class CheckForTap implements Runnable {
14529        public void run() {
14530            mPrivateFlags &= ~PREPRESSED;
14531            setPressed(true);
14532            checkForLongClick(ViewConfiguration.getTapTimeout());
14533        }
14534    }
14535
14536    private final class PerformClick implements Runnable {
14537        public void run() {
14538            performClick();
14539        }
14540    }
14541
14542    /** @hide */
14543    public void hackTurnOffWindowResizeAnim(boolean off) {
14544        mAttachInfo.mTurnOffWindowResizeAnim = off;
14545    }
14546
14547    /**
14548     * This method returns a ViewPropertyAnimator object, which can be used to animate
14549     * specific properties on this View.
14550     *
14551     * @return ViewPropertyAnimator The ViewPropertyAnimator associated with this View.
14552     */
14553    public ViewPropertyAnimator animate() {
14554        if (mAnimator == null) {
14555            mAnimator = new ViewPropertyAnimator(this);
14556        }
14557        return mAnimator;
14558    }
14559
14560    /**
14561     * Interface definition for a callback to be invoked when a key event is
14562     * dispatched to this view. The callback will be invoked before the key
14563     * event is given to the view.
14564     */
14565    public interface OnKeyListener {
14566        /**
14567         * Called when a key is dispatched to a view. This allows listeners to
14568         * get a chance to respond before the target view.
14569         *
14570         * @param v The view the key has been dispatched to.
14571         * @param keyCode The code for the physical key that was pressed
14572         * @param event The KeyEvent object containing full information about
14573         *        the event.
14574         * @return True if the listener has consumed the event, false otherwise.
14575         */
14576        boolean onKey(View v, int keyCode, KeyEvent event);
14577    }
14578
14579    /**
14580     * Interface definition for a callback to be invoked when a touch event is
14581     * dispatched to this view. The callback will be invoked before the touch
14582     * event is given to the view.
14583     */
14584    public interface OnTouchListener {
14585        /**
14586         * Called when a touch event is dispatched to a view. This allows listeners to
14587         * get a chance to respond before the target view.
14588         *
14589         * @param v The view the touch event has been dispatched to.
14590         * @param event The MotionEvent object containing full information about
14591         *        the event.
14592         * @return True if the listener has consumed the event, false otherwise.
14593         */
14594        boolean onTouch(View v, MotionEvent event);
14595    }
14596
14597    /**
14598     * Interface definition for a callback to be invoked when a hover event is
14599     * dispatched to this view. The callback will be invoked before the hover
14600     * event is given to the view.
14601     */
14602    public interface OnHoverListener {
14603        /**
14604         * Called when a hover event is dispatched to a view. This allows listeners to
14605         * get a chance to respond before the target view.
14606         *
14607         * @param v The view the hover event has been dispatched to.
14608         * @param event The MotionEvent object containing full information about
14609         *        the event.
14610         * @return True if the listener has consumed the event, false otherwise.
14611         */
14612        boolean onHover(View v, MotionEvent event);
14613    }
14614
14615    /**
14616     * Interface definition for a callback to be invoked when a generic motion event is
14617     * dispatched to this view. The callback will be invoked before the generic motion
14618     * event is given to the view.
14619     */
14620    public interface OnGenericMotionListener {
14621        /**
14622         * Called when a generic motion event is dispatched to a view. This allows listeners to
14623         * get a chance to respond before the target view.
14624         *
14625         * @param v The view the generic motion event has been dispatched to.
14626         * @param event The MotionEvent object containing full information about
14627         *        the event.
14628         * @return True if the listener has consumed the event, false otherwise.
14629         */
14630        boolean onGenericMotion(View v, MotionEvent event);
14631    }
14632
14633    /**
14634     * Interface definition for a callback to be invoked when a view has been clicked and held.
14635     */
14636    public interface OnLongClickListener {
14637        /**
14638         * Called when a view has been clicked and held.
14639         *
14640         * @param v The view that was clicked and held.
14641         *
14642         * @return true if the callback consumed the long click, false otherwise.
14643         */
14644        boolean onLongClick(View v);
14645    }
14646
14647    /**
14648     * Interface definition for a callback to be invoked when a drag is being dispatched
14649     * to this view.  The callback will be invoked before the hosting view's own
14650     * onDrag(event) method.  If the listener wants to fall back to the hosting view's
14651     * onDrag(event) behavior, it should return 'false' from this callback.
14652     *
14653     * <div class="special reference">
14654     * <h3>Developer Guides</h3>
14655     * <p>For a guide to implementing drag and drop features, read the
14656     * <a href="{@docRoot}guide/topics/ui/drag-drop.html">Drag and Drop</a> developer guide.</p>
14657     * </div>
14658     */
14659    public interface OnDragListener {
14660        /**
14661         * Called when a drag event is dispatched to a view. This allows listeners
14662         * to get a chance to override base View behavior.
14663         *
14664         * @param v The View that received the drag event.
14665         * @param event The {@link android.view.DragEvent} object for the drag event.
14666         * @return {@code true} if the drag event was handled successfully, or {@code false}
14667         * if the drag event was not handled. Note that {@code false} will trigger the View
14668         * to call its {@link #onDragEvent(DragEvent) onDragEvent()} handler.
14669         */
14670        boolean onDrag(View v, DragEvent event);
14671    }
14672
14673    /**
14674     * Interface definition for a callback to be invoked when the focus state of
14675     * a view changed.
14676     */
14677    public interface OnFocusChangeListener {
14678        /**
14679         * Called when the focus state of a view has changed.
14680         *
14681         * @param v The view whose state has changed.
14682         * @param hasFocus The new focus state of v.
14683         */
14684        void onFocusChange(View v, boolean hasFocus);
14685    }
14686
14687    /**
14688     * Interface definition for a callback to be invoked when a view is clicked.
14689     */
14690    public interface OnClickListener {
14691        /**
14692         * Called when a view has been clicked.
14693         *
14694         * @param v The view that was clicked.
14695         */
14696        void onClick(View v);
14697    }
14698
14699    /**
14700     * Interface definition for a callback to be invoked when the context menu
14701     * for this view is being built.
14702     */
14703    public interface OnCreateContextMenuListener {
14704        /**
14705         * Called when the context menu for this view is being built. It is not
14706         * safe to hold onto the menu after this method returns.
14707         *
14708         * @param menu The context menu that is being built
14709         * @param v The view for which the context menu is being built
14710         * @param menuInfo Extra information about the item for which the
14711         *            context menu should be shown. This information will vary
14712         *            depending on the class of v.
14713         */
14714        void onCreateContextMenu(ContextMenu menu, View v, ContextMenuInfo menuInfo);
14715    }
14716
14717    /**
14718     * Interface definition for a callback to be invoked when the status bar changes
14719     * visibility.  This reports <strong>global</strong> changes to the system UI
14720     * state, not just what the application is requesting.
14721     *
14722     * @see View#setOnSystemUiVisibilityChangeListener(android.view.View.OnSystemUiVisibilityChangeListener)
14723     */
14724    public interface OnSystemUiVisibilityChangeListener {
14725        /**
14726         * Called when the status bar changes visibility because of a call to
14727         * {@link View#setSystemUiVisibility(int)}.
14728         *
14729         * @param visibility  Bitwise-or of flags {@link #SYSTEM_UI_FLAG_LOW_PROFILE} or
14730         * {@link #SYSTEM_UI_FLAG_HIDE_NAVIGATION}.  This tells you the
14731         * <strong>global</strong> state of the UI visibility flags, not what your
14732         * app is currently applying.
14733         */
14734        public void onSystemUiVisibilityChange(int visibility);
14735    }
14736
14737    /**
14738     * Interface definition for a callback to be invoked when this view is attached
14739     * or detached from its window.
14740     */
14741    public interface OnAttachStateChangeListener {
14742        /**
14743         * Called when the view is attached to a window.
14744         * @param v The view that was attached
14745         */
14746        public void onViewAttachedToWindow(View v);
14747        /**
14748         * Called when the view is detached from a window.
14749         * @param v The view that was detached
14750         */
14751        public void onViewDetachedFromWindow(View v);
14752    }
14753
14754    private final class UnsetPressedState implements Runnable {
14755        public void run() {
14756            setPressed(false);
14757        }
14758    }
14759
14760    /**
14761     * Base class for derived classes that want to save and restore their own
14762     * state in {@link android.view.View#onSaveInstanceState()}.
14763     */
14764    public static class BaseSavedState extends AbsSavedState {
14765        /**
14766         * Constructor used when reading from a parcel. Reads the state of the superclass.
14767         *
14768         * @param source
14769         */
14770        public BaseSavedState(Parcel source) {
14771            super(source);
14772        }
14773
14774        /**
14775         * Constructor called by derived classes when creating their SavedState objects
14776         *
14777         * @param superState The state of the superclass of this view
14778         */
14779        public BaseSavedState(Parcelable superState) {
14780            super(superState);
14781        }
14782
14783        public static final Parcelable.Creator<BaseSavedState> CREATOR =
14784                new Parcelable.Creator<BaseSavedState>() {
14785            public BaseSavedState createFromParcel(Parcel in) {
14786                return new BaseSavedState(in);
14787            }
14788
14789            public BaseSavedState[] newArray(int size) {
14790                return new BaseSavedState[size];
14791            }
14792        };
14793    }
14794
14795    /**
14796     * A set of information given to a view when it is attached to its parent
14797     * window.
14798     */
14799    static class AttachInfo {
14800        interface Callbacks {
14801            void playSoundEffect(int effectId);
14802            boolean performHapticFeedback(int effectId, boolean always);
14803        }
14804
14805        /**
14806         * InvalidateInfo is used to post invalidate(int, int, int, int) messages
14807         * to a Handler. This class contains the target (View) to invalidate and
14808         * the coordinates of the dirty rectangle.
14809         *
14810         * For performance purposes, this class also implements a pool of up to
14811         * POOL_LIMIT objects that get reused. This reduces memory allocations
14812         * whenever possible.
14813         */
14814        static class InvalidateInfo implements Poolable<InvalidateInfo> {
14815            private static final int POOL_LIMIT = 10;
14816            private static final Pool<InvalidateInfo> sPool = Pools.synchronizedPool(
14817                    Pools.finitePool(new PoolableManager<InvalidateInfo>() {
14818                        public InvalidateInfo newInstance() {
14819                            return new InvalidateInfo();
14820                        }
14821
14822                        public void onAcquired(InvalidateInfo element) {
14823                        }
14824
14825                        public void onReleased(InvalidateInfo element) {
14826                            element.target = null;
14827                        }
14828                    }, POOL_LIMIT)
14829            );
14830
14831            private InvalidateInfo mNext;
14832            private boolean mIsPooled;
14833
14834            View target;
14835
14836            int left;
14837            int top;
14838            int right;
14839            int bottom;
14840
14841            public void setNextPoolable(InvalidateInfo element) {
14842                mNext = element;
14843            }
14844
14845            public InvalidateInfo getNextPoolable() {
14846                return mNext;
14847            }
14848
14849            static InvalidateInfo acquire() {
14850                return sPool.acquire();
14851            }
14852
14853            void release() {
14854                sPool.release(this);
14855            }
14856
14857            public boolean isPooled() {
14858                return mIsPooled;
14859            }
14860
14861            public void setPooled(boolean isPooled) {
14862                mIsPooled = isPooled;
14863            }
14864        }
14865
14866        final IWindowSession mSession;
14867
14868        final IWindow mWindow;
14869
14870        final IBinder mWindowToken;
14871
14872        final Callbacks mRootCallbacks;
14873
14874        HardwareCanvas mHardwareCanvas;
14875
14876        /**
14877         * The top view of the hierarchy.
14878         */
14879        View mRootView;
14880
14881        IBinder mPanelParentWindowToken;
14882        Surface mSurface;
14883
14884        boolean mHardwareAccelerated;
14885        boolean mHardwareAccelerationRequested;
14886        HardwareRenderer mHardwareRenderer;
14887
14888        boolean mScreenOn;
14889
14890        /**
14891         * Scale factor used by the compatibility mode
14892         */
14893        float mApplicationScale;
14894
14895        /**
14896         * Indicates whether the application is in compatibility mode
14897         */
14898        boolean mScalingRequired;
14899
14900        /**
14901         * If set, ViewAncestor doesn't use its lame animation for when the window resizes.
14902         */
14903        boolean mTurnOffWindowResizeAnim;
14904
14905        /**
14906         * Left position of this view's window
14907         */
14908        int mWindowLeft;
14909
14910        /**
14911         * Top position of this view's window
14912         */
14913        int mWindowTop;
14914
14915        /**
14916         * Indicates whether views need to use 32-bit drawing caches
14917         */
14918        boolean mUse32BitDrawingCache;
14919
14920        /**
14921         * For windows that are full-screen but using insets to layout inside
14922         * of the screen decorations, these are the current insets for the
14923         * content of the window.
14924         */
14925        final Rect mContentInsets = new Rect();
14926
14927        /**
14928         * For windows that are full-screen but using insets to layout inside
14929         * of the screen decorations, these are the current insets for the
14930         * actual visible parts of the window.
14931         */
14932        final Rect mVisibleInsets = new Rect();
14933
14934        /**
14935         * The internal insets given by this window.  This value is
14936         * supplied by the client (through
14937         * {@link ViewTreeObserver.OnComputeInternalInsetsListener}) and will
14938         * be given to the window manager when changed to be used in laying
14939         * out windows behind it.
14940         */
14941        final ViewTreeObserver.InternalInsetsInfo mGivenInternalInsets
14942                = new ViewTreeObserver.InternalInsetsInfo();
14943
14944        /**
14945         * All views in the window's hierarchy that serve as scroll containers,
14946         * used to determine if the window can be resized or must be panned
14947         * to adjust for a soft input area.
14948         */
14949        final ArrayList<View> mScrollContainers = new ArrayList<View>();
14950
14951        final KeyEvent.DispatcherState mKeyDispatchState
14952                = new KeyEvent.DispatcherState();
14953
14954        /**
14955         * Indicates whether the view's window currently has the focus.
14956         */
14957        boolean mHasWindowFocus;
14958
14959        /**
14960         * The current visibility of the window.
14961         */
14962        int mWindowVisibility;
14963
14964        /**
14965         * Indicates the time at which drawing started to occur.
14966         */
14967        long mDrawingTime;
14968
14969        /**
14970         * Indicates whether or not ignoring the DIRTY_MASK flags.
14971         */
14972        boolean mIgnoreDirtyState;
14973
14974        /**
14975         * This flag tracks when the mIgnoreDirtyState flag is set during draw(),
14976         * to avoid clearing that flag prematurely.
14977         */
14978        boolean mSetIgnoreDirtyState = false;
14979
14980        /**
14981         * Indicates whether the view's window is currently in touch mode.
14982         */
14983        boolean mInTouchMode;
14984
14985        /**
14986         * Indicates that ViewAncestor should trigger a global layout change
14987         * the next time it performs a traversal
14988         */
14989        boolean mRecomputeGlobalAttributes;
14990
14991        /**
14992         * Always report new attributes at next traversal.
14993         */
14994        boolean mForceReportNewAttributes;
14995
14996        /**
14997         * Set during a traveral if any views want to keep the screen on.
14998         */
14999        boolean mKeepScreenOn;
15000
15001        /**
15002         * Bitwise-or of all of the values that views have passed to setSystemUiVisibility().
15003         */
15004        int mSystemUiVisibility;
15005
15006        /**
15007         * True if a view in this hierarchy has an OnSystemUiVisibilityChangeListener
15008         * attached.
15009         */
15010        boolean mHasSystemUiListeners;
15011
15012        /**
15013         * Set if the visibility of any views has changed.
15014         */
15015        boolean mViewVisibilityChanged;
15016
15017        /**
15018         * Set to true if a view has been scrolled.
15019         */
15020        boolean mViewScrollChanged;
15021
15022        /**
15023         * Global to the view hierarchy used as a temporary for dealing with
15024         * x/y points in the transparent region computations.
15025         */
15026        final int[] mTransparentLocation = new int[2];
15027
15028        /**
15029         * Global to the view hierarchy used as a temporary for dealing with
15030         * x/y points in the ViewGroup.invalidateChild implementation.
15031         */
15032        final int[] mInvalidateChildLocation = new int[2];
15033
15034
15035        /**
15036         * Global to the view hierarchy used as a temporary for dealing with
15037         * x/y location when view is transformed.
15038         */
15039        final float[] mTmpTransformLocation = new float[2];
15040
15041        /**
15042         * The view tree observer used to dispatch global events like
15043         * layout, pre-draw, touch mode change, etc.
15044         */
15045        final ViewTreeObserver mTreeObserver = new ViewTreeObserver();
15046
15047        /**
15048         * A Canvas used by the view hierarchy to perform bitmap caching.
15049         */
15050        Canvas mCanvas;
15051
15052        /**
15053         * The view root impl.
15054         */
15055        final ViewRootImpl mViewRootImpl;
15056
15057        /**
15058         * A Handler supplied by a view's {@link android.view.ViewRootImpl}. This
15059         * handler can be used to pump events in the UI events queue.
15060         */
15061        final Handler mHandler;
15062
15063        /**
15064         * Temporary for use in computing invalidate rectangles while
15065         * calling up the hierarchy.
15066         */
15067        final Rect mTmpInvalRect = new Rect();
15068
15069        /**
15070         * Temporary for use in computing hit areas with transformed views
15071         */
15072        final RectF mTmpTransformRect = new RectF();
15073
15074        /**
15075         * Temporary list for use in collecting focusable descendents of a view.
15076         */
15077        final ArrayList<View> mFocusablesTempList = new ArrayList<View>(24);
15078
15079        /**
15080         * The id of the window for accessibility purposes.
15081         */
15082        int mAccessibilityWindowId = View.NO_ID;
15083
15084        /**
15085         * Creates a new set of attachment information with the specified
15086         * events handler and thread.
15087         *
15088         * @param handler the events handler the view must use
15089         */
15090        AttachInfo(IWindowSession session, IWindow window,
15091                ViewRootImpl viewRootImpl, Handler handler, Callbacks effectPlayer) {
15092            mSession = session;
15093            mWindow = window;
15094            mWindowToken = window.asBinder();
15095            mViewRootImpl = viewRootImpl;
15096            mHandler = handler;
15097            mRootCallbacks = effectPlayer;
15098        }
15099    }
15100
15101    /**
15102     * <p>ScrollabilityCache holds various fields used by a View when scrolling
15103     * is supported. This avoids keeping too many unused fields in most
15104     * instances of View.</p>
15105     */
15106    private static class ScrollabilityCache implements Runnable {
15107
15108        /**
15109         * Scrollbars are not visible
15110         */
15111        public static final int OFF = 0;
15112
15113        /**
15114         * Scrollbars are visible
15115         */
15116        public static final int ON = 1;
15117
15118        /**
15119         * Scrollbars are fading away
15120         */
15121        public static final int FADING = 2;
15122
15123        public boolean fadeScrollBars;
15124
15125        public int fadingEdgeLength;
15126        public int scrollBarDefaultDelayBeforeFade;
15127        public int scrollBarFadeDuration;
15128
15129        public int scrollBarSize;
15130        public ScrollBarDrawable scrollBar;
15131        public float[] interpolatorValues;
15132        public View host;
15133
15134        public final Paint paint;
15135        public final Matrix matrix;
15136        public Shader shader;
15137
15138        public final Interpolator scrollBarInterpolator = new Interpolator(1, 2);
15139
15140        private static final float[] OPAQUE = { 255 };
15141        private static final float[] TRANSPARENT = { 0.0f };
15142
15143        /**
15144         * When fading should start. This time moves into the future every time
15145         * a new scroll happens. Measured based on SystemClock.uptimeMillis()
15146         */
15147        public long fadeStartTime;
15148
15149
15150        /**
15151         * The current state of the scrollbars: ON, OFF, or FADING
15152         */
15153        public int state = OFF;
15154
15155        private int mLastColor;
15156
15157        public ScrollabilityCache(ViewConfiguration configuration, View host) {
15158            fadingEdgeLength = configuration.getScaledFadingEdgeLength();
15159            scrollBarSize = configuration.getScaledScrollBarSize();
15160            scrollBarDefaultDelayBeforeFade = ViewConfiguration.getScrollDefaultDelay();
15161            scrollBarFadeDuration = ViewConfiguration.getScrollBarFadeDuration();
15162
15163            paint = new Paint();
15164            matrix = new Matrix();
15165            // use use a height of 1, and then wack the matrix each time we
15166            // actually use it.
15167            shader = new LinearGradient(0, 0, 0, 1, 0xFF000000, 0, Shader.TileMode.CLAMP);
15168
15169            paint.setShader(shader);
15170            paint.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.DST_OUT));
15171            this.host = host;
15172        }
15173
15174        public void setFadeColor(int color) {
15175            if (color != 0 && color != mLastColor) {
15176                mLastColor = color;
15177                color |= 0xFF000000;
15178
15179                shader = new LinearGradient(0, 0, 0, 1, color | 0xFF000000,
15180                        color & 0x00FFFFFF, Shader.TileMode.CLAMP);
15181
15182                paint.setShader(shader);
15183                // Restore the default transfer mode (src_over)
15184                paint.setXfermode(null);
15185            }
15186        }
15187
15188        public void run() {
15189            long now = AnimationUtils.currentAnimationTimeMillis();
15190            if (now >= fadeStartTime) {
15191
15192                // the animation fades the scrollbars out by changing
15193                // the opacity (alpha) from fully opaque to fully
15194                // transparent
15195                int nextFrame = (int) now;
15196                int framesCount = 0;
15197
15198                Interpolator interpolator = scrollBarInterpolator;
15199
15200                // Start opaque
15201                interpolator.setKeyFrame(framesCount++, nextFrame, OPAQUE);
15202
15203                // End transparent
15204                nextFrame += scrollBarFadeDuration;
15205                interpolator.setKeyFrame(framesCount, nextFrame, TRANSPARENT);
15206
15207                state = FADING;
15208
15209                // Kick off the fade animation
15210                host.invalidate(true);
15211            }
15212        }
15213    }
15214
15215    /**
15216     * Resuable callback for sending
15217     * {@link AccessibilityEvent#TYPE_VIEW_SCROLLED} accessibility event.
15218     */
15219    private class SendViewScrolledAccessibilityEvent implements Runnable {
15220        public volatile boolean mIsPending;
15221
15222        public void run() {
15223            sendAccessibilityEvent(AccessibilityEvent.TYPE_VIEW_SCROLLED);
15224            mIsPending = false;
15225        }
15226    }
15227
15228    /**
15229     * <p>
15230     * This class represents a delegate that can be registered in a {@link View}
15231     * to enhance accessibility support via composition rather via inheritance.
15232     * It is specifically targeted to widget developers that extend basic View
15233     * classes i.e. classes in package android.view, that would like their
15234     * applications to be backwards compatible.
15235     * </p>
15236     * <p>
15237     * A scenario in which a developer would like to use an accessibility delegate
15238     * is overriding a method introduced in a later API version then the minimal API
15239     * version supported by the application. For example, the method
15240     * {@link View#onInitializeAccessibilityNodeInfo(AccessibilityNodeInfo)} is not available
15241     * in API version 4 when the accessibility APIs were first introduced. If a
15242     * developer would like his application to run on API version 4 devices (assuming
15243     * all other APIs used by the application are version 4 or lower) and take advantage
15244     * of this method, instead of overriding the method which would break the application's
15245     * backwards compatibility, he can override the corresponding method in this
15246     * delegate and register the delegate in the target View if the API version of
15247     * the system is high enough i.e. the API version is same or higher to the API
15248     * version that introduced
15249     * {@link View#onInitializeAccessibilityNodeInfo(AccessibilityNodeInfo)}.
15250     * </p>
15251     * <p>
15252     * Here is an example implementation:
15253     * </p>
15254     * <code><pre><p>
15255     * if (Build.VERSION.SDK_INT >= 14) {
15256     *     // If the API version is equal of higher than the version in
15257     *     // which onInitializeAccessibilityNodeInfo was introduced we
15258     *     // register a delegate with a customized implementation.
15259     *     View view = findViewById(R.id.view_id);
15260     *     view.setAccessibilityDelegate(new AccessibilityDelegate() {
15261     *         public void onInitializeAccessibilityNodeInfo(View host,
15262     *                 AccessibilityNodeInfo info) {
15263     *             // Let the default implementation populate the info.
15264     *             super.onInitializeAccessibilityNodeInfo(host, info);
15265     *             // Set some other information.
15266     *             info.setEnabled(host.isEnabled());
15267     *         }
15268     *     });
15269     * }
15270     * </code></pre></p>
15271     * <p>
15272     * This delegate contains methods that correspond to the accessibility methods
15273     * in View. If a delegate has been specified the implementation in View hands
15274     * off handling to the corresponding method in this delegate. The default
15275     * implementation the delegate methods behaves exactly as the corresponding
15276     * method in View for the case of no accessibility delegate been set. Hence,
15277     * to customize the behavior of a View method, clients can override only the
15278     * corresponding delegate method without altering the behavior of the rest
15279     * accessibility related methods of the host view.
15280     * </p>
15281     */
15282    public static class AccessibilityDelegate {
15283
15284        /**
15285         * Sends an accessibility event of the given type. If accessibility is not
15286         * enabled this method has no effect.
15287         * <p>
15288         * The default implementation behaves as {@link View#sendAccessibilityEvent(int)
15289         *  View#sendAccessibilityEvent(int)} for the case of no accessibility delegate
15290         * been set.
15291         * </p>
15292         *
15293         * @param host The View hosting the delegate.
15294         * @param eventType The type of the event to send.
15295         *
15296         * @see View#sendAccessibilityEvent(int) View#sendAccessibilityEvent(int)
15297         */
15298        public void sendAccessibilityEvent(View host, int eventType) {
15299            host.sendAccessibilityEventInternal(eventType);
15300        }
15301
15302        /**
15303         * Sends an accessibility event. This method behaves exactly as
15304         * {@link #sendAccessibilityEvent(View, int)} but takes as an argument an
15305         * empty {@link AccessibilityEvent} and does not perform a check whether
15306         * accessibility is enabled.
15307         * <p>
15308         * The default implementation behaves as
15309         * {@link View#sendAccessibilityEventUnchecked(AccessibilityEvent)
15310         *  View#sendAccessibilityEventUnchecked(AccessibilityEvent)} for
15311         * the case of no accessibility delegate been set.
15312         * </p>
15313         *
15314         * @param host The View hosting the delegate.
15315         * @param event The event to send.
15316         *
15317         * @see View#sendAccessibilityEventUnchecked(AccessibilityEvent)
15318         *      View#sendAccessibilityEventUnchecked(AccessibilityEvent)
15319         */
15320        public void sendAccessibilityEventUnchecked(View host, AccessibilityEvent event) {
15321            host.sendAccessibilityEventUncheckedInternal(event);
15322        }
15323
15324        /**
15325         * Dispatches an {@link AccessibilityEvent} to the host {@link View} first and then
15326         * to its children for adding their text content to the event.
15327         * <p>
15328         * The default implementation behaves as
15329         * {@link View#dispatchPopulateAccessibilityEvent(AccessibilityEvent)
15330         *  View#dispatchPopulateAccessibilityEvent(AccessibilityEvent)} for
15331         * the case of no accessibility delegate been set.
15332         * </p>
15333         *
15334         * @param host The View hosting the delegate.
15335         * @param event The event.
15336         * @return True if the event population was completed.
15337         *
15338         * @see View#dispatchPopulateAccessibilityEvent(AccessibilityEvent)
15339         *      View#dispatchPopulateAccessibilityEvent(AccessibilityEvent)
15340         */
15341        public boolean dispatchPopulateAccessibilityEvent(View host, AccessibilityEvent event) {
15342            return host.dispatchPopulateAccessibilityEventInternal(event);
15343        }
15344
15345        /**
15346         * Gives a chance to the host View to populate the accessibility event with its
15347         * text content.
15348         * <p>
15349         * The default implementation behaves as
15350         * {@link View#onPopulateAccessibilityEvent(AccessibilityEvent)
15351         *  View#onPopulateAccessibilityEvent(AccessibilityEvent)} for
15352         * the case of no accessibility delegate been set.
15353         * </p>
15354         *
15355         * @param host The View hosting the delegate.
15356         * @param event The accessibility event which to populate.
15357         *
15358         * @see View#onPopulateAccessibilityEvent(AccessibilityEvent)
15359         *      View#onPopulateAccessibilityEvent(AccessibilityEvent)
15360         */
15361        public void onPopulateAccessibilityEvent(View host, AccessibilityEvent event) {
15362            host.onPopulateAccessibilityEventInternal(event);
15363        }
15364
15365        /**
15366         * Initializes an {@link AccessibilityEvent} with information about the
15367         * the host View which is the event source.
15368         * <p>
15369         * The default implementation behaves as
15370         * {@link View#onInitializeAccessibilityEvent(AccessibilityEvent)
15371         *  View#onInitializeAccessibilityEvent(AccessibilityEvent)} for
15372         * the case of no accessibility delegate been set.
15373         * </p>
15374         *
15375         * @param host The View hosting the delegate.
15376         * @param event The event to initialize.
15377         *
15378         * @see View#onInitializeAccessibilityEvent(AccessibilityEvent)
15379         *      View#onInitializeAccessibilityEvent(AccessibilityEvent)
15380         */
15381        public void onInitializeAccessibilityEvent(View host, AccessibilityEvent event) {
15382            host.onInitializeAccessibilityEventInternal(event);
15383        }
15384
15385        /**
15386         * Initializes an {@link AccessibilityNodeInfo} with information about the host view.
15387         * <p>
15388         * The default implementation behaves as
15389         * {@link View#onInitializeAccessibilityNodeInfo(AccessibilityNodeInfo)
15390         *  View#onInitializeAccessibilityNodeInfo(AccessibilityNodeInfo)} for
15391         * the case of no accessibility delegate been set.
15392         * </p>
15393         *
15394         * @param host The View hosting the delegate.
15395         * @param info The instance to initialize.
15396         *
15397         * @see View#onInitializeAccessibilityNodeInfo(AccessibilityNodeInfo)
15398         *      View#onInitializeAccessibilityNodeInfo(AccessibilityNodeInfo)
15399         */
15400        public void onInitializeAccessibilityNodeInfo(View host, AccessibilityNodeInfo info) {
15401            host.onInitializeAccessibilityNodeInfoInternal(info);
15402        }
15403
15404        /**
15405         * Called when a child of the host View has requested sending an
15406         * {@link AccessibilityEvent} and gives an opportunity to the parent (the host)
15407         * to augment the event.
15408         * <p>
15409         * The default implementation behaves as
15410         * {@link ViewGroup#onRequestSendAccessibilityEvent(View, AccessibilityEvent)
15411         *  ViewGroup#onRequestSendAccessibilityEvent(View, AccessibilityEvent)} for
15412         * the case of no accessibility delegate been set.
15413         * </p>
15414         *
15415         * @param host The View hosting the delegate.
15416         * @param child The child which requests sending the event.
15417         * @param event The event to be sent.
15418         * @return True if the event should be sent
15419         *
15420         * @see ViewGroup#onRequestSendAccessibilityEvent(View, AccessibilityEvent)
15421         *      ViewGroup#onRequestSendAccessibilityEvent(View, AccessibilityEvent)
15422         */
15423        public boolean onRequestSendAccessibilityEvent(ViewGroup host, View child,
15424                AccessibilityEvent event) {
15425            return host.onRequestSendAccessibilityEventInternal(child, event);
15426        }
15427
15428        /**
15429         * Gets the provider for managing a virtual view hierarchy rooted at this View
15430         * and reported to {@link android.accessibilityservice.AccessibilityService}s
15431         * that explore the window content.
15432         * <p>
15433         * The default implementation behaves as
15434         * {@link View#getAccessibilityNodeProvider() View#getAccessibilityNodeProvider()} for
15435         * the case of no accessibility delegate been set.
15436         * </p>
15437         *
15438         * @return The provider.
15439         *
15440         * @see AccessibilityNodeProvider
15441         */
15442        public AccessibilityNodeProvider getAccessibilityNodeProvider(View host) {
15443            return null;
15444        }
15445    }
15446}
15447