1 /*
2  * Copyright (C) 2008 The Android Open Source Project
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *      http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 
17 package android.view.cts;
18 
19 import static org.mockito.Mockito.*;
20 
21 import android.graphics.BitmapFactory;
22 import com.android.internal.view.menu.ContextMenuBuilder;
23 
24 import android.content.Context;
25 import android.content.res.ColorStateList;
26 import android.content.res.Resources;
27 import android.content.res.XmlResourceParser;
28 import android.cts.util.PollingCheck;
29 import android.graphics.Bitmap;
30 import android.graphics.Canvas;
31 import android.graphics.Color;
32 import android.graphics.ColorFilter;
33 import android.graphics.Point;
34 import android.graphics.PorterDuff;
35 import android.graphics.Rect;
36 import android.graphics.drawable.BitmapDrawable;
37 import android.graphics.drawable.ColorDrawable;
38 import android.graphics.drawable.Drawable;
39 import android.graphics.drawable.StateListDrawable;
40 import android.os.Bundle;
41 import android.os.Parcelable;
42 import android.os.SystemClock;
43 import android.os.Vibrator;
44 import android.test.ActivityInstrumentationTestCase2;
45 import android.test.TouchUtils;
46 import android.test.UiThreadTest;
47 import android.text.format.DateUtils;
48 import android.util.AttributeSet;
49 import android.util.Log;
50 import android.util.Pair;
51 import android.util.SparseArray;
52 import android.util.Xml;
53 import android.view.ActionMode;
54 import android.view.ContextMenu;
55 import android.view.ContextMenu.ContextMenuInfo;
56 import android.view.Display;
57 import android.view.HapticFeedbackConstants;
58 import android.view.InputDevice;
59 import android.view.KeyEvent;
60 import android.view.Menu;
61 import android.view.MenuInflater;
62 import android.view.MotionEvent;
63 import android.view.PointerIcon;
64 import android.view.SoundEffectConstants;
65 import android.view.TouchDelegate;
66 import android.view.View;
67 import android.view.View.BaseSavedState;
68 import android.view.View.OnClickListener;
69 import android.view.View.OnContextClickListener;
70 import android.view.View.OnCreateContextMenuListener;
71 import android.view.View.OnFocusChangeListener;
72 import android.view.View.OnKeyListener;
73 import android.view.View.OnLongClickListener;
74 import android.view.View.OnTouchListener;
75 import android.view.ViewConfiguration;
76 import android.view.ViewGroup;
77 import android.view.ViewParent;
78 import android.view.ViewTreeObserver;
79 import android.view.WindowManager;
80 import android.view.accessibility.AccessibilityEvent;
81 import android.view.animation.AlphaAnimation;
82 import android.view.animation.Animation;
83 import android.view.inputmethod.EditorInfo;
84 import android.view.inputmethod.InputConnection;
85 import android.view.inputmethod.InputMethodManager;
86 import android.widget.Button;
87 import android.widget.EditText;
88 import android.widget.FrameLayout;
89 import android.widget.LinearLayout;
90 
91 import java.lang.reflect.Constructor;
92 import java.util.ArrayList;
93 import java.util.Arrays;
94 import java.util.Collections;
95 import java.util.concurrent.CountDownLatch;
96 import java.util.concurrent.TimeUnit;
97 
98 /**
99  * Test {@link View}.
100  */
101 public class ViewTest extends ActivityInstrumentationTestCase2<ViewTestCtsActivity> {
ViewTest()102     public ViewTest() {
103         super(ViewTestCtsActivity.class);
104     }
105 
106     private Resources mResources;
107     private MockViewParent mMockParent;
108     private ViewTestCtsActivity mActivity;
109 
110     /** timeout delta when wait in case the system is sluggish */
111     private static final long TIMEOUT_DELTA = 10000;
112 
113     private static final String LOG_TAG = "ViewTest";
114 
115     @Override
setUp()116     protected void setUp() throws Exception {
117         super.setUp();
118         mActivity = getActivity();
119         new PollingCheck() {
120             @Override
121                 protected boolean check() {
122                 return mActivity.hasWindowFocus();
123             }
124         }.run();
125         mResources = mActivity.getResources();
126         mMockParent = new MockViewParent(mActivity);
127         assertTrue(mActivity.waitForWindowFocus(5 * DateUtils.SECOND_IN_MILLIS));
128     }
129 
testConstructor()130     public void testConstructor() {
131         new View(mActivity);
132 
133         final XmlResourceParser parser = mResources.getLayout(R.layout.view_layout);
134         final AttributeSet attrs = Xml.asAttributeSet(parser);
135         new View(mActivity, attrs);
136 
137         new View(mActivity, null);
138 
139         try {
140             new View(null, attrs);
141             fail("should throw NullPointerException");
142         } catch (NullPointerException e) {
143         }
144 
145         new View(mActivity, attrs, 0);
146 
147         new View(mActivity, null, 1);
148 
149         try {
150             new View(null, null, 1);
151             fail("should throw NullPointerException");
152         } catch (NullPointerException e) {
153         }
154     }
155 
156     // Test that validates that Views can be constructed on a thread that
157     // does not have a Looper. Necessary for async inflation
158     private Pair<Class<?>, Throwable> sCtorException = null;
testConstructor2()159     public void testConstructor2() throws Exception {
160         final Object[] args = new Object[] { mActivity, null };
161         final CountDownLatch latch = new CountDownLatch(1);
162         sCtorException = null;
163         new Thread() {
164             @Override
165             public void run() {
166                 final Class<?>[] ctorSignature = new Class[] {
167                         Context.class, AttributeSet.class};
168                 for (Class<?> clazz : ASYNC_INFLATE_VIEWS) {
169                     try {
170                         Constructor<?> constructor = clazz.getConstructor(ctorSignature);
171                         constructor.setAccessible(true);
172                         constructor.newInstance(args);
173                     } catch (Throwable t) {
174                         sCtorException = new Pair<Class<?>, Throwable>(clazz, t);
175                         break;
176                     }
177                 }
178                 latch.countDown();
179             }
180         }.start();
181         latch.await();
182         if (sCtorException != null) {
183             throw new AssertionError("Failed to inflate "
184                     + sCtorException.first.getName(), sCtorException.second);
185         }
186     }
187 
testGetContext()188     public void testGetContext() {
189         View view = new View(mActivity);
190         assertSame(mActivity, view.getContext());
191     }
192 
testGetResources()193     public void testGetResources() {
194         View view = new View(mActivity);
195         assertSame(mResources, view.getResources());
196     }
197 
testGetAnimation()198     public void testGetAnimation() {
199         Animation animation = new AlphaAnimation(0.0f, 1.0f);
200         View view = new View(mActivity);
201         assertNull(view.getAnimation());
202 
203         view.setAnimation(animation);
204         assertSame(animation, view.getAnimation());
205 
206         view.clearAnimation();
207         assertNull(view.getAnimation());
208     }
209 
testSetAnimation()210     public void testSetAnimation() {
211         Animation animation = new AlphaAnimation(0.0f, 1.0f);
212         View view = new View(mActivity);
213         assertNull(view.getAnimation());
214 
215         animation.initialize(100, 100, 100, 100);
216         assertTrue(animation.isInitialized());
217         view.setAnimation(animation);
218         assertSame(animation, view.getAnimation());
219         assertFalse(animation.isInitialized());
220 
221         view.setAnimation(null);
222         assertNull(view.getAnimation());
223     }
224 
testClearAnimation()225     public void testClearAnimation() {
226         Animation animation = new AlphaAnimation(0.0f, 1.0f);
227         View view = new View(mActivity);
228 
229         assertNull(view.getAnimation());
230         view.clearAnimation();
231         assertNull(view.getAnimation());
232 
233         view.setAnimation(animation);
234         assertNotNull(view.getAnimation());
235         view.clearAnimation();
236         assertNull(view.getAnimation());
237     }
238 
testStartAnimation()239     public void testStartAnimation() {
240         Animation animation = new AlphaAnimation(0.0f, 1.0f);
241         View view = new View(mActivity);
242 
243         try {
244             view.startAnimation(null);
245             fail("should throw NullPointerException");
246         } catch (NullPointerException e) {
247         }
248 
249         animation.setStartTime(1L);
250         assertEquals(1L, animation.getStartTime());
251         view.startAnimation(animation);
252         assertEquals(Animation.START_ON_FIRST_FRAME, animation.getStartTime());
253     }
254 
testOnAnimation()255     public void testOnAnimation() throws Throwable {
256         final Animation animation = new AlphaAnimation(0.0f, 1.0f);
257         long duration = 2000L;
258         animation.setDuration(duration);
259         final MockView view = (MockView) mActivity.findViewById(R.id.mock_view);
260 
261         // check whether it has started
262         runTestOnUiThread(new Runnable() {
263             @Override
264             public void run() {
265                 view.startAnimation(animation);
266             }
267         });
268         getInstrumentation().waitForIdleSync();
269 
270         new PollingCheck() {
271             @Override
272             protected boolean check() {
273                 return view.hasCalledOnAnimationStart();
274             }
275         }.run();
276 
277         // check whether it has ended after duration, and alpha changed during this time.
278         new PollingCheck(duration + TIMEOUT_DELTA) {
279             @Override
280             protected boolean check() {
281                 return view.hasCalledOnSetAlpha() && view.hasCalledOnAnimationEnd();
282             }
283         }.run();
284     }
285 
testGetParent()286     public void testGetParent() {
287         MockView view = (MockView) mActivity.findViewById(R.id.mock_view);
288         ViewGroup parent = (ViewGroup) mActivity.findViewById(R.id.viewlayout_root);
289         assertSame(parent, view.getParent());
290     }
291 
testAccessScrollIndicators()292     public void testAccessScrollIndicators() {
293         View view = mActivity.findViewById(R.id.viewlayout_root);
294 
295         assertEquals(View.SCROLL_INDICATOR_LEFT | View.SCROLL_INDICATOR_RIGHT,
296                 view.getScrollIndicators());
297     }
298 
testSetScrollIndicators()299     public void testSetScrollIndicators() {
300         View view = new View(mActivity);
301 
302         view.setScrollIndicators(0);
303         assertEquals(0, view.getScrollIndicators());
304 
305         view.setScrollIndicators(View.SCROLL_INDICATOR_LEFT | View.SCROLL_INDICATOR_RIGHT);
306         assertEquals(View.SCROLL_INDICATOR_LEFT | View.SCROLL_INDICATOR_RIGHT,
307                 view.getScrollIndicators());
308 
309         view.setScrollIndicators(View.SCROLL_INDICATOR_TOP, View.SCROLL_INDICATOR_TOP);
310         assertEquals(View.SCROLL_INDICATOR_LEFT | View.SCROLL_INDICATOR_RIGHT
311                         | View.SCROLL_INDICATOR_TOP, view.getScrollIndicators());
312 
313         view.setScrollIndicators(0, view.getScrollIndicators());
314         assertEquals(0, view.getScrollIndicators());
315     }
316 
testFindViewById()317     public void testFindViewById() {
318         View parent = mActivity.findViewById(R.id.viewlayout_root);
319         assertSame(parent, parent.findViewById(R.id.viewlayout_root));
320 
321         View view = parent.findViewById(R.id.mock_view);
322         assertTrue(view instanceof MockView);
323     }
324 
testAccessTouchDelegate()325     public void testAccessTouchDelegate() throws Throwable {
326         final MockView view = (MockView) mActivity.findViewById(R.id.mock_view);
327         Rect rect = new Rect();
328         final Button button = new Button(mActivity);
329         final int WRAP_CONTENT = ViewGroup.LayoutParams.WRAP_CONTENT;
330         final int btnHeight = view.getHeight()/3;
331         runTestOnUiThread(new Runnable() {
332             @Override
333             public void run() {
334                 mActivity.addContentView(button,
335                         new LinearLayout.LayoutParams(WRAP_CONTENT, btnHeight));
336             }
337         });
338         getInstrumentation().waitForIdleSync();
339         button.getHitRect(rect);
340         MockTouchDelegate delegate = new MockTouchDelegate(rect, button);
341 
342         assertNull(view.getTouchDelegate());
343 
344         view.setTouchDelegate(delegate);
345         assertSame(delegate, view.getTouchDelegate());
346         assertFalse(delegate.hasCalledOnTouchEvent());
347         TouchUtils.clickView(this, view);
348         assertTrue(view.hasCalledOnTouchEvent());
349         assertTrue(delegate.hasCalledOnTouchEvent());
350 
351         view.setTouchDelegate(null);
352         assertNull(view.getTouchDelegate());
353     }
354 
testMouseEventCallsGetPointerIcon()355     public void testMouseEventCallsGetPointerIcon() {
356         final MockView view = (MockView) mActivity.findViewById(R.id.mock_view);
357 
358         final int[] xy = new int[2];
359         view.getLocationOnScreen(xy);
360         final int viewWidth = view.getWidth();
361         final int viewHeight = view.getHeight();
362         float x = xy[0] + viewWidth / 2.0f;
363         float y = xy[1] + viewHeight / 2.0f;
364 
365         long eventTime = SystemClock.uptimeMillis();
366 
367         MotionEvent.PointerCoords[] pointerCoords = new MotionEvent.PointerCoords[1];
368         pointerCoords[0] = new MotionEvent.PointerCoords();
369         pointerCoords[0].x = x;
370         pointerCoords[0].y = y;
371 
372         final int[] pointerIds = new int[1];
373         pointerIds[0] = 0;
374 
375         MotionEvent event = MotionEvent.obtain(0, eventTime, MotionEvent.ACTION_HOVER_MOVE,
376                 1, pointerIds, pointerCoords, 0, 0, 0, 0, 0, InputDevice.SOURCE_MOUSE, 0);
377         getInstrumentation().sendPointerSync(event);
378         getInstrumentation().waitForIdleSync();
379 
380         assertTrue(view.hasCalledOnResolvePointerIcon());
381 
382         final MockView view2 = (MockView) mActivity.findViewById(R.id.scroll_view);
383         assertFalse(view2.hasCalledOnResolvePointerIcon());
384     }
385 
testAccessPointerIcon()386     public void testAccessPointerIcon() {
387         View view = mActivity.findViewById(R.id.pointer_icon_layout);
388         MotionEvent event = MotionEvent.obtain(0, 0, MotionEvent.ACTION_HOVER_MOVE, 0, 0, 0);
389 
390         // First view has pointerIcon="help"
391         assertEquals(PointerIcon.getSystemIcon(mActivity, PointerIcon.TYPE_HELP),
392                      view.onResolvePointerIcon(event, 0));
393 
394         // Second view inherits pointerIcon="crosshair" from the parent
395         event.setLocation(0, 21);
396         assertEquals(PointerIcon.getSystemIcon(mActivity, PointerIcon.TYPE_CROSSHAIR),
397                      view.onResolvePointerIcon(event, 0));
398 
399         // Third view has custom pointer icon defined in a resource.
400         event.setLocation(0, 41);
401         assertNotNull(view.onResolvePointerIcon(event, 0));
402 
403         // Parent view has pointerIcon="crosshair"
404         event.setLocation(0, 61);
405         assertEquals(PointerIcon.getSystemIcon(mActivity, PointerIcon.TYPE_CROSSHAIR),
406                      view.onResolvePointerIcon(event, 0));
407 
408         // Outside of the parent view, no pointer icon defined.
409         event.setLocation(0, 71);
410         assertNull(view.onResolvePointerIcon(event, 0));
411 
412         view.setPointerIcon(PointerIcon.getSystemIcon(mActivity, PointerIcon.TYPE_TEXT));
413         assertEquals(PointerIcon.getSystemIcon(mActivity, PointerIcon.TYPE_TEXT),
414                      view.onResolvePointerIcon(event, 0));
415         event.recycle();
416     }
417 
testCreatePointerIcons()418     public void testCreatePointerIcons() {
419         assertSystemPointerIcon(PointerIcon.TYPE_NULL);
420         assertSystemPointerIcon(PointerIcon.TYPE_DEFAULT);
421         assertSystemPointerIcon(PointerIcon.TYPE_ARROW);
422         assertSystemPointerIcon(PointerIcon.TYPE_CONTEXT_MENU);
423         assertSystemPointerIcon(PointerIcon.TYPE_HAND);
424         assertSystemPointerIcon(PointerIcon.TYPE_HELP);
425         assertSystemPointerIcon(PointerIcon.TYPE_WAIT);
426         assertSystemPointerIcon(PointerIcon.TYPE_CELL);
427         assertSystemPointerIcon(PointerIcon.TYPE_CROSSHAIR);
428         assertSystemPointerIcon(PointerIcon.TYPE_TEXT);
429         assertSystemPointerIcon(PointerIcon.TYPE_VERTICAL_TEXT);
430         assertSystemPointerIcon(PointerIcon.TYPE_ALIAS);
431         assertSystemPointerIcon(PointerIcon.TYPE_COPY);
432         assertSystemPointerIcon(PointerIcon.TYPE_NO_DROP);
433         assertSystemPointerIcon(PointerIcon.TYPE_ALL_SCROLL);
434         assertSystemPointerIcon(PointerIcon.TYPE_HORIZONTAL_DOUBLE_ARROW);
435         assertSystemPointerIcon(PointerIcon.TYPE_VERTICAL_DOUBLE_ARROW);
436         assertSystemPointerIcon(PointerIcon.TYPE_TOP_RIGHT_DIAGONAL_DOUBLE_ARROW);
437         assertSystemPointerIcon(PointerIcon.TYPE_TOP_LEFT_DIAGONAL_DOUBLE_ARROW);
438         assertSystemPointerIcon(PointerIcon.TYPE_ZOOM_IN);
439         assertSystemPointerIcon(PointerIcon.TYPE_ZOOM_OUT);
440         assertSystemPointerIcon(PointerIcon.TYPE_GRAB);
441 
442         assertNotNull(PointerIcon.load(mResources, R.drawable.custom_pointer_icon));
443 
444         Bitmap bitmap = BitmapFactory.decodeResource(mResources, R.drawable.icon_blue);
445         assertNotNull(PointerIcon.create(bitmap, 0, 0));
446     }
447 
assertSystemPointerIcon(int style)448     private void assertSystemPointerIcon(int style) {
449         assertNotNull(PointerIcon.getSystemIcon(mActivity, style));
450     }
451 
452     @UiThreadTest
testAccessTag()453     public void testAccessTag() {
454         ViewGroup viewGroup = (ViewGroup) mActivity.findViewById(R.id.viewlayout_root);
455         MockView mockView = (MockView) mActivity.findViewById(R.id.mock_view);
456         MockView scrollView = (MockView) mActivity.findViewById(R.id.scroll_view);
457 
458         ViewData viewData = new ViewData();
459         viewData.childCount = 3;
460         viewData.tag = "linearLayout";
461         viewData.firstChild = mockView;
462         viewGroup.setTag(viewData);
463         viewGroup.setFocusable(true);
464         assertSame(viewData, viewGroup.getTag());
465 
466         final String tag = "mock";
467         assertNull(mockView.getTag());
468         mockView.setTag(tag);
469         assertEquals(tag, mockView.getTag());
470 
471         scrollView.setTag(viewGroup);
472         assertSame(viewGroup, scrollView.getTag());
473 
474         assertSame(viewGroup, viewGroup.findViewWithTag(viewData));
475         assertSame(mockView, viewGroup.findViewWithTag(tag));
476         assertSame(scrollView, viewGroup.findViewWithTag(viewGroup));
477 
478         mockView.setTag(null);
479         assertNull(mockView.getTag());
480     }
481 
testOnSizeChanged()482     public void testOnSizeChanged() throws Throwable {
483         final ViewGroup viewGroup = (ViewGroup) mActivity.findViewById(R.id.viewlayout_root);
484         final MockView mockView = new MockView(mActivity);
485         assertEquals(-1, mockView.getOldWOnSizeChanged());
486         assertEquals(-1, mockView.getOldHOnSizeChanged());
487         runTestOnUiThread(new Runnable() {
488             @Override
489             public void run() {
490                 viewGroup.addView(mockView);
491             }
492         });
493         getInstrumentation().waitForIdleSync();
494         assertTrue(mockView.hasCalledOnSizeChanged());
495         assertEquals(0, mockView.getOldWOnSizeChanged());
496         assertEquals(0, mockView.getOldHOnSizeChanged());
497 
498         final MockView view = (MockView) mActivity.findViewById(R.id.mock_view);
499         assertTrue(view.hasCalledOnSizeChanged());
500         view.reset();
501         assertEquals(-1, view.getOldWOnSizeChanged());
502         assertEquals(-1, view.getOldHOnSizeChanged());
503         int oldw = view.getWidth();
504         int oldh = view.getHeight();
505         final LinearLayout.LayoutParams layoutParams = new LinearLayout.LayoutParams(200, 100);
506         runTestOnUiThread(new Runnable() {
507             @Override
508             public void run() {
509                 view.setLayoutParams(layoutParams);
510             }
511         });
512         getInstrumentation().waitForIdleSync();
513         assertTrue(view.hasCalledOnSizeChanged());
514         assertEquals(oldw, view.getOldWOnSizeChanged());
515         assertEquals(oldh, view.getOldHOnSizeChanged());
516     }
517 
testGetHitRect()518     public void testGetHitRect() {
519         MockView view = new MockView(mActivity);
520         Rect outRect = new Rect();
521 
522         try {
523             view.getHitRect(null);
524             fail("should throw NullPointerException");
525         } catch (NullPointerException e) {
526         }
527 
528         View mockView = mActivity.findViewById(R.id.mock_view);
529         mockView.getHitRect(outRect);
530         assertEquals(0, outRect.left);
531         assertEquals(0, outRect.top);
532         assertEquals(mockView.getWidth(), outRect.right);
533         assertEquals(mockView.getHeight(), outRect.bottom);
534     }
535 
testForceLayout()536     public void testForceLayout() {
537         View view = new View(mActivity);
538 
539         assertFalse(view.isLayoutRequested());
540         view.forceLayout();
541         assertTrue(view.isLayoutRequested());
542 
543         view.forceLayout();
544         assertTrue(view.isLayoutRequested());
545     }
546 
testIsLayoutRequested()547     public void testIsLayoutRequested() {
548         View view = new View(mActivity);
549 
550         assertFalse(view.isLayoutRequested());
551         view.forceLayout();
552         assertTrue(view.isLayoutRequested());
553 
554         view.layout(0, 0, 0, 0);
555         assertFalse(view.isLayoutRequested());
556     }
557 
testRequestLayout()558     public void testRequestLayout() {
559         MockView view = new MockView(mActivity);
560         assertFalse(view.isLayoutRequested());
561         assertNull(view.getParent());
562 
563         view.requestLayout();
564         assertTrue(view.isLayoutRequested());
565 
566         view.setParent(mMockParent);
567         assertTrue(mMockParent.hasRequestLayout());
568 
569         mMockParent.reset();
570         view.requestLayout();
571         assertTrue(view.isLayoutRequested());
572         assertTrue(mMockParent.hasRequestLayout());
573     }
574 
testLayout()575     public void testLayout() throws Throwable {
576         final MockView view = (MockView) mActivity.findViewById(R.id.mock_view);
577         assertTrue(view.hasCalledOnLayout());
578 
579         view.reset();
580         assertFalse(view.hasCalledOnLayout());
581         runTestOnUiThread(new Runnable() {
582             @Override
583             public void run() {
584                 view.requestLayout();
585             }
586         });
587         getInstrumentation().waitForIdleSync();
588         assertTrue(view.hasCalledOnLayout());
589     }
590 
testGetBaseline()591     public void testGetBaseline() {
592         View view = new View(mActivity);
593 
594         assertEquals(-1, view.getBaseline());
595     }
596 
testAccessBackground()597     public void testAccessBackground() {
598         View view = new View(mActivity);
599         Drawable d1 = mResources.getDrawable(R.drawable.scenery);
600         Drawable d2 = mResources.getDrawable(R.drawable.pass);
601 
602         assertNull(view.getBackground());
603 
604         view.setBackgroundDrawable(d1);
605         assertEquals(d1, view.getBackground());
606 
607         view.setBackgroundDrawable(d2);
608         assertEquals(d2, view.getBackground());
609 
610         view.setBackgroundDrawable(null);
611         assertNull(view.getBackground());
612     }
613 
testSetBackgroundResource()614     public void testSetBackgroundResource() {
615         View view = new View(mActivity);
616 
617         assertNull(view.getBackground());
618 
619         view.setBackgroundResource(R.drawable.pass);
620         assertNotNull(view.getBackground());
621 
622         view.setBackgroundResource(0);
623         assertNull(view.getBackground());
624     }
625 
testAccessDrawingCacheBackgroundColor()626     public void testAccessDrawingCacheBackgroundColor() {
627         View view = new View(mActivity);
628 
629         assertEquals(0, view.getDrawingCacheBackgroundColor());
630 
631         view.setDrawingCacheBackgroundColor(0xFF00FF00);
632         assertEquals(0xFF00FF00, view.getDrawingCacheBackgroundColor());
633 
634         view.setDrawingCacheBackgroundColor(-1);
635         assertEquals(-1, view.getDrawingCacheBackgroundColor());
636     }
637 
testSetBackgroundColor()638     public void testSetBackgroundColor() {
639         View view = new View(mActivity);
640         ColorDrawable colorDrawable;
641         assertNull(view.getBackground());
642 
643         view.setBackgroundColor(0xFFFF0000);
644         colorDrawable = (ColorDrawable) view.getBackground();
645         assertNotNull(colorDrawable);
646         assertEquals(0xFF, colorDrawable.getAlpha());
647 
648         view.setBackgroundColor(0);
649         colorDrawable = (ColorDrawable) view.getBackground();
650         assertNotNull(colorDrawable);
651         assertEquals(0, colorDrawable.getAlpha());
652     }
653 
testVerifyDrawable()654     public void testVerifyDrawable() {
655         MockView view = new MockView(mActivity);
656         Drawable d1 = mResources.getDrawable(R.drawable.scenery);
657         Drawable d2 = mResources.getDrawable(R.drawable.pass);
658 
659         assertNull(view.getBackground());
660         assertTrue(view.verifyDrawable(null));
661         assertFalse(view.verifyDrawable(d1));
662 
663         view.setBackgroundDrawable(d1);
664         assertTrue(view.verifyDrawable(d1));
665         assertFalse(view.verifyDrawable(d2));
666     }
667 
testGetDrawingRect()668     public void testGetDrawingRect() {
669         MockView view = new MockView(mActivity);
670         Rect outRect = new Rect();
671 
672         view.getDrawingRect(outRect);
673         assertEquals(0, outRect.left);
674         assertEquals(0, outRect.top);
675         assertEquals(0, outRect.right);
676         assertEquals(0, outRect.bottom);
677 
678         view.scrollTo(10, 100);
679         view.getDrawingRect(outRect);
680         assertEquals(10, outRect.left);
681         assertEquals(100, outRect.top);
682         assertEquals(10, outRect.right);
683         assertEquals(100, outRect.bottom);
684 
685         View mockView = mActivity.findViewById(R.id.mock_view);
686         mockView.getDrawingRect(outRect);
687         assertEquals(0, outRect.left);
688         assertEquals(0, outRect.top);
689         assertEquals(mockView.getWidth(), outRect.right);
690         assertEquals(mockView.getHeight(), outRect.bottom);
691     }
692 
testGetFocusedRect()693     public void testGetFocusedRect() {
694         MockView view = new MockView(mActivity);
695         Rect outRect = new Rect();
696 
697         view.getFocusedRect(outRect);
698         assertEquals(0, outRect.left);
699         assertEquals(0, outRect.top);
700         assertEquals(0, outRect.right);
701         assertEquals(0, outRect.bottom);
702 
703         view.scrollTo(10, 100);
704         view.getFocusedRect(outRect);
705         assertEquals(10, outRect.left);
706         assertEquals(100, outRect.top);
707         assertEquals(10, outRect.right);
708         assertEquals(100, outRect.bottom);
709     }
710 
testGetGlobalVisibleRectPoint()711     public void testGetGlobalVisibleRectPoint() throws Throwable {
712         final View view = mActivity.findViewById(R.id.mock_view);
713         final ViewGroup viewGroup = (ViewGroup) mActivity.findViewById(R.id.viewlayout_root);
714         Rect rect = new Rect();
715         Point point = new Point();
716 
717         assertTrue(view.getGlobalVisibleRect(rect, point));
718         Rect rcParent = new Rect();
719         Point ptParent = new Point();
720         viewGroup.getGlobalVisibleRect(rcParent, ptParent);
721         assertEquals(rcParent.left, rect.left);
722         assertEquals(rcParent.top, rect.top);
723         assertEquals(rect.left + view.getWidth(), rect.right);
724         assertEquals(rect.top + view.getHeight(), rect.bottom);
725         assertEquals(ptParent.x, point.x);
726         assertEquals(ptParent.y, point.y);
727 
728         // width is 0
729         final LinearLayout.LayoutParams layoutParams1 = new LinearLayout.LayoutParams(0, 300);
730         runTestOnUiThread(new Runnable() {
731             @Override
732             public void run() {
733                 view.setLayoutParams(layoutParams1);
734             }
735         });
736         getInstrumentation().waitForIdleSync();
737         assertFalse(view.getGlobalVisibleRect(rect, point));
738 
739         // height is -10
740         final LinearLayout.LayoutParams layoutParams2 = new LinearLayout.LayoutParams(200, -10);
741         runTestOnUiThread(new Runnable() {
742             @Override
743             public void run() {
744                 view.setLayoutParams(layoutParams2);
745             }
746         });
747         getInstrumentation().waitForIdleSync();
748         assertFalse(view.getGlobalVisibleRect(rect, point));
749 
750         Display display = getActivity().getWindowManager().getDefaultDisplay();
751         int halfWidth = display.getWidth() / 2;
752         int halfHeight = display.getHeight() /2;
753 
754         final LinearLayout.LayoutParams layoutParams3 =
755                 new LinearLayout.LayoutParams(halfWidth, halfHeight);
756         runTestOnUiThread(new Runnable() {
757             @Override
758             public void run() {
759                 view.setLayoutParams(layoutParams3);
760             }
761         });
762         getInstrumentation().waitForIdleSync();
763         assertTrue(view.getGlobalVisibleRect(rect, point));
764         assertEquals(rcParent.left, rect.left);
765         assertEquals(rcParent.top, rect.top);
766         assertEquals(rect.left + halfWidth, rect.right);
767         assertEquals(rect.top + halfHeight, rect.bottom);
768         assertEquals(ptParent.x, point.x);
769         assertEquals(ptParent.y, point.y);
770     }
771 
testGetGlobalVisibleRect()772     public void testGetGlobalVisibleRect() throws Throwable {
773         final View view = mActivity.findViewById(R.id.mock_view);
774         final ViewGroup viewGroup = (ViewGroup) mActivity.findViewById(R.id.viewlayout_root);
775         Rect rect = new Rect();
776 
777         assertTrue(view.getGlobalVisibleRect(rect));
778         Rect rcParent = new Rect();
779         viewGroup.getGlobalVisibleRect(rcParent);
780         assertEquals(rcParent.left, rect.left);
781         assertEquals(rcParent.top, rect.top);
782         assertEquals(rect.left + view.getWidth(), rect.right);
783         assertEquals(rect.top + view.getHeight(), rect.bottom);
784 
785         // width is 0
786         final LinearLayout.LayoutParams layoutParams1 = new LinearLayout.LayoutParams(0, 300);
787         runTestOnUiThread(new Runnable() {
788             @Override
789             public void run() {
790                 view.setLayoutParams(layoutParams1);
791             }
792         });
793         getInstrumentation().waitForIdleSync();
794         assertFalse(view.getGlobalVisibleRect(rect));
795 
796         // height is -10
797         final LinearLayout.LayoutParams layoutParams2 = new LinearLayout.LayoutParams(200, -10);
798         runTestOnUiThread(new Runnable() {
799             @Override
800             public void run() {
801                 view.setLayoutParams(layoutParams2);
802             }
803         });
804         getInstrumentation().waitForIdleSync();
805         assertFalse(view.getGlobalVisibleRect(rect));
806 
807         Display display = getActivity().getWindowManager().getDefaultDisplay();
808         int halfWidth = display.getWidth() / 2;
809         int halfHeight = display.getHeight() /2;
810 
811         final LinearLayout.LayoutParams layoutParams3 =
812                 new LinearLayout.LayoutParams(halfWidth, halfHeight);
813         runTestOnUiThread(new Runnable() {
814             @Override
815             public void run() {
816                 view.setLayoutParams(layoutParams3);
817             }
818         });
819         getInstrumentation().waitForIdleSync();
820         assertTrue(view.getGlobalVisibleRect(rect));
821         assertEquals(rcParent.left, rect.left);
822         assertEquals(rcParent.top, rect.top);
823         assertEquals(rect.left + halfWidth, rect.right);
824         assertEquals(rect.top + halfHeight, rect.bottom);
825     }
826 
testComputeHorizontalScroll()827     public void testComputeHorizontalScroll() throws Throwable {
828         final MockView view = (MockView) mActivity.findViewById(R.id.mock_view);
829 
830         assertEquals(0, view.computeHorizontalScrollOffset());
831         assertEquals(view.getWidth(), view.computeHorizontalScrollRange());
832         assertEquals(view.getWidth(), view.computeHorizontalScrollExtent());
833 
834         runTestOnUiThread(new Runnable() {
835             @Override
836             public void run() {
837                 view.scrollTo(12, 0);
838             }
839         });
840         getInstrumentation().waitForIdleSync();
841         assertEquals(12, view.computeHorizontalScrollOffset());
842         assertEquals(view.getWidth(), view.computeHorizontalScrollRange());
843         assertEquals(view.getWidth(), view.computeHorizontalScrollExtent());
844 
845         runTestOnUiThread(new Runnable() {
846             @Override
847             public void run() {
848                 view.scrollBy(12, 0);
849             }
850         });
851         getInstrumentation().waitForIdleSync();
852         assertEquals(24, view.computeHorizontalScrollOffset());
853         assertEquals(view.getWidth(), view.computeHorizontalScrollRange());
854         assertEquals(view.getWidth(), view.computeHorizontalScrollExtent());
855 
856         int newWidth = 200;
857         final LinearLayout.LayoutParams layoutParams = new LinearLayout.LayoutParams(newWidth, 100);
858         runTestOnUiThread(new Runnable() {
859             @Override
860             public void run() {
861                 view.setLayoutParams(layoutParams);
862             }
863         });
864         getInstrumentation().waitForIdleSync();
865         assertEquals(24, view.computeHorizontalScrollOffset());
866         assertEquals(newWidth, view.getWidth());
867         assertEquals(view.getWidth(), view.computeHorizontalScrollRange());
868         assertEquals(view.getWidth(), view.computeHorizontalScrollExtent());
869     }
870 
testComputeVerticalScroll()871     public void testComputeVerticalScroll() throws Throwable {
872         final MockView view = (MockView) mActivity.findViewById(R.id.mock_view);
873 
874         assertEquals(0, view.computeVerticalScrollOffset());
875         assertEquals(view.getHeight(), view.computeVerticalScrollRange());
876         assertEquals(view.getHeight(), view.computeVerticalScrollExtent());
877 
878         final int scrollToY = 34;
879         runTestOnUiThread(new Runnable() {
880             @Override
881             public void run() {
882                 view.scrollTo(0, scrollToY);
883             }
884         });
885         getInstrumentation().waitForIdleSync();
886         assertEquals(scrollToY, view.computeVerticalScrollOffset());
887         assertEquals(view.getHeight(), view.computeVerticalScrollRange());
888         assertEquals(view.getHeight(), view.computeVerticalScrollExtent());
889 
890         final int scrollByY = 200;
891         runTestOnUiThread(new Runnable() {
892             @Override
893             public void run() {
894                 view.scrollBy(0, scrollByY);
895             }
896         });
897         getInstrumentation().waitForIdleSync();
898         assertEquals(scrollToY + scrollByY, view.computeVerticalScrollOffset());
899         assertEquals(view.getHeight(), view.computeVerticalScrollRange());
900         assertEquals(view.getHeight(), view.computeVerticalScrollExtent());
901 
902         int newHeight = 333;
903         final LinearLayout.LayoutParams layoutParams = new LinearLayout.LayoutParams(200, newHeight);
904         runTestOnUiThread(new Runnable() {
905             @Override
906             public void run() {
907                 view.setLayoutParams(layoutParams);
908             }
909         });
910         getInstrumentation().waitForIdleSync();
911         assertEquals(scrollToY + scrollByY, view.computeVerticalScrollOffset());
912         assertEquals(newHeight, view.getHeight());
913         assertEquals(view.getHeight(), view.computeVerticalScrollRange());
914         assertEquals(view.getHeight(), view.computeVerticalScrollExtent());
915     }
916 
testGetFadingEdgeStrength()917     public void testGetFadingEdgeStrength() throws Throwable {
918         final MockView view = (MockView) mActivity.findViewById(R.id.mock_view);
919 
920         assertEquals(0f, view.getLeftFadingEdgeStrength());
921         assertEquals(0f, view.getRightFadingEdgeStrength());
922         assertEquals(0f, view.getTopFadingEdgeStrength());
923         assertEquals(0f, view.getBottomFadingEdgeStrength());
924 
925         runTestOnUiThread(new Runnable() {
926             @Override
927             public void run() {
928                 view.scrollTo(10, 10);
929             }
930         });
931         getInstrumentation().waitForIdleSync();
932         assertEquals(1f, view.getLeftFadingEdgeStrength());
933         assertEquals(0f, view.getRightFadingEdgeStrength());
934         assertEquals(1f, view.getTopFadingEdgeStrength());
935         assertEquals(0f, view.getBottomFadingEdgeStrength());
936 
937         runTestOnUiThread(new Runnable() {
938             @Override
939             public void run() {
940                 view.scrollTo(-10, -10);
941             }
942         });
943         getInstrumentation().waitForIdleSync();
944         assertEquals(0f, view.getLeftFadingEdgeStrength());
945         assertEquals(1f, view.getRightFadingEdgeStrength());
946         assertEquals(0f, view.getTopFadingEdgeStrength());
947         assertEquals(1f, view.getBottomFadingEdgeStrength());
948     }
949 
testGetLeftFadingEdgeStrength()950     public void testGetLeftFadingEdgeStrength() {
951         MockView view = new MockView(mActivity);
952 
953         assertEquals(0.0f, view.getLeftFadingEdgeStrength());
954 
955         view.scrollTo(1, 0);
956         assertEquals(1.0f, view.getLeftFadingEdgeStrength());
957     }
958 
testGetRightFadingEdgeStrength()959     public void testGetRightFadingEdgeStrength() {
960         MockView view = new MockView(mActivity);
961 
962         assertEquals(0.0f, view.getRightFadingEdgeStrength());
963 
964         view.scrollTo(-1, 0);
965         assertEquals(1.0f, view.getRightFadingEdgeStrength());
966     }
967 
testGetBottomFadingEdgeStrength()968     public void testGetBottomFadingEdgeStrength() {
969         MockView view = new MockView(mActivity);
970 
971         assertEquals(0.0f, view.getBottomFadingEdgeStrength());
972 
973         view.scrollTo(0, -2);
974         assertEquals(1.0f, view.getBottomFadingEdgeStrength());
975     }
976 
testGetTopFadingEdgeStrength()977     public void testGetTopFadingEdgeStrength() {
978         MockView view = new MockView(mActivity);
979 
980         assertEquals(0.0f, view.getTopFadingEdgeStrength());
981 
982         view.scrollTo(0, 2);
983         assertEquals(1.0f, view.getTopFadingEdgeStrength());
984     }
985 
testResolveSize()986     public void testResolveSize() {
987         assertEquals(50, View.resolveSize(50, View.MeasureSpec.UNSPECIFIED));
988 
989         assertEquals(40, View.resolveSize(50, 40 | View.MeasureSpec.EXACTLY));
990 
991         assertEquals(30, View.resolveSize(50, 30 | View.MeasureSpec.AT_MOST));
992 
993         assertEquals(20, View.resolveSize(20, 30 | View.MeasureSpec.AT_MOST));
994     }
995 
testGetDefaultSize()996     public void testGetDefaultSize() {
997         assertEquals(50, View.getDefaultSize(50, View.MeasureSpec.UNSPECIFIED));
998 
999         assertEquals(40, View.getDefaultSize(50, 40 | View.MeasureSpec.EXACTLY));
1000 
1001         assertEquals(30, View.getDefaultSize(50, 30 | View.MeasureSpec.AT_MOST));
1002 
1003         assertEquals(30, View.getDefaultSize(20, 30 | View.MeasureSpec.AT_MOST));
1004     }
1005 
testAccessId()1006     public void testAccessId() {
1007         View view = new View(mActivity);
1008 
1009         assertEquals(View.NO_ID, view.getId());
1010 
1011         view.setId(10);
1012         assertEquals(10, view.getId());
1013 
1014         view.setId(0xFFFFFFFF);
1015         assertEquals(0xFFFFFFFF, view.getId());
1016     }
1017 
testAccessLongClickable()1018     public void testAccessLongClickable() {
1019         View view = new View(mActivity);
1020 
1021         assertFalse(view.isLongClickable());
1022 
1023         view.setLongClickable(true);
1024         assertTrue(view.isLongClickable());
1025 
1026         view.setLongClickable(false);
1027         assertFalse(view.isLongClickable());
1028     }
1029 
testAccessClickable()1030     public void testAccessClickable() {
1031         View view = new View(mActivity);
1032 
1033         assertFalse(view.isClickable());
1034 
1035         view.setClickable(true);
1036         assertTrue(view.isClickable());
1037 
1038         view.setClickable(false);
1039         assertFalse(view.isClickable());
1040     }
1041 
testAccessContextClickable()1042     public void testAccessContextClickable() {
1043         View view = new View(mActivity);
1044 
1045         assertFalse(view.isContextClickable());
1046 
1047         view.setContextClickable(true);
1048         assertTrue(view.isContextClickable());
1049 
1050         view.setContextClickable(false);
1051         assertFalse(view.isContextClickable());
1052     }
1053 
testGetContextMenuInfo()1054     public void testGetContextMenuInfo() {
1055         MockView view = new MockView(mActivity);
1056 
1057         assertNull(view.getContextMenuInfo());
1058     }
1059 
testSetOnCreateContextMenuListener()1060     public void testSetOnCreateContextMenuListener() {
1061         View view = new View(mActivity);
1062         assertFalse(view.isLongClickable());
1063 
1064         view.setOnCreateContextMenuListener(null);
1065         assertTrue(view.isLongClickable());
1066 
1067         view.setOnCreateContextMenuListener(new OnCreateContextMenuListenerImpl());
1068         assertTrue(view.isLongClickable());
1069     }
1070 
testCreateContextMenu()1071     public void testCreateContextMenu() {
1072         OnCreateContextMenuListenerImpl listener = new OnCreateContextMenuListenerImpl();
1073         MockView view = new MockView(mActivity);
1074         ContextMenu contextMenu = new ContextMenuBuilder(mActivity);
1075         view.setParent(mMockParent);
1076         view.setOnCreateContextMenuListener(listener);
1077         assertFalse(view.hasCalledOnCreateContextMenu());
1078         assertFalse(mMockParent.hasCreateContextMenu());
1079         assertFalse(listener.hasOnCreateContextMenu());
1080 
1081         view.createContextMenu(contextMenu);
1082         assertTrue(view.hasCalledOnCreateContextMenu());
1083         assertTrue(mMockParent.hasCreateContextMenu());
1084         assertTrue(listener.hasOnCreateContextMenu());
1085 
1086         try {
1087             view.createContextMenu(null);
1088             fail("should throw NullPointerException");
1089         } catch (NullPointerException e) {
1090         }
1091     }
1092 
testAddFocusables()1093     public void testAddFocusables() {
1094         View view = new View(mActivity);
1095         ArrayList<View> viewList = new ArrayList<>();
1096 
1097         // view is not focusable
1098         assertFalse(view.isFocusable());
1099         assertEquals(0, viewList.size());
1100         view.addFocusables(viewList, 0);
1101         assertEquals(0, viewList.size());
1102 
1103         // view is focusable
1104         view.setFocusable(true);
1105         view.addFocusables(viewList, 0);
1106         assertEquals(1, viewList.size());
1107         assertEquals(view, viewList.get(0));
1108 
1109         // null array should be ignored
1110         view.addFocusables(null, 0);
1111     }
1112 
testGetFocusables()1113     public void testGetFocusables() {
1114         View view = new View(mActivity);
1115         ArrayList<View> viewList;
1116 
1117         // view is not focusable
1118         assertFalse(view.isFocusable());
1119         viewList = view.getFocusables(0);
1120         assertEquals(0, viewList.size());
1121 
1122         // view is focusable
1123         view.setFocusable(true);
1124         viewList = view.getFocusables(0);
1125         assertEquals(1, viewList.size());
1126         assertEquals(view, viewList.get(0));
1127 
1128         viewList = view.getFocusables(-1);
1129         assertEquals(1, viewList.size());
1130         assertEquals(view, viewList.get(0));
1131     }
1132 
testAddFocusablesWithoutTouchMode()1133     public void testAddFocusablesWithoutTouchMode() {
1134         View view = new View(mActivity);
1135         assertFalse("test sanity", view.isInTouchMode());
1136         focusableInTouchModeTest(view, false);
1137     }
1138 
testAddFocusablesInTouchMode()1139     public void testAddFocusablesInTouchMode() {
1140         View view = spy(new View(mActivity));
1141         when(view.isInTouchMode()).thenReturn(true);
1142         focusableInTouchModeTest(view, true);
1143     }
1144 
focusableInTouchModeTest(View view, boolean inTouchMode)1145     private void focusableInTouchModeTest(View view, boolean inTouchMode) {
1146         ArrayList<View> views = new ArrayList<View>();
1147 
1148         view.setFocusableInTouchMode(false);
1149         view.setFocusable(true);
1150 
1151         view.addFocusables(views, View.FOCUS_FORWARD);
1152         if (inTouchMode) {
1153             assertEquals(Collections.emptyList(), views);
1154         } else {
1155             assertEquals(Collections.singletonList(view), views);
1156         }
1157 
1158 
1159         views.clear();
1160         view.addFocusables(views, View.FOCUS_FORWARD, View.FOCUSABLES_ALL);
1161         assertEquals(Collections.singletonList(view), views);
1162 
1163         views.clear();
1164         view.addFocusables(views, View.FOCUS_FORWARD, View.FOCUSABLES_TOUCH_MODE);
1165         assertEquals(Collections.emptyList(), views);
1166 
1167         view.setFocusableInTouchMode(true);
1168 
1169         views.clear();
1170         view.addFocusables(views, View.FOCUS_FORWARD);
1171         assertEquals(Collections.singletonList(view), views);
1172 
1173         views.clear();
1174         view.addFocusables(views, View.FOCUS_FORWARD, View.FOCUSABLES_ALL);
1175         assertEquals(Collections.singletonList(view), views);
1176 
1177         views.clear();
1178         view.addFocusables(views, View.FOCUS_FORWARD, View.FOCUSABLES_TOUCH_MODE);
1179         assertEquals(Collections.singletonList(view), views);
1180 
1181         view.setFocusable(false);
1182 
1183         views.clear();
1184         view.addFocusables(views, View.FOCUS_FORWARD);
1185         assertEquals(Collections.emptyList(), views);
1186 
1187         views.clear();
1188         view.addFocusables(views, View.FOCUS_FORWARD, View.FOCUSABLES_ALL);
1189         assertEquals(Collections.emptyList(), views);
1190 
1191         views.clear();
1192         view.addFocusables(views, View.FOCUS_FORWARD, View.FOCUSABLES_TOUCH_MODE);
1193         assertEquals(Collections.emptyList(), views);
1194     }
1195 
testGetRootView()1196     public void testGetRootView() {
1197         MockView view = new MockView(mActivity);
1198 
1199         assertNull(view.getParent());
1200         assertEquals(view, view.getRootView());
1201 
1202         view.setParent(mMockParent);
1203         assertEquals(mMockParent, view.getRootView());
1204     }
1205 
testGetSolidColor()1206     public void testGetSolidColor() {
1207         View view = new View(mActivity);
1208 
1209         assertEquals(0, view.getSolidColor());
1210     }
1211 
testSetMinimumWidth()1212     public void testSetMinimumWidth() {
1213         MockView view = new MockView(mActivity);
1214         assertEquals(0, view.getSuggestedMinimumWidth());
1215 
1216         view.setMinimumWidth(100);
1217         assertEquals(100, view.getSuggestedMinimumWidth());
1218 
1219         view.setMinimumWidth(-100);
1220         assertEquals(-100, view.getSuggestedMinimumWidth());
1221     }
1222 
testGetSuggestedMinimumWidth()1223     public void testGetSuggestedMinimumWidth() {
1224         MockView view = new MockView(mActivity);
1225         Drawable d = mResources.getDrawable(R.drawable.scenery);
1226         int drawableMinimumWidth = d.getMinimumWidth();
1227 
1228         // drawable is null
1229         view.setMinimumWidth(100);
1230         assertNull(view.getBackground());
1231         assertEquals(100, view.getSuggestedMinimumWidth());
1232 
1233         // drawable minimum width is larger than mMinWidth
1234         view.setBackgroundDrawable(d);
1235         view.setMinimumWidth(drawableMinimumWidth - 10);
1236         assertEquals(drawableMinimumWidth, view.getSuggestedMinimumWidth());
1237 
1238         // drawable minimum width is smaller than mMinWidth
1239         view.setMinimumWidth(drawableMinimumWidth + 10);
1240         assertEquals(drawableMinimumWidth + 10, view.getSuggestedMinimumWidth());
1241     }
1242 
testSetMinimumHeight()1243     public void testSetMinimumHeight() {
1244         MockView view = new MockView(mActivity);
1245         assertEquals(0, view.getSuggestedMinimumHeight());
1246 
1247         view.setMinimumHeight(100);
1248         assertEquals(100, view.getSuggestedMinimumHeight());
1249 
1250         view.setMinimumHeight(-100);
1251         assertEquals(-100, view.getSuggestedMinimumHeight());
1252     }
1253 
testGetSuggestedMinimumHeight()1254     public void testGetSuggestedMinimumHeight() {
1255         MockView view = new MockView(mActivity);
1256         Drawable d = mResources.getDrawable(R.drawable.scenery);
1257         int drawableMinimumHeight = d.getMinimumHeight();
1258 
1259         // drawable is null
1260         view.setMinimumHeight(100);
1261         assertNull(view.getBackground());
1262         assertEquals(100, view.getSuggestedMinimumHeight());
1263 
1264         // drawable minimum height is larger than mMinHeight
1265         view.setBackgroundDrawable(d);
1266         view.setMinimumHeight(drawableMinimumHeight - 10);
1267         assertEquals(drawableMinimumHeight, view.getSuggestedMinimumHeight());
1268 
1269         // drawable minimum height is smaller than mMinHeight
1270         view.setMinimumHeight(drawableMinimumHeight + 10);
1271         assertEquals(drawableMinimumHeight + 10, view.getSuggestedMinimumHeight());
1272     }
1273 
testAccessWillNotCacheDrawing()1274     public void testAccessWillNotCacheDrawing() {
1275         View view = new View(mActivity);
1276 
1277         assertFalse(view.willNotCacheDrawing());
1278 
1279         view.setWillNotCacheDrawing(true);
1280         assertTrue(view.willNotCacheDrawing());
1281     }
1282 
testAccessDrawingCacheEnabled()1283     public void testAccessDrawingCacheEnabled() {
1284         View view = new View(mActivity);
1285 
1286         assertFalse(view.isDrawingCacheEnabled());
1287 
1288         view.setDrawingCacheEnabled(true);
1289         assertTrue(view.isDrawingCacheEnabled());
1290     }
1291 
testGetDrawingCache()1292     public void testGetDrawingCache() {
1293         MockView view = new MockView(mActivity);
1294 
1295         // should not call buildDrawingCache when getDrawingCache
1296         assertNull(view.getDrawingCache());
1297 
1298         // should call buildDrawingCache when getDrawingCache
1299         view = (MockView) mActivity.findViewById(R.id.mock_view);
1300         view.setDrawingCacheEnabled(true);
1301         Bitmap bitmap1 = view.getDrawingCache();
1302         assertNotNull(bitmap1);
1303         assertEquals(view.getWidth(), bitmap1.getWidth());
1304         assertEquals(view.getHeight(), bitmap1.getHeight());
1305 
1306         view.setWillNotCacheDrawing(true);
1307         assertNull(view.getDrawingCache());
1308 
1309         view.setWillNotCacheDrawing(false);
1310         // build a new drawingcache
1311         Bitmap bitmap2 = view.getDrawingCache();
1312         assertNotSame(bitmap1, bitmap2);
1313     }
1314 
testBuildAndDestroyDrawingCache()1315     public void testBuildAndDestroyDrawingCache() {
1316         MockView view = (MockView) mActivity.findViewById(R.id.mock_view);
1317 
1318         assertNull(view.getDrawingCache());
1319 
1320         view.buildDrawingCache();
1321         Bitmap bitmap = view.getDrawingCache();
1322         assertNotNull(bitmap);
1323         assertEquals(view.getWidth(), bitmap.getWidth());
1324         assertEquals(view.getHeight(), bitmap.getHeight());
1325 
1326         view.destroyDrawingCache();
1327         assertNull(view.getDrawingCache());
1328     }
1329 
testAccessWillNotDraw()1330     public void testAccessWillNotDraw() {
1331         View view = new View(mActivity);
1332 
1333         assertFalse(view.willNotDraw());
1334 
1335         view.setWillNotDraw(true);
1336         assertTrue(view.willNotDraw());
1337     }
1338 
testAccessDrawingCacheQuality()1339     public void testAccessDrawingCacheQuality() {
1340         View view = new View(mActivity);
1341 
1342         assertEquals(0, view.getDrawingCacheQuality());
1343 
1344         view.setDrawingCacheQuality(1);
1345         assertEquals(0, view.getDrawingCacheQuality());
1346 
1347         view.setDrawingCacheQuality(0x00100000);
1348         assertEquals(0x00100000, view.getDrawingCacheQuality());
1349 
1350         view.setDrawingCacheQuality(0x00080000);
1351         assertEquals(0x00080000, view.getDrawingCacheQuality());
1352 
1353         view.setDrawingCacheQuality(0xffffffff);
1354         // 0x00180000 is View.DRAWING_CACHE_QUALITY_MASK
1355         assertEquals(0x00180000, view.getDrawingCacheQuality());
1356     }
1357 
testDispatchSetSelected()1358     public void testDispatchSetSelected() {
1359         MockView mockView1 = new MockView(mActivity);
1360         MockView mockView2 = new MockView(mActivity);
1361         mockView1.setParent(mMockParent);
1362         mockView2.setParent(mMockParent);
1363 
1364         mMockParent.dispatchSetSelected(true);
1365         assertTrue(mockView1.isSelected());
1366         assertTrue(mockView2.isSelected());
1367 
1368         mMockParent.dispatchSetSelected(false);
1369         assertFalse(mockView1.isSelected());
1370         assertFalse(mockView2.isSelected());
1371     }
1372 
testAccessSelected()1373     public void testAccessSelected() {
1374         View view = new View(mActivity);
1375 
1376         assertFalse(view.isSelected());
1377 
1378         view.setSelected(true);
1379         assertTrue(view.isSelected());
1380     }
1381 
testDispatchSetPressed()1382     public void testDispatchSetPressed() {
1383         MockView mockView1 = new MockView(mActivity);
1384         MockView mockView2 = new MockView(mActivity);
1385         mockView1.setParent(mMockParent);
1386         mockView2.setParent(mMockParent);
1387 
1388         mMockParent.dispatchSetPressed(true);
1389         assertTrue(mockView1.isPressed());
1390         assertTrue(mockView2.isPressed());
1391 
1392         mMockParent.dispatchSetPressed(false);
1393         assertFalse(mockView1.isPressed());
1394         assertFalse(mockView2.isPressed());
1395     }
1396 
testAccessPressed()1397     public void testAccessPressed() {
1398         View view = new View(mActivity);
1399 
1400         assertFalse(view.isPressed());
1401 
1402         view.setPressed(true);
1403         assertTrue(view.isPressed());
1404     }
1405 
testAccessSoundEffectsEnabled()1406     public void testAccessSoundEffectsEnabled() {
1407         View view = new View(mActivity);
1408 
1409         assertTrue(view.isSoundEffectsEnabled());
1410 
1411         view.setSoundEffectsEnabled(false);
1412         assertFalse(view.isSoundEffectsEnabled());
1413     }
1414 
testAccessKeepScreenOn()1415     public void testAccessKeepScreenOn() {
1416         View view = new View(mActivity);
1417 
1418         assertFalse(view.getKeepScreenOn());
1419 
1420         view.setKeepScreenOn(true);
1421         assertTrue(view.getKeepScreenOn());
1422     }
1423 
testAccessDuplicateParentStateEnabled()1424     public void testAccessDuplicateParentStateEnabled() {
1425         View view = new View(mActivity);
1426 
1427         assertFalse(view.isDuplicateParentStateEnabled());
1428 
1429         view.setDuplicateParentStateEnabled(true);
1430         assertTrue(view.isDuplicateParentStateEnabled());
1431     }
1432 
testAccessEnabled()1433     public void testAccessEnabled() {
1434         View view = new View(mActivity);
1435 
1436         assertTrue(view.isEnabled());
1437 
1438         view.setEnabled(false);
1439         assertFalse(view.isEnabled());
1440     }
1441 
testAccessSaveEnabled()1442     public void testAccessSaveEnabled() {
1443         View view = new View(mActivity);
1444 
1445         assertTrue(view.isSaveEnabled());
1446 
1447         view.setSaveEnabled(false);
1448         assertFalse(view.isSaveEnabled());
1449     }
1450 
testShowContextMenu()1451     public void testShowContextMenu() {
1452         MockView view = new MockView(mActivity);
1453 
1454         assertNull(view.getParent());
1455         try {
1456             view.showContextMenu();
1457             fail("should throw NullPointerException");
1458         } catch (NullPointerException e) {
1459         }
1460 
1461         view.setParent(mMockParent);
1462         assertFalse(mMockParent.hasShowContextMenuForChild());
1463 
1464         assertFalse(view.showContextMenu());
1465         assertTrue(mMockParent.hasShowContextMenuForChild());
1466     }
1467 
testShowContextMenuXY()1468     public void testShowContextMenuXY() {
1469         MockViewParent parent = new MockViewParent(mActivity);
1470         MockView view = new MockView(mActivity);
1471 
1472         assertNull(view.getParent());
1473         try {
1474             view.showContextMenu(0, 0);
1475             fail("should throw NullPointerException");
1476         } catch (NullPointerException e) {
1477         }
1478 
1479         view.setParent(parent);
1480         assertFalse(parent.hasShowContextMenuForChildXY());
1481 
1482         assertFalse(view.showContextMenu(0, 0));
1483         assertTrue(parent.hasShowContextMenuForChildXY());
1484     }
1485 
testFitSystemWindows()1486     public void testFitSystemWindows() {
1487         final XmlResourceParser parser = mResources.getLayout(R.layout.view_layout);
1488         final AttributeSet attrs = Xml.asAttributeSet(parser);
1489         Rect insets = new Rect(10, 20, 30, 50);
1490 
1491         MockView view = new MockView(mActivity);
1492         assertFalse(view.fitSystemWindows(insets));
1493         assertFalse(view.fitSystemWindows(null));
1494 
1495         view = new MockView(mActivity, attrs, android.R.attr.fitsSystemWindows);
1496         assertFalse(view.fitSystemWindows(insets));
1497         assertFalse(view.fitSystemWindows(null));
1498     }
1499 
testPerformClick()1500     public void testPerformClick() {
1501         View view = new View(mActivity);
1502         OnClickListenerImpl listener = new OnClickListenerImpl();
1503 
1504         assertFalse(view.performClick());
1505 
1506         assertFalse(listener.hasOnClick());
1507         view.setOnClickListener(listener);
1508 
1509         assertTrue(view.performClick());
1510         assertTrue(listener.hasOnClick());
1511 
1512         view.setOnClickListener(null);
1513         assertFalse(view.performClick());
1514     }
1515 
testSetOnClickListener()1516     public void testSetOnClickListener() {
1517         View view = new View(mActivity);
1518         assertFalse(view.performClick());
1519         assertFalse(view.isClickable());
1520 
1521         view.setOnClickListener(null);
1522         assertFalse(view.performClick());
1523         assertTrue(view.isClickable());
1524 
1525         view.setOnClickListener(new OnClickListenerImpl());
1526         assertTrue(view.performClick());
1527         assertTrue(view.isClickable());
1528     }
1529 
testPerformLongClick()1530     public void testPerformLongClick() {
1531         MockView view = new MockView(mActivity);
1532         OnLongClickListenerImpl listener = new OnLongClickListenerImpl();
1533 
1534         try {
1535             view.performLongClick();
1536             fail("should throw NullPointerException");
1537         } catch (NullPointerException e) {
1538         }
1539 
1540         view.setParent(mMockParent);
1541         assertFalse(mMockParent.hasShowContextMenuForChild());
1542         assertFalse(view.performLongClick());
1543         assertTrue(mMockParent.hasShowContextMenuForChild());
1544 
1545         view.setOnLongClickListener(listener);
1546         mMockParent.reset();
1547         assertFalse(mMockParent.hasShowContextMenuForChild());
1548         assertFalse(listener.hasOnLongClick());
1549         assertTrue(view.performLongClick());
1550         assertFalse(mMockParent.hasShowContextMenuForChild());
1551         assertTrue(listener.hasOnLongClick());
1552     }
1553 
testPerformLongClickXY()1554     public void testPerformLongClickXY() {
1555         MockViewParent parent = new MockViewParent(mActivity);
1556         MockView view = new MockView(mActivity);
1557 
1558         try {
1559             view.performLongClick(0, 0);
1560             fail("should throw NullPointerException");
1561         } catch (NullPointerException e) {
1562         }
1563 
1564         parent.addView(view);
1565         assertFalse(parent.hasShowContextMenuForChildXY());
1566 
1567         // Verify default context menu behavior.
1568         assertFalse(view.performLongClick(0, 0));
1569         assertTrue(parent.hasShowContextMenuForChildXY());
1570     }
1571 
testPerformLongClickXY_WithListener()1572     public void testPerformLongClickXY_WithListener() {
1573         OnLongClickListener listener = mock(OnLongClickListener.class);
1574         when(listener.onLongClick(any(View.class))).thenReturn(true);
1575 
1576         MockViewParent parent = new MockViewParent(mActivity);
1577         MockView view = new MockView(mActivity);
1578 
1579         view.setOnLongClickListener(listener);
1580         verify(listener, never()).onLongClick(any(View.class));
1581 
1582         parent.addView(view);
1583         assertFalse(parent.hasShowContextMenuForChildXY());
1584 
1585         // Verify listener is preferred over default context menu.
1586         assertTrue(view.performLongClick(0, 0));
1587         assertFalse(parent.hasShowContextMenuForChildXY());
1588         verify(listener).onLongClick(view);
1589     }
1590 
testSetOnLongClickListener()1591     public void testSetOnLongClickListener() {
1592         MockView view = new MockView(mActivity);
1593         view.setParent(mMockParent);
1594         assertFalse(view.performLongClick());
1595         assertFalse(view.isLongClickable());
1596 
1597         view.setOnLongClickListener(null);
1598         assertFalse(view.performLongClick());
1599         assertTrue(view.isLongClickable());
1600 
1601         view.setOnLongClickListener(new OnLongClickListenerImpl());
1602         assertTrue(view.performLongClick());
1603         assertTrue(view.isLongClickable());
1604     }
1605 
testPerformContextClick()1606     public void testPerformContextClick() {
1607         MockView view = new MockView(mActivity);
1608         view.setParent(mMockParent);
1609         OnContextClickListenerImpl listener = new OnContextClickListenerImpl();
1610 
1611         view.setOnContextClickListener(listener);
1612         assertFalse(listener.hasOnContextClick());
1613 
1614         assertTrue(view.performContextClick());
1615         assertTrue(listener.hasOnContextClick());
1616         assertSame(view, listener.getLastViewContextClicked());
1617     }
1618 
testSetOnContextClickListener()1619     public void testSetOnContextClickListener() {
1620         MockView view = new MockView(mActivity);
1621         view.setParent(mMockParent);
1622 
1623         assertFalse(view.performContextClick());
1624         assertFalse(view.isContextClickable());
1625 
1626         view.setOnContextClickListener(new OnContextClickListenerImpl());
1627         assertTrue(view.performContextClick());
1628         assertTrue(view.isContextClickable());
1629     }
1630 
testAccessOnFocusChangeListener()1631     public void testAccessOnFocusChangeListener() {
1632         View view = new View(mActivity);
1633         OnFocusChangeListener listener = new OnFocusChangeListenerImpl();
1634 
1635         assertNull(view.getOnFocusChangeListener());
1636 
1637         view.setOnFocusChangeListener(listener);
1638         assertSame(listener, view.getOnFocusChangeListener());
1639     }
1640 
testAccessNextFocusUpId()1641     public void testAccessNextFocusUpId() {
1642         View view = new View(mActivity);
1643 
1644         assertEquals(View.NO_ID, view.getNextFocusUpId());
1645 
1646         view.setNextFocusUpId(1);
1647         assertEquals(1, view.getNextFocusUpId());
1648 
1649         view.setNextFocusUpId(Integer.MAX_VALUE);
1650         assertEquals(Integer.MAX_VALUE, view.getNextFocusUpId());
1651 
1652         view.setNextFocusUpId(Integer.MIN_VALUE);
1653         assertEquals(Integer.MIN_VALUE, view.getNextFocusUpId());
1654     }
1655 
testAccessNextFocusDownId()1656     public void testAccessNextFocusDownId() {
1657         View view = new View(mActivity);
1658 
1659         assertEquals(View.NO_ID, view.getNextFocusDownId());
1660 
1661         view.setNextFocusDownId(1);
1662         assertEquals(1, view.getNextFocusDownId());
1663 
1664         view.setNextFocusDownId(Integer.MAX_VALUE);
1665         assertEquals(Integer.MAX_VALUE, view.getNextFocusDownId());
1666 
1667         view.setNextFocusDownId(Integer.MIN_VALUE);
1668         assertEquals(Integer.MIN_VALUE, view.getNextFocusDownId());
1669     }
1670 
testAccessNextFocusLeftId()1671     public void testAccessNextFocusLeftId() {
1672         View view = new View(mActivity);
1673 
1674         assertEquals(View.NO_ID, view.getNextFocusLeftId());
1675 
1676         view.setNextFocusLeftId(1);
1677         assertEquals(1, view.getNextFocusLeftId());
1678 
1679         view.setNextFocusLeftId(Integer.MAX_VALUE);
1680         assertEquals(Integer.MAX_VALUE, view.getNextFocusLeftId());
1681 
1682         view.setNextFocusLeftId(Integer.MIN_VALUE);
1683         assertEquals(Integer.MIN_VALUE, view.getNextFocusLeftId());
1684     }
1685 
testAccessNextFocusRightId()1686     public void testAccessNextFocusRightId() {
1687         View view = new View(mActivity);
1688 
1689         assertEquals(View.NO_ID, view.getNextFocusRightId());
1690 
1691         view.setNextFocusRightId(1);
1692         assertEquals(1, view.getNextFocusRightId());
1693 
1694         view.setNextFocusRightId(Integer.MAX_VALUE);
1695         assertEquals(Integer.MAX_VALUE, view.getNextFocusRightId());
1696 
1697         view.setNextFocusRightId(Integer.MIN_VALUE);
1698         assertEquals(Integer.MIN_VALUE, view.getNextFocusRightId());
1699     }
1700 
testAccessMeasuredDimension()1701     public void testAccessMeasuredDimension() {
1702         MockView view = new MockView(mActivity);
1703         assertEquals(0, view.getMeasuredWidth());
1704         assertEquals(0, view.getMeasuredHeight());
1705 
1706         view.setMeasuredDimensionWrapper(20, 30);
1707         assertEquals(20, view.getMeasuredWidth());
1708         assertEquals(30, view.getMeasuredHeight());
1709     }
1710 
testMeasure()1711     public void testMeasure() throws Throwable {
1712         final MockView view = (MockView) mActivity.findViewById(R.id.mock_view);
1713         assertTrue(view.hasCalledOnMeasure());
1714         assertEquals(100, view.getMeasuredWidth());
1715         assertEquals(200, view.getMeasuredHeight());
1716 
1717         view.reset();
1718         runTestOnUiThread(new Runnable() {
1719             @Override
1720             public void run() {
1721                 view.requestLayout();
1722             }
1723         });
1724         getInstrumentation().waitForIdleSync();
1725         assertTrue(view.hasCalledOnMeasure());
1726         assertEquals(100, view.getMeasuredWidth());
1727         assertEquals(200, view.getMeasuredHeight());
1728 
1729         view.reset();
1730         final LinearLayout.LayoutParams layoutParams = new LinearLayout.LayoutParams(200, 100);
1731         runTestOnUiThread(new Runnable() {
1732             @Override
1733             public void run() {
1734                 view.setLayoutParams(layoutParams);
1735             }
1736         });
1737         getInstrumentation().waitForIdleSync();
1738         assertTrue(view.hasCalledOnMeasure());
1739         assertEquals(200, view.getMeasuredWidth());
1740         assertEquals(100, view.getMeasuredHeight());
1741     }
1742 
testAccessLayoutParams()1743     public void testAccessLayoutParams() {
1744         View view = new View(mActivity);
1745         ViewGroup.LayoutParams params = new ViewGroup.LayoutParams(10, 20);
1746 
1747         assertNull(view.getLayoutParams());
1748 
1749         try {
1750             view.setLayoutParams(null);
1751             fail("should throw NullPointerException");
1752         } catch (NullPointerException e) {
1753         }
1754 
1755         assertFalse(view.isLayoutRequested());
1756         view.setLayoutParams(params);
1757         assertSame(params, view.getLayoutParams());
1758         assertTrue(view.isLayoutRequested());
1759     }
1760 
testIsShown()1761     public void testIsShown() {
1762         MockView view = new MockView(mActivity);
1763 
1764         view.setVisibility(View.INVISIBLE);
1765         assertFalse(view.isShown());
1766 
1767         view.setVisibility(View.VISIBLE);
1768         assertNull(view.getParent());
1769         assertFalse(view.isShown());
1770 
1771         view.setParent(mMockParent);
1772         // mMockParent is not a instance of ViewRoot
1773         assertFalse(view.isShown());
1774     }
1775 
testGetDrawingTime()1776     public void testGetDrawingTime() {
1777         View view = new View(mActivity);
1778         // mAttachInfo is null
1779         assertEquals(0, view.getDrawingTime());
1780 
1781         // mAttachInfo is not null
1782         view = mActivity.findViewById(R.id.fit_windows);
1783         assertEquals(SystemClock.uptimeMillis(), view.getDrawingTime(), 1000);
1784     }
1785 
testScheduleDrawable()1786     public void testScheduleDrawable() {
1787         View view = new View(mActivity);
1788         Drawable drawable = new StateListDrawable();
1789         Runnable what = new Runnable() {
1790             @Override
1791             public void run() {
1792                 // do nothing
1793             }
1794         };
1795 
1796         // mAttachInfo is null
1797         view.scheduleDrawable(drawable, what, 1000);
1798 
1799         view.setBackgroundDrawable(drawable);
1800         view.scheduleDrawable(drawable, what, 1000);
1801 
1802         view.scheduleDrawable(null, null, -1000);
1803 
1804         // mAttachInfo is not null
1805         view = mActivity.findViewById(R.id.fit_windows);
1806         view.scheduleDrawable(drawable, what, 1000);
1807 
1808         view.scheduleDrawable(view.getBackground(), what, 1000);
1809         view.unscheduleDrawable(view.getBackground(), what);
1810 
1811         view.scheduleDrawable(null, null, -1000);
1812     }
1813 
testUnscheduleDrawable()1814     public void testUnscheduleDrawable() {
1815         View view = new View(mActivity);
1816         Drawable drawable = new StateListDrawable();
1817         Runnable what = new Runnable() {
1818             @Override
1819             public void run() {
1820                 // do nothing
1821             }
1822         };
1823 
1824         // mAttachInfo is null
1825         view.unscheduleDrawable(drawable, what);
1826 
1827         view.setBackgroundDrawable(drawable);
1828         view.unscheduleDrawable(drawable);
1829 
1830         view.unscheduleDrawable(null, null);
1831         view.unscheduleDrawable(null);
1832 
1833         // mAttachInfo is not null
1834         view = mActivity.findViewById(R.id.fit_windows);
1835         view.unscheduleDrawable(drawable);
1836 
1837         view.scheduleDrawable(view.getBackground(), what, 1000);
1838         view.unscheduleDrawable(view.getBackground(), what);
1839 
1840         view.unscheduleDrawable(null);
1841         view.unscheduleDrawable(null, null);
1842     }
1843 
testGetWindowVisibility()1844     public void testGetWindowVisibility() {
1845         View view = new View(mActivity);
1846         // mAttachInfo is null
1847         assertEquals(View.GONE, view.getWindowVisibility());
1848 
1849         // mAttachInfo is not null
1850         view = mActivity.findViewById(R.id.fit_windows);
1851         assertEquals(View.VISIBLE, view.getWindowVisibility());
1852     }
1853 
testGetWindowToken()1854     public void testGetWindowToken() {
1855         View view = new View(mActivity);
1856         // mAttachInfo is null
1857         assertNull(view.getWindowToken());
1858 
1859         // mAttachInfo is not null
1860         view = mActivity.findViewById(R.id.fit_windows);
1861         assertNotNull(view.getWindowToken());
1862     }
1863 
testHasWindowFocus()1864     public void testHasWindowFocus() {
1865         View view = new View(mActivity);
1866         // mAttachInfo is null
1867         assertFalse(view.hasWindowFocus());
1868 
1869         // mAttachInfo is not null
1870         final View view2 = mActivity.findViewById(R.id.fit_windows);
1871         // Wait until the window has been focused.
1872         new PollingCheck(TIMEOUT_DELTA) {
1873             @Override
1874             protected boolean check() {
1875                 return view2.hasWindowFocus();
1876             }
1877         }.run();
1878     }
1879 
testGetHandler()1880     public void testGetHandler() {
1881         MockView view = new MockView(mActivity);
1882         // mAttachInfo is null
1883         assertNull(view.getHandler());
1884     }
1885 
testRemoveCallbacks()1886     public void testRemoveCallbacks() throws InterruptedException {
1887         final long delay = 500L;
1888         View view = mActivity.findViewById(R.id.mock_view);
1889         MockRunnable runner = new MockRunnable();
1890         assertTrue(view.postDelayed(runner, delay));
1891         assertTrue(view.removeCallbacks(runner));
1892         assertTrue(view.removeCallbacks(null));
1893         assertTrue(view.removeCallbacks(new MockRunnable()));
1894         Thread.sleep(delay * 2);
1895         assertFalse(runner.hasRun);
1896         // check that the runner actually works
1897         runner = new MockRunnable();
1898         assertTrue(view.postDelayed(runner, delay));
1899         Thread.sleep(delay * 2);
1900         assertTrue(runner.hasRun);
1901     }
1902 
testCancelLongPress()1903     public void testCancelLongPress() {
1904         View view = new View(mActivity);
1905         // mAttachInfo is null
1906         view.cancelLongPress();
1907 
1908         // mAttachInfo is not null
1909         view = mActivity.findViewById(R.id.fit_windows);
1910         view.cancelLongPress();
1911     }
1912 
testGetViewTreeObserver()1913     public void testGetViewTreeObserver() {
1914         View view = new View(mActivity);
1915         // mAttachInfo is null
1916         assertNotNull(view.getViewTreeObserver());
1917 
1918         // mAttachInfo is not null
1919         view = mActivity.findViewById(R.id.fit_windows);
1920         assertNotNull(view.getViewTreeObserver());
1921     }
1922 
testGetWindowAttachCount()1923     public void testGetWindowAttachCount() {
1924         MockView view = new MockView(mActivity);
1925         // mAttachInfo is null
1926         assertEquals(0, view.getWindowAttachCount());
1927     }
1928 
1929     @UiThreadTest
testOnAttachedToAndDetachedFromWindow()1930     public void testOnAttachedToAndDetachedFromWindow() {
1931         MockView mockView = new MockView(mActivity);
1932         ViewGroup viewGroup = (ViewGroup) mActivity.findViewById(R.id.viewlayout_root);
1933 
1934         viewGroup.addView(mockView);
1935         assertTrue(mockView.hasCalledOnAttachedToWindow());
1936 
1937         viewGroup.removeView(mockView);
1938         assertTrue(mockView.hasCalledOnDetachedFromWindow());
1939 
1940         mockView.reset();
1941         mActivity.setContentView(mockView);
1942         assertTrue(mockView.hasCalledOnAttachedToWindow());
1943 
1944         mActivity.setContentView(R.layout.view_layout);
1945         assertTrue(mockView.hasCalledOnDetachedFromWindow());
1946     }
1947 
testGetLocationInWindow()1948     public void testGetLocationInWindow() {
1949         int[] location = new int[] { -1, -1 };
1950 
1951         View layout = mActivity.findViewById(R.id.viewlayout_root);
1952         int[] layoutLocation = new int[] { -1, -1 };
1953         layout.getLocationInWindow(layoutLocation);
1954 
1955         final View mockView = mActivity.findViewById(R.id.mock_view);
1956         mockView.getLocationInWindow(location);
1957         assertEquals(layoutLocation[0], location[0]);
1958         assertEquals(layoutLocation[1], location[1]);
1959 
1960         View scrollView = mActivity.findViewById(R.id.scroll_view);
1961         scrollView.getLocationInWindow(location);
1962         assertEquals(layoutLocation[0], location[0]);
1963         assertEquals(layoutLocation[1] + mockView.getHeight(), location[1]);
1964 
1965         try {
1966             mockView.getLocationInWindow(null);
1967             fail("should throw IllegalArgumentException");
1968         } catch (IllegalArgumentException e) {
1969         }
1970 
1971         try {
1972             mockView.getLocationInWindow(new int[] { 0 });
1973             fail("should throw IllegalArgumentException");
1974         } catch (IllegalArgumentException e) {
1975         }
1976     }
1977 
testGetLocationOnScreen()1978     public void testGetLocationOnScreen() {
1979         int[] location = new int[] { -1, -1 };
1980 
1981         // mAttachInfo is not null
1982         View layout = mActivity.findViewById(R.id.viewlayout_root);
1983         int[] layoutLocation = new int[] { -1, -1 };
1984         layout.getLocationOnScreen(layoutLocation);
1985 
1986         View mockView = mActivity.findViewById(R.id.mock_view);
1987         mockView.getLocationOnScreen(location);
1988         assertEquals(layoutLocation[0], location[0]);
1989         assertEquals(layoutLocation[1], location[1]);
1990 
1991         View scrollView = mActivity.findViewById(R.id.scroll_view);
1992         scrollView.getLocationOnScreen(location);
1993         assertEquals(layoutLocation[0], location[0]);
1994         assertEquals(layoutLocation[1] + mockView.getHeight(), location[1]);
1995 
1996         try {
1997             scrollView.getLocationOnScreen(null);
1998             fail("should throw IllegalArgumentException");
1999         } catch (IllegalArgumentException e) {
2000         }
2001 
2002         try {
2003             scrollView.getLocationOnScreen(new int[] { 0 });
2004             fail("should throw IllegalArgumentException");
2005         } catch (IllegalArgumentException e) {
2006         }
2007     }
2008 
testAddTouchables()2009     public void testAddTouchables() {
2010         View view = new View(mActivity);
2011         ArrayList<View> result = new ArrayList<>();
2012         assertEquals(0, result.size());
2013 
2014         view.addTouchables(result);
2015         assertEquals(0, result.size());
2016 
2017         view.setClickable(true);
2018         view.addTouchables(result);
2019         assertEquals(1, result.size());
2020         assertSame(view, result.get(0));
2021 
2022         try {
2023             view.addTouchables(null);
2024             fail("should throw NullPointerException");
2025         } catch (NullPointerException e) {
2026         }
2027 
2028         result.clear();
2029         view.setEnabled(false);
2030         assertTrue(view.isClickable());
2031         view.addTouchables(result);
2032         assertEquals(0, result.size());
2033     }
2034 
testGetTouchables()2035     public void testGetTouchables() {
2036         View view = new View(mActivity);
2037         ArrayList<View> result;
2038 
2039         result = view.getTouchables();
2040         assertEquals(0, result.size());
2041 
2042         view.setClickable(true);
2043         result = view.getTouchables();
2044         assertEquals(1, result.size());
2045         assertSame(view, result.get(0));
2046 
2047         result.clear();
2048         view.setEnabled(false);
2049         assertTrue(view.isClickable());
2050         result = view.getTouchables();
2051         assertEquals(0, result.size());
2052     }
2053 
testInflate()2054     public void testInflate() {
2055         View view = View.inflate(mActivity, R.layout.view_layout, null);
2056         assertNotNull(view);
2057         assertTrue(view instanceof LinearLayout);
2058 
2059         MockView mockView = (MockView) view.findViewById(R.id.mock_view);
2060         assertNotNull(mockView);
2061         assertTrue(mockView.hasCalledOnFinishInflate());
2062     }
2063 
testIsInTouchMode()2064     public void testIsInTouchMode() {
2065         View view = new View(mActivity);
2066         // mAttachInfo is null
2067         assertFalse(view.isInTouchMode());
2068 
2069         // mAttachInfo is not null
2070         view = mActivity.findViewById(R.id.fit_windows);
2071         assertFalse(view.isInTouchMode());
2072     }
2073 
testIsInEditMode()2074     public void testIsInEditMode() {
2075         View view = new View(mActivity);
2076         assertFalse(view.isInEditMode());
2077     }
2078 
testPostInvalidate1()2079     public void testPostInvalidate1() {
2080         View view = new View(mActivity);
2081         // mAttachInfo is null
2082         view.postInvalidate();
2083 
2084         // mAttachInfo is not null
2085         view = mActivity.findViewById(R.id.fit_windows);
2086         view.postInvalidate();
2087     }
2088 
testPostInvalidate2()2089     public void testPostInvalidate2() {
2090         View view = new View(mActivity);
2091         // mAttachInfo is null
2092         view.postInvalidate(0, 1, 2, 3);
2093 
2094         // mAttachInfo is not null
2095         view = mActivity.findViewById(R.id.fit_windows);
2096         view.postInvalidate(10, 20, 30, 40);
2097         view.postInvalidate(0, -20, -30, -40);
2098     }
2099 
testPostInvalidateDelayed()2100     public void testPostInvalidateDelayed() {
2101         View view = new View(mActivity);
2102         // mAttachInfo is null
2103         view.postInvalidateDelayed(1000);
2104         view.postInvalidateDelayed(500, 0, 0, 100, 200);
2105 
2106         // mAttachInfo is not null
2107         view = mActivity.findViewById(R.id.fit_windows);
2108         view.postInvalidateDelayed(1000);
2109         view.postInvalidateDelayed(500, 0, 0, 100, 200);
2110         view.postInvalidateDelayed(-1);
2111     }
2112 
testPost()2113     public void testPost() {
2114         View view = new View(mActivity);
2115         MockRunnable action = new MockRunnable();
2116 
2117         // mAttachInfo is null
2118         assertTrue(view.post(action));
2119         assertTrue(view.post(null));
2120 
2121         // mAttachInfo is not null
2122         view = mActivity.findViewById(R.id.fit_windows);
2123         assertTrue(view.post(action));
2124         assertTrue(view.post(null));
2125     }
2126 
testPostDelayed()2127     public void testPostDelayed() {
2128         View view = new View(mActivity);
2129         MockRunnable action = new MockRunnable();
2130 
2131         // mAttachInfo is null
2132         assertTrue(view.postDelayed(action, 1000));
2133         assertTrue(view.postDelayed(null, -1));
2134 
2135         // mAttachInfo is not null
2136         view = mActivity.findViewById(R.id.fit_windows);
2137         assertTrue(view.postDelayed(action, 1000));
2138         assertTrue(view.postDelayed(null, 0));
2139     }
2140 
2141     @UiThreadTest
testPlaySoundEffect()2142     public void testPlaySoundEffect() {
2143         MockView view = (MockView) mActivity.findViewById(R.id.mock_view);
2144         // sound effect enabled
2145         view.playSoundEffect(SoundEffectConstants.CLICK);
2146 
2147         // sound effect disabled
2148         view.setSoundEffectsEnabled(false);
2149         view.playSoundEffect(SoundEffectConstants.NAVIGATION_DOWN);
2150 
2151         // no way to assert the soundConstant be really played.
2152     }
2153 
testOnKeyShortcut()2154     public void testOnKeyShortcut() throws Throwable {
2155         final MockView view = (MockView) mActivity.findViewById(R.id.mock_view);
2156         runTestOnUiThread(new Runnable() {
2157             @Override
2158             public void run() {
2159                 view.setFocusable(true);
2160                 view.requestFocus();
2161             }
2162         });
2163         getInstrumentation().waitForIdleSync();
2164         assertTrue(view.isFocused());
2165 
2166         KeyEvent event = new KeyEvent(KeyEvent.ACTION_DOWN, KeyEvent.KEYCODE_MENU);
2167         getInstrumentation().sendKeySync(event);
2168         event = new KeyEvent(KeyEvent.ACTION_DOWN, KeyEvent.KEYCODE_0);
2169         getInstrumentation().sendKeySync(event);
2170         assertTrue(view.hasCalledOnKeyShortcut());
2171     }
2172 
testOnKeyMultiple()2173     public void testOnKeyMultiple() throws Throwable {
2174         final MockView view = (MockView) mActivity.findViewById(R.id.mock_view);
2175         runTestOnUiThread(new Runnable() {
2176             @Override
2177             public void run() {
2178                 view.setFocusable(true);
2179             }
2180         });
2181 
2182         assertFalse(view.hasCalledOnKeyMultiple());
2183         view.dispatchKeyEvent(new KeyEvent(KeyEvent.ACTION_MULTIPLE, KeyEvent.KEYCODE_ENTER));
2184         assertTrue(view.hasCalledOnKeyMultiple());
2185     }
2186 
2187     @UiThreadTest
testDispatchKeyShortcutEvent()2188     public void testDispatchKeyShortcutEvent() {
2189         MockView view = (MockView) mActivity.findViewById(R.id.mock_view);
2190         view.setFocusable(true);
2191 
2192         KeyEvent event = new KeyEvent(KeyEvent.ACTION_DOWN, KeyEvent.KEYCODE_0);
2193         view.dispatchKeyShortcutEvent(event);
2194         assertTrue(view.hasCalledOnKeyShortcut());
2195 
2196         try {
2197             view.dispatchKeyShortcutEvent(null);
2198             fail("should throw NullPointerException");
2199         } catch (NullPointerException e) {
2200         }
2201     }
2202 
testOnTrackballEvent()2203     public void testOnTrackballEvent() throws Throwable {
2204         final MockView view = (MockView) mActivity.findViewById(R.id.mock_view);
2205         runTestOnUiThread(new Runnable() {
2206             @Override
2207             public void run() {
2208                 view.setEnabled(true);
2209                 view.setFocusable(true);
2210                 view.requestFocus();
2211             }
2212         });
2213         getInstrumentation().waitForIdleSync();
2214 
2215         long downTime = SystemClock.uptimeMillis();
2216         long eventTime = downTime;
2217         MotionEvent event = MotionEvent.obtain(downTime, eventTime, MotionEvent.ACTION_MOVE,
2218                 1, 2, 0);
2219         getInstrumentation().sendTrackballEventSync(event);
2220         getInstrumentation().waitForIdleSync();
2221         assertTrue(view.hasCalledOnTrackballEvent());
2222     }
2223 
2224     @UiThreadTest
testDispatchTrackballMoveEvent()2225     public void testDispatchTrackballMoveEvent() {
2226         ViewGroup viewGroup = (ViewGroup) mActivity.findViewById(R.id.viewlayout_root);
2227         MockView mockView1 = new MockView(mActivity);
2228         MockView mockView2 = new MockView(mActivity);
2229         viewGroup.addView(mockView1);
2230         viewGroup.addView(mockView2);
2231         mockView1.setFocusable(true);
2232         mockView2.setFocusable(true);
2233         mockView2.requestFocus();
2234 
2235         long downTime = SystemClock.uptimeMillis();
2236         long eventTime = downTime;
2237         MotionEvent event = MotionEvent.obtain(downTime, eventTime, MotionEvent.ACTION_MOVE,
2238                 1, 2, 0);
2239         mockView1.dispatchTrackballEvent(event);
2240         // issue 1695243
2241         // It passes a trackball motion event down to itself even if it is not the focused view.
2242         assertTrue(mockView1.hasCalledOnTrackballEvent());
2243         assertFalse(mockView2.hasCalledOnTrackballEvent());
2244 
2245         mockView1.reset();
2246         mockView2.reset();
2247         downTime = SystemClock.uptimeMillis();
2248         eventTime = downTime;
2249         event = MotionEvent.obtain(downTime, eventTime, MotionEvent.ACTION_MOVE, 1, 2, 0);
2250         mockView2.dispatchTrackballEvent(event);
2251         assertFalse(mockView1.hasCalledOnTrackballEvent());
2252         assertTrue(mockView2.hasCalledOnTrackballEvent());
2253     }
2254 
testDispatchUnhandledMove()2255     public void testDispatchUnhandledMove() throws Throwable {
2256         final MockView view = (MockView) mActivity.findViewById(R.id.mock_view);
2257         runTestOnUiThread(new Runnable() {
2258             @Override
2259             public void run() {
2260                 view.setFocusable(true);
2261                 view.requestFocus();
2262             }
2263         });
2264         getInstrumentation().waitForIdleSync();
2265 
2266         KeyEvent event = new KeyEvent(KeyEvent.ACTION_DOWN, KeyEvent.KEYCODE_DPAD_RIGHT);
2267         getInstrumentation().sendKeySync(event);
2268 
2269         assertTrue(view.hasCalledDispatchUnhandledMove());
2270     }
2271 
testWindowVisibilityChanged()2272     public void testWindowVisibilityChanged() throws Throwable {
2273         final MockView mockView = new MockView(mActivity);
2274         final ViewGroup viewGroup = (ViewGroup) mActivity.findViewById(R.id.viewlayout_root);
2275 
2276         runTestOnUiThread(new Runnable() {
2277             @Override
2278             public void run() {
2279                 viewGroup.addView(mockView);
2280             }
2281         });
2282         getInstrumentation().waitForIdleSync();
2283         assertTrue(mockView.hasCalledOnWindowVisibilityChanged());
2284 
2285         mockView.reset();
2286         runTestOnUiThread(new Runnable() {
2287             @Override
2288             public void run() {
2289                 getActivity().setVisible(false);
2290             }
2291         });
2292         getInstrumentation().waitForIdleSync();
2293         assertTrue(mockView.hasCalledDispatchWindowVisibilityChanged());
2294         assertTrue(mockView.hasCalledOnWindowVisibilityChanged());
2295 
2296         mockView.reset();
2297         runTestOnUiThread(new Runnable() {
2298             @Override
2299             public void run() {
2300                 getActivity().setVisible(true);
2301             }
2302         });
2303         getInstrumentation().waitForIdleSync();
2304         assertTrue(mockView.hasCalledDispatchWindowVisibilityChanged());
2305         assertTrue(mockView.hasCalledOnWindowVisibilityChanged());
2306 
2307         mockView.reset();
2308         runTestOnUiThread(new Runnable() {
2309             @Override
2310             public void run() {
2311                 viewGroup.removeView(mockView);
2312             }
2313         });
2314         getInstrumentation().waitForIdleSync();
2315         assertTrue(mockView.hasCalledOnWindowVisibilityChanged());
2316     }
2317 
testGetLocalVisibleRect()2318     public void testGetLocalVisibleRect() throws Throwable {
2319         final View view = mActivity.findViewById(R.id.mock_view);
2320         Rect rect = new Rect();
2321 
2322         assertTrue(view.getLocalVisibleRect(rect));
2323         assertEquals(0, rect.left);
2324         assertEquals(0, rect.top);
2325         assertEquals(100, rect.right);
2326         assertEquals(200, rect.bottom);
2327 
2328         final LinearLayout.LayoutParams layoutParams1 = new LinearLayout.LayoutParams(0, 300);
2329         runTestOnUiThread(new Runnable() {
2330             @Override
2331             public void run() {
2332                 view.setLayoutParams(layoutParams1);
2333             }
2334         });
2335         getInstrumentation().waitForIdleSync();
2336         assertFalse(view.getLocalVisibleRect(rect));
2337 
2338         final LinearLayout.LayoutParams layoutParams2 = new LinearLayout.LayoutParams(200, -10);
2339         runTestOnUiThread(new Runnable() {
2340             @Override
2341             public void run() {
2342                 view.setLayoutParams(layoutParams2);
2343             }
2344         });
2345         getInstrumentation().waitForIdleSync();
2346         assertFalse(view.getLocalVisibleRect(rect));
2347 
2348         Display display = getActivity().getWindowManager().getDefaultDisplay();
2349         int halfWidth = display.getWidth() / 2;
2350         int halfHeight = display.getHeight() /2;
2351 
2352         final LinearLayout.LayoutParams layoutParams3 =
2353                 new LinearLayout.LayoutParams(halfWidth, halfHeight);
2354         runTestOnUiThread(new Runnable() {
2355             @Override
2356             public void run() {
2357                 view.setLayoutParams(layoutParams3);
2358                 view.scrollTo(20, -30);
2359             }
2360         });
2361         getInstrumentation().waitForIdleSync();
2362         assertTrue(view.getLocalVisibleRect(rect));
2363         assertEquals(20, rect.left);
2364         assertEquals(-30, rect.top);
2365         assertEquals(halfWidth + 20, rect.right);
2366         assertEquals(halfHeight - 30, rect.bottom);
2367 
2368         try {
2369             view.getLocalVisibleRect(null);
2370             fail("should throw NullPointerException");
2371         } catch (NullPointerException e) {
2372         }
2373     }
2374 
testMergeDrawableStates()2375     public void testMergeDrawableStates() {
2376         MockView view = new MockView(mActivity);
2377 
2378         int[] states = view.mergeDrawableStatesWrapper(new int[] { 0, 1, 2, 0, 0 },
2379                 new int[] { 3 });
2380         assertNotNull(states);
2381         assertEquals(5, states.length);
2382         assertEquals(0, states[0]);
2383         assertEquals(1, states[1]);
2384         assertEquals(2, states[2]);
2385         assertEquals(3, states[3]);
2386         assertEquals(0, states[4]);
2387 
2388         try {
2389             view.mergeDrawableStatesWrapper(new int[] { 1, 2 }, new int[] { 3 });
2390             fail("should throw IndexOutOfBoundsException");
2391         } catch (IndexOutOfBoundsException e) {
2392         }
2393 
2394         try {
2395             view.mergeDrawableStatesWrapper(null, new int[] { 0 });
2396             fail("should throw NullPointerException");
2397         } catch (NullPointerException e) {
2398         }
2399 
2400         try {
2401             view.mergeDrawableStatesWrapper(new int [] { 0 }, null);
2402             fail("should throw NullPointerException");
2403         } catch (NullPointerException e) {
2404         }
2405     }
2406 
testOnSaveAndRestoreInstanceState()2407     public void testOnSaveAndRestoreInstanceState() {
2408         // it is hard to simulate operation to make callback be called.
2409     }
2410 
testSaveAndRestoreHierarchyState()2411     public void testSaveAndRestoreHierarchyState() {
2412         int viewId = R.id.mock_view;
2413         MockView view = (MockView) mActivity.findViewById(viewId);
2414         SparseArray<Parcelable> container = new SparseArray<>();
2415         view.saveHierarchyState(container);
2416         assertTrue(view.hasCalledDispatchSaveInstanceState());
2417         assertTrue(view.hasCalledOnSaveInstanceState());
2418         assertEquals(viewId, container.keyAt(0));
2419 
2420         view.reset();
2421         container.put(R.id.mock_view, BaseSavedState.EMPTY_STATE);
2422         view.restoreHierarchyState(container);
2423         assertTrue(view.hasCalledDispatchRestoreInstanceState());
2424         assertTrue(view.hasCalledOnRestoreInstanceState());
2425         container.clear();
2426         view.saveHierarchyState(container);
2427         assertTrue(view.hasCalledDispatchSaveInstanceState());
2428         assertTrue(view.hasCalledOnSaveInstanceState());
2429         assertEquals(viewId, container.keyAt(0));
2430 
2431         container.clear();
2432         container.put(viewId, new android.graphics.Rect());
2433         try {
2434             view.restoreHierarchyState(container);
2435             fail("Parcelable state must be an AbsSaveState, should throw IllegalArgumentException");
2436         } catch (IllegalArgumentException e) {
2437             // expected
2438         }
2439 
2440         try {
2441             view.restoreHierarchyState(null);
2442             fail("Cannot pass null to restoreHierarchyState(), should throw NullPointerException");
2443         } catch (NullPointerException e) {
2444             // expected
2445         }
2446 
2447         try {
2448             view.saveHierarchyState(null);
2449             fail("Cannot pass null to saveHierarchyState(), should throw NullPointerException");
2450         } catch (NullPointerException e) {
2451             // expected
2452         }
2453     }
2454 
testOnKeyDownOrUp()2455     public void testOnKeyDownOrUp() throws Throwable {
2456         final MockView view = (MockView) mActivity.findViewById(R.id.mock_view);
2457         runTestOnUiThread(new Runnable() {
2458             @Override
2459             public void run() {
2460                 view.setFocusable(true);
2461                 view.requestFocus();
2462             }
2463         });
2464         getInstrumentation().waitForIdleSync();
2465         assertTrue(view.isFocused());
2466 
2467         KeyEvent event = new KeyEvent(KeyEvent.ACTION_DOWN, KeyEvent.KEYCODE_0);
2468         getInstrumentation().sendKeySync(event);
2469         assertTrue(view.hasCalledOnKeyDown());
2470 
2471         event = new KeyEvent(KeyEvent.ACTION_UP, KeyEvent.KEYCODE_0);
2472         getInstrumentation().sendKeySync(event);
2473         assertTrue(view.hasCalledOnKeyUp());
2474 
2475         view.reset();
2476         assertTrue(view.isEnabled());
2477         assertFalse(view.isClickable());
2478         assertFalse(view.isPressed());
2479         event = new KeyEvent(KeyEvent.ACTION_DOWN, KeyEvent.KEYCODE_ENTER);
2480         getInstrumentation().sendKeySync(event);
2481         assertFalse(view.isPressed());
2482         assertTrue(view.hasCalledOnKeyDown());
2483 
2484         runTestOnUiThread(new Runnable() {
2485             @Override
2486             public void run() {
2487                 view.setEnabled(true);
2488                 view.setClickable(true);
2489             }
2490         });
2491         view.reset();
2492         OnClickListenerImpl listener = new OnClickListenerImpl();
2493         view.setOnClickListener(listener);
2494 
2495         assertFalse(view.isPressed());
2496         event = new KeyEvent(KeyEvent.ACTION_DOWN, KeyEvent.KEYCODE_ENTER);
2497         getInstrumentation().sendKeySync(event);
2498         assertTrue(view.isPressed());
2499         assertTrue(view.hasCalledOnKeyDown());
2500         event = new KeyEvent(KeyEvent.ACTION_UP, KeyEvent.KEYCODE_ENTER);
2501         getInstrumentation().sendKeySync(event);
2502         assertFalse(view.isPressed());
2503         assertTrue(view.hasCalledOnKeyUp());
2504         assertTrue(listener.hasOnClick());
2505 
2506         view.setPressed(false);
2507         listener.reset();
2508         view.reset();
2509 
2510         assertFalse(view.isPressed());
2511         event = new KeyEvent(KeyEvent.ACTION_DOWN, KeyEvent.KEYCODE_DPAD_CENTER);
2512         getInstrumentation().sendKeySync(event);
2513         assertTrue(view.isPressed());
2514         assertTrue(view.hasCalledOnKeyDown());
2515         event = new KeyEvent(KeyEvent.ACTION_UP, KeyEvent.KEYCODE_DPAD_CENTER);
2516         getInstrumentation().sendKeySync(event);
2517         assertFalse(view.isPressed());
2518         assertTrue(view.hasCalledOnKeyUp());
2519         assertTrue(listener.hasOnClick());
2520     }
2521 
checkBounds(final ViewGroup viewGroup, final View view, final CountDownLatch countDownLatch, final int left, final int top, final int width, final int height)2522     private void checkBounds(final ViewGroup viewGroup, final View view,
2523             final CountDownLatch countDownLatch, final int left, final int top,
2524             final int width, final int height) {
2525         viewGroup.getViewTreeObserver().addOnPreDrawListener(new ViewTreeObserver.OnPreDrawListener() {
2526             @Override
2527             public boolean onPreDraw() {
2528                 assertEquals(left, view.getLeft());
2529                 assertEquals(top, view.getTop());
2530                 assertEquals(width, view.getWidth());
2531                 assertEquals(height, view.getHeight());
2532                 countDownLatch.countDown();
2533                 viewGroup.getViewTreeObserver().removeOnPreDrawListener(this);
2534                 return true;
2535             }
2536         });
2537     }
2538 
testAddRemoveAffectsWrapContentLayout()2539     public void testAddRemoveAffectsWrapContentLayout() throws Throwable {
2540         final int childWidth = 100;
2541         final int childHeight = 200;
2542         final int parentHeight = 400;
2543         final MockLinearLayout parent = new MockLinearLayout(mActivity);
2544         ViewGroup.LayoutParams parentParams = new ViewGroup.LayoutParams(
2545                 ViewGroup.LayoutParams.WRAP_CONTENT, parentHeight);
2546         parent.setLayoutParams(parentParams);
2547         final MockView child = new MockView(mActivity);
2548         child.setBackgroundColor(Color.GREEN);
2549         ViewGroup.LayoutParams childParams = new ViewGroup.LayoutParams(childWidth, childHeight);
2550         child.setLayoutParams(childParams);
2551         final ViewGroup viewGroup = (ViewGroup) mActivity.findViewById(R.id.viewlayout_root);
2552 
2553         // Idea:
2554         // Add the wrap_content parent view to the hierarchy (removing other views as they
2555         // are not needed), test that parent is 0xparentHeight
2556         // Add the child view to the parent, test that parent has same width as child
2557         // Remove the child view from the parent, test that parent is 0xparentHeight
2558         final CountDownLatch countDownLatch1 = new CountDownLatch(1);
2559         runTestOnUiThread(new Runnable() {
2560             @Override
2561             public void run() {
2562                 viewGroup.removeAllViews();
2563                 viewGroup.addView(parent);
2564                 checkBounds(viewGroup, parent, countDownLatch1, 0, 0, 0, parentHeight);
2565             }
2566         });
2567         countDownLatch1.await(500, TimeUnit.MILLISECONDS);
2568 
2569         final CountDownLatch countDownLatch2 = new CountDownLatch(1);
2570         runTestOnUiThread(new Runnable() {
2571             @Override
2572             public void run() {
2573                 parent.addView(child);
2574                 checkBounds(viewGroup, parent, countDownLatch2, 0, 0, childWidth, parentHeight);
2575             }
2576         });
2577         countDownLatch2.await(500, TimeUnit.MILLISECONDS);
2578 
2579         final CountDownLatch countDownLatch3 = new CountDownLatch(1);
2580         runTestOnUiThread(new Runnable() {
2581             @Override
2582             public void run() {
2583                 parent.removeView(child);
2584                 checkBounds(viewGroup, parent, countDownLatch3, 0, 0, 0, parentHeight);
2585             }
2586         });
2587         countDownLatch3.await(500, TimeUnit.MILLISECONDS);
2588     }
2589 
2590     @UiThreadTest
testDispatchKeyEvent()2591     public void testDispatchKeyEvent() {
2592         MockView view = (MockView) mActivity.findViewById(R.id.mock_view);
2593         MockView mockView1 = new MockView(mActivity);
2594         MockView mockView2 = new MockView(mActivity);
2595         ViewGroup viewGroup = (ViewGroup) mActivity.findViewById(R.id.viewlayout_root);
2596         viewGroup.addView(mockView1);
2597         viewGroup.addView(mockView2);
2598         view.setFocusable(true);
2599         mockView1.setFocusable(true);
2600         mockView2.setFocusable(true);
2601 
2602         assertFalse(view.hasCalledOnKeyDown());
2603         assertFalse(mockView1.hasCalledOnKeyDown());
2604         assertFalse(mockView2.hasCalledOnKeyDown());
2605         KeyEvent event = new KeyEvent(KeyEvent.ACTION_DOWN, KeyEvent.KEYCODE_0);
2606         assertFalse(view.dispatchKeyEvent(event));
2607         assertTrue(view.hasCalledOnKeyDown());
2608         assertFalse(mockView1.hasCalledOnKeyDown());
2609         assertFalse(mockView2.hasCalledOnKeyDown());
2610 
2611         view.reset();
2612         mockView1.reset();
2613         mockView2.reset();
2614         assertFalse(view.hasCalledOnKeyDown());
2615         assertFalse(mockView1.hasCalledOnKeyDown());
2616         assertFalse(mockView2.hasCalledOnKeyDown());
2617         event = new KeyEvent(KeyEvent.ACTION_DOWN, KeyEvent.KEYCODE_0);
2618         assertFalse(mockView1.dispatchKeyEvent(event));
2619         assertFalse(view.hasCalledOnKeyDown());
2620         // issue 1695243
2621         // When the view has NOT focus, it dispatches to itself, which disobey the javadoc.
2622         assertTrue(mockView1.hasCalledOnKeyDown());
2623         assertFalse(mockView2.hasCalledOnKeyDown());
2624 
2625         assertFalse(view.hasCalledOnKeyUp());
2626         event = new KeyEvent(KeyEvent.ACTION_UP, KeyEvent.KEYCODE_0);
2627         assertFalse(view.dispatchKeyEvent(event));
2628         assertTrue(view.hasCalledOnKeyUp());
2629 
2630         assertFalse(view.hasCalledOnKeyMultiple());
2631         event = new KeyEvent(1, 2, KeyEvent.ACTION_MULTIPLE, KeyEvent.KEYCODE_0, 2);
2632         assertFalse(view.dispatchKeyEvent(event));
2633         assertTrue(view.hasCalledOnKeyMultiple());
2634 
2635         try {
2636             view.dispatchKeyEvent(null);
2637             fail("should throw NullPointerException");
2638         } catch (NullPointerException e) {
2639             // expected
2640         }
2641 
2642         view.reset();
2643         event = new KeyEvent(KeyEvent.ACTION_UP, KeyEvent.KEYCODE_0);
2644         OnKeyListenerImpl listener = new OnKeyListenerImpl();
2645         view.setOnKeyListener(listener);
2646         assertFalse(listener.hasOnKey());
2647         assertTrue(view.dispatchKeyEvent(event));
2648         assertTrue(listener.hasOnKey());
2649         assertFalse(view.hasCalledOnKeyUp());
2650     }
2651 
2652     @UiThreadTest
testDispatchTouchEvent()2653     public void testDispatchTouchEvent() {
2654         ViewGroup viewGroup = (ViewGroup) mActivity.findViewById(R.id.viewlayout_root);
2655         MockView mockView1 = new MockView(mActivity);
2656         MockView mockView2 = new MockView(mActivity);
2657         viewGroup.addView(mockView1);
2658         viewGroup.addView(mockView2);
2659 
2660         int[] xy = new int[2];
2661         mockView1.getLocationOnScreen(xy);
2662 
2663         final int viewWidth = mockView1.getWidth();
2664         final int viewHeight = mockView1.getHeight();
2665         final float x = xy[0] + viewWidth / 2.0f;
2666         final float y = xy[1] + viewHeight / 2.0f;
2667 
2668         long downTime = SystemClock.uptimeMillis();
2669         long eventTime = SystemClock.uptimeMillis();
2670         MotionEvent event = MotionEvent.obtain(downTime, eventTime, MotionEvent.ACTION_MOVE,
2671                 x, y, 0);
2672 
2673         assertFalse(mockView1.hasCalledOnTouchEvent());
2674         assertFalse(mockView1.dispatchTouchEvent(event));
2675         assertTrue(mockView1.hasCalledOnTouchEvent());
2676 
2677         assertFalse(mockView2.hasCalledOnTouchEvent());
2678         assertFalse(mockView2.dispatchTouchEvent(event));
2679         // issue 1695243
2680         // it passes the touch screen motion event down to itself even if it is not the target view.
2681         assertTrue(mockView2.hasCalledOnTouchEvent());
2682 
2683         mockView1.reset();
2684         OnTouchListenerImpl listener = new OnTouchListenerImpl();
2685         mockView1.setOnTouchListener(listener);
2686         assertFalse(listener.hasOnTouch());
2687         assertTrue(mockView1.dispatchTouchEvent(event));
2688         assertTrue(listener.hasOnTouch());
2689         assertFalse(mockView1.hasCalledOnTouchEvent());
2690     }
2691 
testInvalidate1()2692     public void testInvalidate1() throws Throwable {
2693         final MockView view = (MockView) mActivity.findViewById(R.id.mock_view);
2694         assertTrue(view.hasCalledOnDraw());
2695 
2696         view.reset();
2697         runTestOnUiThread(new Runnable() {
2698             @Override
2699             public void run() {
2700                 view.invalidate();
2701             }
2702         });
2703         getInstrumentation().waitForIdleSync();
2704         new PollingCheck() {
2705             @Override
2706             protected boolean check() {
2707                 return view.hasCalledOnDraw();
2708             }
2709         }.run();
2710 
2711         view.reset();
2712         runTestOnUiThread(new Runnable() {
2713             @Override
2714             public void run() {
2715                 view.setVisibility(View.INVISIBLE);
2716                 view.invalidate();
2717             }
2718         });
2719         getInstrumentation().waitForIdleSync();
2720         assertFalse(view.hasCalledOnDraw());
2721     }
2722 
testInvalidate2()2723     public void testInvalidate2() throws Throwable {
2724         final MockView view = (MockView) mActivity.findViewById(R.id.mock_view);
2725         assertTrue(view.hasCalledOnDraw());
2726 
2727         try {
2728             view.invalidate(null);
2729             fail("should throw NullPointerException");
2730         } catch (NullPointerException e) {
2731         }
2732 
2733         view.reset();
2734         final Rect dirty = new Rect(view.getLeft() + 1, view.getTop() + 1,
2735                 view.getLeft() + view.getWidth() / 2, view.getTop() + view.getHeight() / 2);
2736         runTestOnUiThread(new Runnable() {
2737             @Override
2738             public void run() {
2739                 view.invalidate(dirty);
2740             }
2741         });
2742         getInstrumentation().waitForIdleSync();
2743         new PollingCheck() {
2744             @Override
2745             protected boolean check() {
2746                 return view.hasCalledOnDraw();
2747             }
2748         }.run();
2749 
2750         view.reset();
2751         runTestOnUiThread(new Runnable() {
2752             @Override
2753             public void run() {
2754                 view.setVisibility(View.INVISIBLE);
2755                 view.invalidate(dirty);
2756             }
2757         });
2758         getInstrumentation().waitForIdleSync();
2759         assertFalse(view.hasCalledOnDraw());
2760     }
2761 
testInvalidate3()2762     public void testInvalidate3() throws Throwable {
2763         final MockView view = (MockView) mActivity.findViewById(R.id.mock_view);
2764         assertTrue(view.hasCalledOnDraw());
2765 
2766         view.reset();
2767         final Rect dirty = new Rect(view.getLeft() + 1, view.getTop() + 1,
2768                 view.getLeft() + view.getWidth() / 2, view.getTop() + view.getHeight() / 2);
2769         runTestOnUiThread(new Runnable() {
2770             @Override
2771             public void run() {
2772                 view.invalidate(dirty.left, dirty.top, dirty.right, dirty.bottom);
2773             }
2774         });
2775         getInstrumentation().waitForIdleSync();
2776         new PollingCheck() {
2777             @Override
2778             protected boolean check() {
2779                 return view.hasCalledOnDraw();
2780             }
2781         }.run();
2782 
2783         view.reset();
2784         runTestOnUiThread(new Runnable() {
2785             @Override
2786             public void run() {
2787                 view.setVisibility(View.INVISIBLE);
2788                 view.invalidate(dirty.left, dirty.top, dirty.right, dirty.bottom);
2789             }
2790         });
2791         getInstrumentation().waitForIdleSync();
2792         assertFalse(view.hasCalledOnDraw());
2793     }
2794 
testInvalidateDrawable()2795     public void testInvalidateDrawable() throws Throwable {
2796         final MockView view = (MockView) mActivity.findViewById(R.id.mock_view);
2797         final Drawable d1 = mResources.getDrawable(R.drawable.scenery);
2798         final Drawable d2 = mResources.getDrawable(R.drawable.pass);
2799 
2800         view.reset();
2801         runTestOnUiThread(new Runnable() {
2802             @Override
2803             public void run() {
2804                 view.setBackgroundDrawable(d1);
2805                 view.invalidateDrawable(d1);
2806             }
2807         });
2808         getInstrumentation().waitForIdleSync();
2809         new PollingCheck() {
2810             @Override
2811             protected boolean check() {
2812                 return view.hasCalledOnDraw();
2813             }
2814         }.run();
2815 
2816         view.reset();
2817         runTestOnUiThread(new Runnable() {
2818             @Override
2819             public void run() {
2820                 view.invalidateDrawable(d2);
2821             }
2822         });
2823         getInstrumentation().waitForIdleSync();
2824         assertFalse(view.hasCalledOnDraw());
2825 
2826         MockView viewTestNull = new MockView(mActivity);
2827         try {
2828             viewTestNull.invalidateDrawable(null);
2829             fail("should throw NullPointerException");
2830         } catch (NullPointerException e) {
2831         }
2832     }
2833 
2834     @UiThreadTest
testOnFocusChanged()2835     public void testOnFocusChanged() {
2836         MockView view = (MockView) mActivity.findViewById(R.id.mock_view);
2837 
2838         mActivity.findViewById(R.id.fit_windows).setFocusable(true);
2839         view.setFocusable(true);
2840         assertFalse(view.hasCalledOnFocusChanged());
2841 
2842         view.requestFocus();
2843         assertTrue(view.hasCalledOnFocusChanged());
2844 
2845         view.reset();
2846         view.clearFocus();
2847         assertTrue(view.hasCalledOnFocusChanged());
2848     }
2849 
testDrawableState()2850     public void testDrawableState() {
2851         MockView view = new MockView(mActivity);
2852         view.setParent(mMockParent);
2853 
2854         assertFalse(view.hasCalledOnCreateDrawableState());
2855         assertTrue(Arrays.equals(MockView.getEnabledStateSet(), view.getDrawableState()));
2856         assertTrue(view.hasCalledOnCreateDrawableState());
2857 
2858         view.reset();
2859         assertFalse(view.hasCalledOnCreateDrawableState());
2860         assertTrue(Arrays.equals(MockView.getEnabledStateSet(), view.getDrawableState()));
2861         assertFalse(view.hasCalledOnCreateDrawableState());
2862 
2863         view.reset();
2864         assertFalse(view.hasCalledDrawableStateChanged());
2865         view.setPressed(true);
2866         assertTrue(view.hasCalledDrawableStateChanged());
2867         assertTrue(Arrays.equals(MockView.getPressedEnabledStateSet(), view.getDrawableState()));
2868         assertTrue(view.hasCalledOnCreateDrawableState());
2869 
2870         view.reset();
2871         mMockParent.reset();
2872         assertFalse(view.hasCalledDrawableStateChanged());
2873         assertFalse(mMockParent.hasChildDrawableStateChanged());
2874         view.refreshDrawableState();
2875         assertTrue(view.hasCalledDrawableStateChanged());
2876         assertTrue(mMockParent.hasChildDrawableStateChanged());
2877         assertTrue(Arrays.equals(MockView.getPressedEnabledStateSet(), view.getDrawableState()));
2878         assertTrue(view.hasCalledOnCreateDrawableState());
2879     }
2880 
testWindowFocusChanged()2881     public void testWindowFocusChanged() {
2882         final MockView view = (MockView) mActivity.findViewById(R.id.mock_view);
2883 
2884         // Wait until the window has been focused.
2885         new PollingCheck(TIMEOUT_DELTA) {
2886             @Override
2887             protected boolean check() {
2888                 return view.hasWindowFocus();
2889             }
2890         }.run();
2891 
2892         new PollingCheck() {
2893             @Override
2894             protected boolean check() {
2895                 return view.hasCalledOnWindowFocusChanged();
2896             }
2897         }.run();
2898 
2899         assertTrue(view.hasCalledOnWindowFocusChanged());
2900         assertTrue(view.hasCalledDispatchWindowFocusChanged());
2901 
2902         view.reset();
2903         assertFalse(view.hasCalledOnWindowFocusChanged());
2904         assertFalse(view.hasCalledDispatchWindowFocusChanged());
2905 
2906         CtsActivity activity = launchActivity("android.view.cts", CtsActivity.class, null);
2907 
2908         // Wait until the window lost focus.
2909         new PollingCheck(TIMEOUT_DELTA) {
2910             @Override
2911             protected boolean check() {
2912                 return !view.hasWindowFocus();
2913             }
2914         }.run();
2915 
2916         assertTrue(view.hasCalledOnWindowFocusChanged());
2917         assertTrue(view.hasCalledDispatchWindowFocusChanged());
2918 
2919         activity.finish();
2920     }
2921 
testDraw()2922     public void testDraw() throws Throwable {
2923         final MockView view = (MockView) mActivity.findViewById(R.id.mock_view);
2924         runTestOnUiThread(new Runnable() {
2925             @Override
2926             public void run() {
2927                 view.requestLayout();
2928             }
2929         });
2930         getInstrumentation().waitForIdleSync();
2931 
2932         assertTrue(view.hasCalledOnDraw());
2933         assertTrue(view.hasCalledDispatchDraw());
2934     }
2935 
testRequestFocusFromTouch()2936     public void testRequestFocusFromTouch() {
2937         View view = new View(mActivity);
2938         view.setFocusable(true);
2939         assertFalse(view.isFocused());
2940 
2941         view.requestFocusFromTouch();
2942         assertTrue(view.isFocused());
2943 
2944         view.requestFocusFromTouch();
2945         assertTrue(view.isFocused());
2946     }
2947 
testRequestRectangleOnScreen1()2948     public void testRequestRectangleOnScreen1() {
2949         MockView view = new MockView(mActivity);
2950         Rect rectangle = new Rect(10, 10, 20, 30);
2951         MockViewGroupParent parent = new MockViewGroupParent(mActivity);
2952 
2953         // parent is null
2954         assertFalse(view.requestRectangleOnScreen(rectangle, true));
2955         assertFalse(view.requestRectangleOnScreen(rectangle, false));
2956         assertFalse(view.requestRectangleOnScreen(null, true));
2957 
2958         view.setParent(parent);
2959         view.scrollTo(1, 2);
2960         assertFalse(parent.hasRequestChildRectangleOnScreen());
2961 
2962         assertFalse(view.requestRectangleOnScreen(rectangle, true));
2963         assertTrue(parent.hasRequestChildRectangleOnScreen());
2964 
2965         parent.reset();
2966         view.scrollTo(11, 22);
2967         assertFalse(parent.hasRequestChildRectangleOnScreen());
2968 
2969         assertFalse(view.requestRectangleOnScreen(rectangle, true));
2970         assertTrue(parent.hasRequestChildRectangleOnScreen());
2971 
2972         try {
2973             view.requestRectangleOnScreen(null, true);
2974             fail("should throw NullPointerException");
2975         } catch (NullPointerException e) {
2976         }
2977     }
2978 
testRequestRectangleOnScreen2()2979     public void testRequestRectangleOnScreen2() {
2980         MockView view = new MockView(mActivity);
2981         Rect rectangle = new Rect();
2982         MockViewGroupParent parent = new MockViewGroupParent(mActivity);
2983 
2984         MockViewGroupParent grandparent = new MockViewGroupParent(mActivity);
2985 
2986         // parent is null
2987         assertFalse(view.requestRectangleOnScreen(rectangle));
2988         assertFalse(view.requestRectangleOnScreen(null));
2989         assertEquals(0, rectangle.left);
2990         assertEquals(0, rectangle.top);
2991         assertEquals(0, rectangle.right);
2992         assertEquals(0, rectangle.bottom);
2993 
2994         parent.addView(view);
2995         parent.scrollTo(1, 2);
2996         grandparent.addView(parent);
2997 
2998         assertFalse(parent.hasRequestChildRectangleOnScreen());
2999         assertFalse(grandparent.hasRequestChildRectangleOnScreen());
3000 
3001         assertFalse(view.requestRectangleOnScreen(rectangle));
3002 
3003         assertTrue(parent.hasRequestChildRectangleOnScreen());
3004         assertTrue(grandparent.hasRequestChildRectangleOnScreen());
3005 
3006         // it is grand parent's responsibility to check parent's scroll offset
3007         final Rect requestedRect = grandparent.getLastRequestedChildRectOnScreen();
3008         assertEquals(0, requestedRect.left);
3009         assertEquals(0, requestedRect.top);
3010         assertEquals(0, requestedRect.right);
3011         assertEquals(0, requestedRect.bottom);
3012 
3013         try {
3014             view.requestRectangleOnScreen(null);
3015             fail("should throw NullPointerException");
3016         } catch (NullPointerException e) {
3017         }
3018     }
3019 
testRequestRectangleOnScreen3()3020     public void testRequestRectangleOnScreen3() {
3021         requestRectangleOnScreenTest(false);
3022     }
3023 
testRequestRectangleOnScreen4()3024     public void testRequestRectangleOnScreen4() {
3025         requestRectangleOnScreenTest(true);
3026     }
3027 
testRequestRectangleOnScreen5()3028     public void testRequestRectangleOnScreen5() {
3029         MockView child = new MockView(mActivity);
3030 
3031         MockViewGroupParent parent = new MockViewGroupParent(mActivity);
3032         MockViewGroupParent grandParent = new MockViewGroupParent(mActivity);
3033         parent.addView(child);
3034         grandParent.addView(parent);
3035 
3036         child.layout(5, 6, 7, 9);
3037         child.requestRectangleOnScreen(new Rect(10, 10, 12, 13));
3038         assertEquals(new Rect(10, 10, 12, 13), parent.getLastRequestedChildRectOnScreen());
3039         assertEquals(new Rect(15, 16, 17, 19), grandParent.getLastRequestedChildRectOnScreen());
3040 
3041         child.scrollBy(1, 2);
3042         child.requestRectangleOnScreen(new Rect(10, 10, 12, 13));
3043         assertEquals(new Rect(10, 10, 12, 13), parent.getLastRequestedChildRectOnScreen());
3044         assertEquals(new Rect(14, 14, 16, 17), grandParent.getLastRequestedChildRectOnScreen());
3045     }
3046 
requestRectangleOnScreenTest(boolean scrollParent)3047     private void requestRectangleOnScreenTest(boolean scrollParent) {
3048         MockView child = new MockView(mActivity);
3049 
3050         MockViewGroupParent parent = new MockViewGroupParent(mActivity);
3051         MockViewGroupParent grandParent = new MockViewGroupParent(mActivity);
3052         parent.addView(child);
3053         grandParent.addView(parent);
3054 
3055         child.requestRectangleOnScreen(new Rect(10, 10, 12, 13));
3056         assertEquals(new Rect(10, 10, 12, 13), parent.getLastRequestedChildRectOnScreen());
3057         assertEquals(new Rect(10, 10, 12, 13), grandParent.getLastRequestedChildRectOnScreen());
3058 
3059         child.scrollBy(1, 2);
3060         if (scrollParent) {
3061             // should not affect anything
3062             parent.scrollBy(25, 30);
3063             parent.layout(3, 5, 7, 9);
3064         }
3065         child.requestRectangleOnScreen(new Rect(10, 10, 12, 13));
3066         assertEquals(new Rect(10, 10, 12, 13), parent.getLastRequestedChildRectOnScreen());
3067         assertEquals(new Rect(9, 8, 11, 11), grandParent.getLastRequestedChildRectOnScreen());
3068     }
3069 
testRequestRectangleOnScreenWithScale()3070     public void testRequestRectangleOnScreenWithScale() {
3071         // scale should not affect the rectangle
3072         MockView child = new MockView(mActivity);
3073         child.setScaleX(2);
3074         child.setScaleX(3);
3075         MockViewGroupParent parent = new MockViewGroupParent(mActivity);
3076         MockViewGroupParent grandParent = new MockViewGroupParent(mActivity);
3077         parent.addView(child);
3078         grandParent.addView(parent);
3079         child.requestRectangleOnScreen(new Rect(10, 10, 12, 13));
3080         assertEquals(new Rect(10, 10, 12, 13), parent.getLastRequestedChildRectOnScreen());
3081         assertEquals(new Rect(10, 10, 12, 13), grandParent.getLastRequestedChildRectOnScreen());
3082     }
3083 
3084     /**
3085      * For the duration of the tap timeout we are in a 'prepressed' state
3086      * to differentiate between taps and touch scrolls.
3087      * Wait at least this long before testing if the view is pressed
3088      * by calling this function.
3089      */
waitPrepressedTimeout()3090     private void waitPrepressedTimeout() {
3091         try {
3092             Thread.sleep(ViewConfiguration.getTapTimeout() + 10);
3093         } catch (InterruptedException e) {
3094             Log.e(LOG_TAG, "waitPrepressedTimeout() interrupted! Test may fail!", e);
3095         }
3096         getInstrumentation().waitForIdleSync();
3097     }
3098 
testOnTouchEvent()3099     public void testOnTouchEvent() throws Throwable {
3100         final MockView view = (MockView) mActivity.findViewById(R.id.mock_view);
3101 
3102         assertTrue(view.isEnabled());
3103         assertFalse(view.isClickable());
3104         assertFalse(view.isLongClickable());
3105 
3106         TouchUtils.clickView(this, view);
3107         assertTrue(view.hasCalledOnTouchEvent());
3108 
3109         runTestOnUiThread(new Runnable() {
3110             @Override
3111             public void run() {
3112                 view.setEnabled(true);
3113                 view.setClickable(true);
3114                 view.setLongClickable(true);
3115             }
3116         });
3117         getInstrumentation().waitForIdleSync();
3118         assertTrue(view.isEnabled());
3119         assertTrue(view.isClickable());
3120         assertTrue(view.isLongClickable());
3121 
3122         // MotionEvent.ACTION_DOWN
3123         int[] xy = new int[2];
3124         view.getLocationOnScreen(xy);
3125 
3126         final int viewWidth = view.getWidth();
3127         final int viewHeight = view.getHeight();
3128         float x = xy[0] + viewWidth / 2.0f;
3129         float y = xy[1] + viewHeight / 2.0f;
3130 
3131         long downTime = SystemClock.uptimeMillis();
3132         long eventTime = SystemClock.uptimeMillis();
3133         MotionEvent event = MotionEvent.obtain(downTime, eventTime, MotionEvent.ACTION_DOWN,
3134                 x, y, 0);
3135         assertFalse(view.isPressed());
3136         getInstrumentation().sendPointerSync(event);
3137         waitPrepressedTimeout();
3138         assertTrue(view.hasCalledOnTouchEvent());
3139         assertTrue(view.isPressed());
3140 
3141         // MotionEvent.ACTION_MOVE
3142         // move out of the bound.
3143         view.reset();
3144         downTime = SystemClock.uptimeMillis();
3145         eventTime = SystemClock.uptimeMillis();
3146         int slop = ViewConfiguration.get(mActivity).getScaledTouchSlop();
3147         x = xy[0] + viewWidth + slop;
3148         y = xy[1] + viewHeight + slop;
3149         event = MotionEvent.obtain(downTime, eventTime, MotionEvent.ACTION_MOVE, x, y, 0);
3150         getInstrumentation().sendPointerSync(event);
3151         assertTrue(view.hasCalledOnTouchEvent());
3152         assertFalse(view.isPressed());
3153 
3154         // move into view
3155         view.reset();
3156         downTime = SystemClock.uptimeMillis();
3157         eventTime = SystemClock.uptimeMillis();
3158         x = xy[0] + viewWidth - 1;
3159         y = xy[1] + viewHeight - 1;
3160         event = MotionEvent.obtain(downTime, eventTime, MotionEvent.ACTION_MOVE, x, y, 0);
3161         getInstrumentation().sendPointerSync(event);
3162         waitPrepressedTimeout();
3163         assertTrue(view.hasCalledOnTouchEvent());
3164         assertFalse(view.isPressed());
3165 
3166         // MotionEvent.ACTION_UP
3167         OnClickListenerImpl listener = new OnClickListenerImpl();
3168         view.setOnClickListener(listener);
3169         view.reset();
3170         downTime = SystemClock.uptimeMillis();
3171         eventTime = SystemClock.uptimeMillis();
3172         event = MotionEvent.obtain(downTime, eventTime, MotionEvent.ACTION_UP, x, y, 0);
3173         getInstrumentation().sendPointerSync(event);
3174         assertTrue(view.hasCalledOnTouchEvent());
3175         assertFalse(listener.hasOnClick());
3176 
3177         view.reset();
3178         x = xy[0] + viewWidth / 2.0f;
3179         y = xy[1] + viewHeight / 2.0f;
3180         downTime = SystemClock.uptimeMillis();
3181         eventTime = SystemClock.uptimeMillis();
3182         event = MotionEvent.obtain(downTime, eventTime, MotionEvent.ACTION_DOWN, x, y, 0);
3183         getInstrumentation().sendPointerSync(event);
3184         assertTrue(view.hasCalledOnTouchEvent());
3185 
3186         // MotionEvent.ACTION_CANCEL
3187         view.reset();
3188         listener.reset();
3189         downTime = SystemClock.uptimeMillis();
3190         eventTime = SystemClock.uptimeMillis();
3191         event = MotionEvent.obtain(downTime, eventTime, MotionEvent.ACTION_CANCEL, x, y, 0);
3192         getInstrumentation().sendPointerSync(event);
3193         assertTrue(view.hasCalledOnTouchEvent());
3194         assertFalse(view.isPressed());
3195         assertFalse(listener.hasOnClick());
3196     }
3197 
testBringToFront()3198     public void testBringToFront() {
3199         MockView view = new MockView(mActivity);
3200         view.setParent(mMockParent);
3201 
3202         assertFalse(mMockParent.hasBroughtChildToFront());
3203         view.bringToFront();
3204         assertTrue(mMockParent.hasBroughtChildToFront());
3205     }
3206 
testGetApplicationWindowToken()3207     public void testGetApplicationWindowToken() {
3208         View view = new View(mActivity);
3209         // mAttachInfo is null
3210         assertNull(view.getApplicationWindowToken());
3211 
3212         // mAttachInfo is not null
3213         view = mActivity.findViewById(R.id.fit_windows);
3214         assertNotNull(view.getApplicationWindowToken());
3215     }
3216 
testGetBottomPaddingOffset()3217     public void testGetBottomPaddingOffset() {
3218         MockView view = new MockView(mActivity);
3219         assertEquals(0, view.getBottomPaddingOffset());
3220     }
3221 
testGetLeftPaddingOffset()3222     public void testGetLeftPaddingOffset() {
3223         MockView view = new MockView(mActivity);
3224         assertEquals(0, view.getLeftPaddingOffset());
3225     }
3226 
testGetRightPaddingOffset()3227     public void testGetRightPaddingOffset() {
3228         MockView view = new MockView(mActivity);
3229         assertEquals(0, view.getRightPaddingOffset());
3230     }
3231 
testGetTopPaddingOffset()3232     public void testGetTopPaddingOffset() {
3233         MockView view = new MockView(mActivity);
3234         assertEquals(0, view.getTopPaddingOffset());
3235     }
3236 
testIsPaddingOffsetRequired()3237     public void testIsPaddingOffsetRequired() {
3238         MockView view = new MockView(mActivity);
3239         assertFalse(view.isPaddingOffsetRequired());
3240     }
3241 
3242     @UiThreadTest
testPadding()3243     public void testPadding() {
3244         MockView view = (MockView) mActivity.findViewById(R.id.mock_view_padding_full);
3245         Drawable background = view.getBackground();
3246         Rect backgroundPadding = new Rect();
3247         background.getPadding(backgroundPadding);
3248 
3249         // There is some background with a non null padding
3250         assertNotNull(background);
3251         assertTrue(backgroundPadding.left != 0);
3252         assertTrue(backgroundPadding.right != 0);
3253         assertTrue(backgroundPadding.top != 0);
3254         assertTrue(backgroundPadding.bottom != 0);
3255 
3256         // The XML defines android:padding="0dp" and that should be the resulting padding
3257         assertEquals(0, view.getPaddingLeft());
3258         assertEquals(0, view.getPaddingTop());
3259         assertEquals(0, view.getPaddingRight());
3260         assertEquals(0, view.getPaddingBottom());
3261 
3262         // LEFT case
3263         view = (MockView) mActivity.findViewById(R.id.mock_view_padding_left);
3264         background = view.getBackground();
3265         backgroundPadding = new Rect();
3266         background.getPadding(backgroundPadding);
3267 
3268         // There is some background with a non null padding
3269         assertNotNull(background);
3270         assertTrue(backgroundPadding.left != 0);
3271         assertTrue(backgroundPadding.right != 0);
3272         assertTrue(backgroundPadding.top != 0);
3273         assertTrue(backgroundPadding.bottom != 0);
3274 
3275         // The XML defines android:paddingLeft="0dp" and that should be the resulting padding
3276         assertEquals(0, view.getPaddingLeft());
3277         assertEquals(backgroundPadding.top, view.getPaddingTop());
3278         assertEquals(backgroundPadding.right, view.getPaddingRight());
3279         assertEquals(backgroundPadding.bottom, view.getPaddingBottom());
3280 
3281         // RIGHT case
3282         view = (MockView) mActivity.findViewById(R.id.mock_view_padding_right);
3283         background = view.getBackground();
3284         backgroundPadding = new Rect();
3285         background.getPadding(backgroundPadding);
3286 
3287         // There is some background with a non null padding
3288         assertNotNull(background);
3289         assertTrue(backgroundPadding.left != 0);
3290         assertTrue(backgroundPadding.right != 0);
3291         assertTrue(backgroundPadding.top != 0);
3292         assertTrue(backgroundPadding.bottom != 0);
3293 
3294         // The XML defines android:paddingRight="0dp" and that should be the resulting padding
3295         assertEquals(backgroundPadding.left, view.getPaddingLeft());
3296         assertEquals(backgroundPadding.top, view.getPaddingTop());
3297         assertEquals(0, view.getPaddingRight());
3298         assertEquals(backgroundPadding.bottom, view.getPaddingBottom());
3299 
3300         // TOP case
3301         view = (MockView) mActivity.findViewById(R.id.mock_view_padding_top);
3302         background = view.getBackground();
3303         backgroundPadding = new Rect();
3304         background.getPadding(backgroundPadding);
3305 
3306         // There is some background with a non null padding
3307         assertNotNull(background);
3308         assertTrue(backgroundPadding.left != 0);
3309         assertTrue(backgroundPadding.right != 0);
3310         assertTrue(backgroundPadding.top != 0);
3311         assertTrue(backgroundPadding.bottom != 0);
3312 
3313         // The XML defines android:paddingTop="0dp" and that should be the resulting padding
3314         assertEquals(backgroundPadding.left, view.getPaddingLeft());
3315         assertEquals(0, view.getPaddingTop());
3316         assertEquals(backgroundPadding.right, view.getPaddingRight());
3317         assertEquals(backgroundPadding.bottom, view.getPaddingBottom());
3318 
3319         // BOTTOM case
3320         view = (MockView) mActivity.findViewById(R.id.mock_view_padding_bottom);
3321         background = view.getBackground();
3322         backgroundPadding = new Rect();
3323         background.getPadding(backgroundPadding);
3324 
3325         // There is some background with a non null padding
3326         assertNotNull(background);
3327         assertTrue(backgroundPadding.left != 0);
3328         assertTrue(backgroundPadding.right != 0);
3329         assertTrue(backgroundPadding.top != 0);
3330         assertTrue(backgroundPadding.bottom != 0);
3331 
3332         // The XML defines android:paddingBottom="0dp" and that should be the resulting padding
3333         assertEquals(backgroundPadding.left, view.getPaddingLeft());
3334         assertEquals(backgroundPadding.top, view.getPaddingTop());
3335         assertEquals(backgroundPadding.right, view.getPaddingRight());
3336         assertEquals(0, view.getPaddingBottom());
3337 
3338         // Case for interleaved background/padding changes
3339         view = (MockView) mActivity.findViewById(R.id.mock_view_padding_runtime_updated);
3340         background = view.getBackground();
3341         backgroundPadding = new Rect();
3342         background.getPadding(backgroundPadding);
3343 
3344         // There is some background with a null padding
3345         assertNotNull(background);
3346         assertTrue(backgroundPadding.left == 0);
3347         assertTrue(backgroundPadding.right == 0);
3348         assertTrue(backgroundPadding.top == 0);
3349         assertTrue(backgroundPadding.bottom == 0);
3350 
3351         final int paddingLeft = view.getPaddingLeft();
3352         final int paddingRight = view.getPaddingRight();
3353         final int paddingTop = view.getPaddingTop();
3354         final int paddingBottom = view.getPaddingBottom();
3355         assertEquals(8, paddingLeft);
3356         assertEquals(0, paddingTop);
3357         assertEquals(8, paddingRight);
3358         assertEquals(0, paddingBottom);
3359 
3360         // Manipulate background and padding
3361         background.setState(view.getDrawableState());
3362         background.jumpToCurrentState();
3363         view.setBackground(background);
3364         view.setPadding(paddingLeft, paddingTop, paddingRight, paddingBottom);
3365 
3366         assertEquals(8, view.getPaddingLeft());
3367         assertEquals(0, view.getPaddingTop());
3368         assertEquals(8, view.getPaddingRight());
3369         assertEquals(0, view.getPaddingBottom());
3370     }
3371 
testGetWindowVisibleDisplayFrame()3372     public void testGetWindowVisibleDisplayFrame() {
3373         Rect outRect = new Rect();
3374         View view = new View(mActivity);
3375         // mAttachInfo is null
3376         WindowManager wm = (WindowManager)mActivity.getSystemService(Context.WINDOW_SERVICE);
3377         Display d = wm.getDefaultDisplay();
3378         view.getWindowVisibleDisplayFrame(outRect);
3379         assertEquals(0, outRect.left);
3380         assertEquals(0, outRect.top);
3381         assertEquals(d.getWidth(), outRect.right);
3382         assertEquals(d.getHeight(), outRect.bottom);
3383 
3384         // mAttachInfo is not null
3385         outRect = new Rect();
3386         view = mActivity.findViewById(R.id.fit_windows);
3387         // it's implementation detail
3388         view.getWindowVisibleDisplayFrame(outRect);
3389     }
3390 
testSetScrollContainer()3391     public void testSetScrollContainer() throws Throwable {
3392         final MockView mockView = (MockView) mActivity.findViewById(R.id.mock_view);
3393         final MockView scrollView = (MockView) mActivity.findViewById(R.id.scroll_view);
3394         Bitmap bitmap = Bitmap.createBitmap(200, 300, Bitmap.Config.RGB_565);
3395         final BitmapDrawable d = new BitmapDrawable(bitmap);
3396         final InputMethodManager imm = (InputMethodManager)getActivity().getSystemService(
3397                 Context.INPUT_METHOD_SERVICE);
3398         final LinearLayout.LayoutParams layoutParams = new LinearLayout.LayoutParams(300, 500);
3399         runTestOnUiThread(new Runnable() {
3400             @Override
3401             public void run() {
3402                 mockView.setBackgroundDrawable(d);
3403                 mockView.setHorizontalFadingEdgeEnabled(true);
3404                 mockView.setVerticalFadingEdgeEnabled(true);
3405                 mockView.setLayoutParams(layoutParams);
3406                 scrollView.setLayoutParams(layoutParams);
3407 
3408                 mockView.setFocusable(true);
3409                 mockView.requestFocus();
3410                 mockView.setScrollContainer(true);
3411                 scrollView.setScrollContainer(false);
3412                 imm.showSoftInput(mockView, 0);
3413             }
3414         });
3415         getInstrumentation().waitForIdleSync();
3416 
3417         // FIXME: why the size of view doesn't change?
3418 
3419         runTestOnUiThread(new Runnable() {
3420             @Override
3421             public void run() {
3422                 imm.hideSoftInputFromInputMethod(mockView.getWindowToken(), 0);
3423             }
3424         });
3425         getInstrumentation().waitForIdleSync();
3426     }
3427 
testTouchMode()3428     public void testTouchMode() throws Throwable {
3429         final MockView mockView = (MockView) mActivity.findViewById(R.id.mock_view);
3430         final View fitWindowsView = mActivity.findViewById(R.id.fit_windows);
3431         runTestOnUiThread(new Runnable() {
3432             @Override
3433             public void run() {
3434                 mockView.setFocusableInTouchMode(true);
3435                 fitWindowsView.setFocusable(true);
3436                 fitWindowsView.requestFocus();
3437             }
3438         });
3439         getInstrumentation().waitForIdleSync();
3440         assertTrue(mockView.isFocusableInTouchMode());
3441         assertFalse(fitWindowsView.isFocusableInTouchMode());
3442         assertTrue(mockView.isFocusable());
3443         assertTrue(fitWindowsView.isFocusable());
3444         assertFalse(mockView.isFocused());
3445         assertTrue(fitWindowsView.isFocused());
3446         assertFalse(mockView.isInTouchMode());
3447         assertFalse(fitWindowsView.isInTouchMode());
3448 
3449         TouchUtils.tapView(this, mockView);
3450         assertFalse(fitWindowsView.isFocused());
3451         assertFalse(mockView.isFocused());
3452         runTestOnUiThread(new Runnable() {
3453             @Override
3454             public void run() {
3455                 mockView.requestFocus();
3456             }
3457         });
3458         getInstrumentation().waitForIdleSync();
3459         assertTrue(mockView.isFocused());
3460         runTestOnUiThread(new Runnable() {
3461             @Override
3462             public void run() {
3463                 fitWindowsView.requestFocus();
3464             }
3465         });
3466         getInstrumentation().waitForIdleSync();
3467         assertFalse(fitWindowsView.isFocused());
3468         assertTrue(mockView.isInTouchMode());
3469         assertTrue(fitWindowsView.isInTouchMode());
3470 
3471         KeyEvent keyEvent = new KeyEvent(KeyEvent.ACTION_DOWN, KeyEvent.KEYCODE_0);
3472         getInstrumentation().sendKeySync(keyEvent);
3473         assertTrue(mockView.isFocused());
3474         assertFalse(fitWindowsView.isFocused());
3475         runTestOnUiThread(new Runnable() {
3476             @Override
3477             public void run() {
3478                 fitWindowsView.requestFocus();
3479             }
3480         });
3481         getInstrumentation().waitForIdleSync();
3482         assertFalse(mockView.isFocused());
3483         assertTrue(fitWindowsView.isFocused());
3484         assertFalse(mockView.isInTouchMode());
3485         assertFalse(fitWindowsView.isInTouchMode());
3486     }
3487 
3488     @UiThreadTest
testScrollbarStyle()3489     public void testScrollbarStyle() {
3490         MockView view = (MockView) mActivity.findViewById(R.id.scroll_view);
3491         Bitmap bitmap = Bitmap.createBitmap(200, 300, Bitmap.Config.RGB_565);
3492         BitmapDrawable d = new BitmapDrawable(bitmap);
3493         view.setBackgroundDrawable(d);
3494         view.setHorizontalFadingEdgeEnabled(true);
3495         view.setVerticalFadingEdgeEnabled(true);
3496 
3497         assertTrue(view.isHorizontalScrollBarEnabled());
3498         assertTrue(view.isVerticalScrollBarEnabled());
3499         int verticalScrollBarWidth = view.getVerticalScrollbarWidth();
3500         int horizontalScrollBarHeight = view.getHorizontalScrollbarHeight();
3501         assertTrue(verticalScrollBarWidth > 0);
3502         assertTrue(horizontalScrollBarHeight > 0);
3503         assertEquals(0, view.getPaddingRight());
3504         assertEquals(0, view.getPaddingBottom());
3505 
3506         view.setScrollBarStyle(View.SCROLLBARS_INSIDE_INSET);
3507         assertEquals(View.SCROLLBARS_INSIDE_INSET, view.getScrollBarStyle());
3508         assertEquals(verticalScrollBarWidth, view.getPaddingRight());
3509         assertEquals(horizontalScrollBarHeight, view.getPaddingBottom());
3510 
3511         view.setScrollBarStyle(View.SCROLLBARS_OUTSIDE_OVERLAY);
3512         assertEquals(View.SCROLLBARS_OUTSIDE_OVERLAY, view.getScrollBarStyle());
3513         assertEquals(0, view.getPaddingRight());
3514         assertEquals(0, view.getPaddingBottom());
3515 
3516         view.setScrollBarStyle(View.SCROLLBARS_OUTSIDE_INSET);
3517         assertEquals(View.SCROLLBARS_OUTSIDE_INSET, view.getScrollBarStyle());
3518         assertEquals(verticalScrollBarWidth, view.getPaddingRight());
3519         assertEquals(horizontalScrollBarHeight, view.getPaddingBottom());
3520 
3521         // TODO: how to get the position of the Scrollbar to assert it is inside or outside.
3522     }
3523 
3524     @UiThreadTest
testScrollFading()3525     public void testScrollFading() {
3526         MockView view = (MockView) mActivity.findViewById(R.id.mock_view);
3527         Bitmap bitmap = Bitmap.createBitmap(200, 300, Bitmap.Config.RGB_565);
3528         BitmapDrawable d = new BitmapDrawable(bitmap);
3529         view.setBackgroundDrawable(d);
3530 
3531         assertFalse(view.isHorizontalFadingEdgeEnabled());
3532         assertFalse(view.isVerticalFadingEdgeEnabled());
3533         assertEquals(0, view.getHorizontalFadingEdgeLength());
3534         assertEquals(0, view.getVerticalFadingEdgeLength());
3535 
3536         view.setHorizontalFadingEdgeEnabled(true);
3537         view.setVerticalFadingEdgeEnabled(true);
3538         assertTrue(view.isHorizontalFadingEdgeEnabled());
3539         assertTrue(view.isVerticalFadingEdgeEnabled());
3540         assertTrue(view.getHorizontalFadingEdgeLength() > 0);
3541         assertTrue(view.getVerticalFadingEdgeLength() > 0);
3542 
3543         final int fadingLength = 20;
3544         view.setFadingEdgeLength(fadingLength);
3545         assertEquals(fadingLength, view.getHorizontalFadingEdgeLength());
3546         assertEquals(fadingLength, view.getVerticalFadingEdgeLength());
3547     }
3548 
3549     @UiThreadTest
testScrolling()3550     public void testScrolling() {
3551         MockView view = (MockView) mActivity.findViewById(R.id.mock_view);
3552         view.reset();
3553         assertEquals(0, view.getScrollX());
3554         assertEquals(0, view.getScrollY());
3555         assertFalse(view.hasCalledOnScrollChanged());
3556 
3557         view.scrollTo(0, 0);
3558         assertEquals(0, view.getScrollX());
3559         assertEquals(0, view.getScrollY());
3560         assertFalse(view.hasCalledOnScrollChanged());
3561 
3562         view.scrollBy(0, 0);
3563         assertEquals(0, view.getScrollX());
3564         assertEquals(0, view.getScrollY());
3565         assertFalse(view.hasCalledOnScrollChanged());
3566 
3567         view.scrollTo(10, 100);
3568         assertEquals(10, view.getScrollX());
3569         assertEquals(100, view.getScrollY());
3570         assertTrue(view.hasCalledOnScrollChanged());
3571 
3572         view.reset();
3573         assertFalse(view.hasCalledOnScrollChanged());
3574         view.scrollBy(-10, -100);
3575         assertEquals(0, view.getScrollX());
3576         assertEquals(0, view.getScrollY());
3577         assertTrue(view.hasCalledOnScrollChanged());
3578 
3579         view.reset();
3580         assertFalse(view.hasCalledOnScrollChanged());
3581         view.scrollTo(-1, -2);
3582         assertEquals(-1, view.getScrollX());
3583         assertEquals(-2, view.getScrollY());
3584         assertTrue(view.hasCalledOnScrollChanged());
3585     }
3586 
testInitializeScrollbarsAndFadingEdge()3587     public void testInitializeScrollbarsAndFadingEdge() {
3588         MockView view = (MockView) mActivity.findViewById(R.id.scroll_view);
3589 
3590         assertTrue(view.isHorizontalScrollBarEnabled());
3591         assertTrue(view.isVerticalScrollBarEnabled());
3592         assertFalse(view.isHorizontalFadingEdgeEnabled());
3593         assertFalse(view.isVerticalFadingEdgeEnabled());
3594 
3595         view = (MockView) mActivity.findViewById(R.id.scroll_view_2);
3596         final int fadingEdgeLength = 20;
3597 
3598         assertTrue(view.isHorizontalScrollBarEnabled());
3599         assertTrue(view.isVerticalScrollBarEnabled());
3600         assertTrue(view.isHorizontalFadingEdgeEnabled());
3601         assertTrue(view.isVerticalFadingEdgeEnabled());
3602         assertEquals(fadingEdgeLength, view.getHorizontalFadingEdgeLength());
3603         assertEquals(fadingEdgeLength, view.getVerticalFadingEdgeLength());
3604     }
3605 
3606     @UiThreadTest
testScrollIndicators()3607     public void testScrollIndicators() {
3608         MockView view = (MockView) mActivity.findViewById(R.id.scroll_view);
3609 
3610         assertEquals("Set indicators match those specified in XML",
3611                 View.SCROLL_INDICATOR_TOP | View.SCROLL_INDICATOR_BOTTOM,
3612                 view.getScrollIndicators());
3613 
3614         view.setScrollIndicators(0);
3615         assertEquals("Cleared indicators", 0, view.getScrollIndicators());
3616 
3617         view.setScrollIndicators(View.SCROLL_INDICATOR_START | View.SCROLL_INDICATOR_RIGHT);
3618         assertEquals("Set start and right indicators",
3619                 View.SCROLL_INDICATOR_START | View.SCROLL_INDICATOR_RIGHT,
3620                 view.getScrollIndicators());
3621 
3622     }
3623 
testOnStartAndFinishTemporaryDetach()3624     public void testOnStartAndFinishTemporaryDetach() throws Throwable {
3625         final MockView view = (MockView) mActivity.findViewById(R.id.mock_view);
3626 
3627         assertFalse(view.isTemporarilyDetached());
3628         assertFalse(view.hasCalledDispatchStartTemporaryDetach());
3629         assertFalse(view.hasCalledDispatchFinishTemporaryDetach());
3630         assertFalse(view.hasCalledOnStartTemporaryDetach());
3631         assertFalse(view.hasCalledOnFinishTemporaryDetach());
3632 
3633         runTestOnUiThread(new Runnable() {
3634             @Override
3635             public void run() {
3636                 view.dispatchStartTemporaryDetach();
3637             }
3638         });
3639         getInstrumentation().waitForIdleSync();
3640 
3641         assertTrue(view.isTemporarilyDetached());
3642         assertTrue(view.hasCalledDispatchStartTemporaryDetach());
3643         assertFalse(view.hasCalledDispatchFinishTemporaryDetach());
3644         assertTrue(view.hasCalledOnStartTemporaryDetach());
3645         assertFalse(view.hasCalledOnFinishTemporaryDetach());
3646 
3647         runTestOnUiThread(new Runnable() {
3648             @Override
3649             public void run() {
3650                 view.dispatchFinishTemporaryDetach();
3651             }
3652         });
3653         getInstrumentation().waitForIdleSync();
3654 
3655         assertFalse(view.isTemporarilyDetached());
3656         assertTrue(view.hasCalledDispatchStartTemporaryDetach());
3657         assertTrue(view.hasCalledDispatchFinishTemporaryDetach());
3658         assertTrue(view.hasCalledOnStartTemporaryDetach());
3659         assertTrue(view.hasCalledOnFinishTemporaryDetach());
3660     }
3661 
testKeyPreIme()3662     public void testKeyPreIme() throws Throwable {
3663         final MockView view = (MockView) mActivity.findViewById(R.id.mock_view);
3664 
3665         runTestOnUiThread(new Runnable() {
3666             @Override
3667             public void run() {
3668                 view.setFocusable(true);
3669                 view.requestFocus();
3670             }
3671         });
3672         getInstrumentation().waitForIdleSync();
3673 
3674         getInstrumentation().sendKeySync(new KeyEvent(KeyEvent.ACTION_DOWN, KeyEvent.KEYCODE_BACK));
3675         assertTrue(view.hasCalledDispatchKeyEventPreIme());
3676         assertTrue(view.hasCalledOnKeyPreIme());
3677     }
3678 
testHapticFeedback()3679     public void testHapticFeedback() {
3680         Vibrator vib = (Vibrator) mActivity.getSystemService(Context.VIBRATOR_SERVICE);
3681         boolean hasVibrator = vib.hasVibrator();
3682 
3683         final MockView view = (MockView) mActivity.findViewById(R.id.mock_view);
3684         final int LONG_PRESS = HapticFeedbackConstants.LONG_PRESS;
3685         final int FLAG_IGNORE_VIEW_SETTING = HapticFeedbackConstants.FLAG_IGNORE_VIEW_SETTING;
3686         final int FLAG_IGNORE_GLOBAL_SETTING = HapticFeedbackConstants.FLAG_IGNORE_GLOBAL_SETTING;
3687         final int ALWAYS = FLAG_IGNORE_VIEW_SETTING | FLAG_IGNORE_GLOBAL_SETTING;
3688 
3689         view.setHapticFeedbackEnabled(false);
3690         assertFalse(view.isHapticFeedbackEnabled());
3691         assertFalse(view.performHapticFeedback(LONG_PRESS));
3692         assertFalse(view.performHapticFeedback(LONG_PRESS, FLAG_IGNORE_GLOBAL_SETTING));
3693         assertEquals(hasVibrator, view.performHapticFeedback(LONG_PRESS, ALWAYS));
3694 
3695         view.setHapticFeedbackEnabled(true);
3696         assertTrue(view.isHapticFeedbackEnabled());
3697         assertEquals(hasVibrator, view.performHapticFeedback(LONG_PRESS, FLAG_IGNORE_GLOBAL_SETTING));
3698     }
3699 
testInputConnection()3700     public void testInputConnection() throws Throwable {
3701         final InputMethodManager imm = (InputMethodManager)getActivity().getSystemService(
3702                 Context.INPUT_METHOD_SERVICE);
3703         final MockView view = (MockView) mActivity.findViewById(R.id.mock_view);
3704         final ViewGroup viewGroup = (ViewGroup) mActivity.findViewById(R.id.viewlayout_root);
3705         final MockEditText editText = new MockEditText(mActivity);
3706 
3707         runTestOnUiThread(new Runnable() {
3708             @Override
3709             public void run() {
3710                 viewGroup.addView(editText);
3711                 editText.requestFocus();
3712             }
3713         });
3714         getInstrumentation().waitForIdleSync();
3715         assertTrue(editText.isFocused());
3716 
3717         runTestOnUiThread(new Runnable() {
3718             @Override
3719             public void run() {
3720                 imm.showSoftInput(editText, 0);
3721             }
3722         });
3723         getInstrumentation().waitForIdleSync();
3724 
3725         new PollingCheck(TIMEOUT_DELTA) {
3726             @Override
3727             protected boolean check() {
3728                 return editText.hasCalledOnCreateInputConnection();
3729             }
3730         }.run();
3731 
3732         assertTrue(editText.hasCalledOnCheckIsTextEditor());
3733 
3734         runTestOnUiThread(new Runnable() {
3735             @Override
3736             public void run() {
3737                 assertTrue(imm.isActive(editText));
3738                 assertFalse(editText.hasCalledCheckInputConnectionProxy());
3739                 imm.isActive(view);
3740                 assertTrue(editText.hasCalledCheckInputConnectionProxy());
3741             }
3742         });
3743     }
3744 
testFilterTouchesWhenObscured()3745     public void testFilterTouchesWhenObscured() throws Throwable {
3746         OnTouchListenerImpl touchListener = new OnTouchListenerImpl();
3747         View view = new View(mActivity);
3748         view.setOnTouchListener(touchListener);
3749 
3750         MotionEvent.PointerProperties[] props = new MotionEvent.PointerProperties[] {
3751                 new MotionEvent.PointerProperties()
3752         };
3753         MotionEvent.PointerCoords[] coords = new MotionEvent.PointerCoords[] {
3754                 new MotionEvent.PointerCoords()
3755         };
3756         MotionEvent obscuredTouch = MotionEvent.obtain(0, 0, MotionEvent.ACTION_DOWN,
3757                 1, props, coords, 0, 0, 0, 0, -1, 0, InputDevice.SOURCE_TOUCHSCREEN,
3758                 MotionEvent.FLAG_WINDOW_IS_OBSCURED);
3759         MotionEvent unobscuredTouch = MotionEvent.obtain(0, 0, MotionEvent.ACTION_DOWN,
3760                 1, props, coords, 0, 0, 0, 0, -1, 0, InputDevice.SOURCE_TOUCHSCREEN,
3761                 0);
3762 
3763         // Initially filter touches is false so all touches are dispatched.
3764         assertFalse(view.getFilterTouchesWhenObscured());
3765 
3766         view.dispatchTouchEvent(unobscuredTouch);
3767         assertTrue(touchListener.hasOnTouch());
3768         touchListener.reset();
3769         view.dispatchTouchEvent(obscuredTouch);
3770         assertTrue(touchListener.hasOnTouch());
3771         touchListener.reset();
3772 
3773         // Set filter touches to true so only unobscured touches are dispatched.
3774         view.setFilterTouchesWhenObscured(true);
3775         assertTrue(view.getFilterTouchesWhenObscured());
3776 
3777         view.dispatchTouchEvent(unobscuredTouch);
3778         assertTrue(touchListener.hasOnTouch());
3779         touchListener.reset();
3780         view.dispatchTouchEvent(obscuredTouch);
3781         assertFalse(touchListener.hasOnTouch());
3782         touchListener.reset();
3783 
3784         // Set filter touches to false so all touches are dispatched.
3785         view.setFilterTouchesWhenObscured(false);
3786         assertFalse(view.getFilterTouchesWhenObscured());
3787 
3788         view.dispatchTouchEvent(unobscuredTouch);
3789         assertTrue(touchListener.hasOnTouch());
3790         touchListener.reset();
3791         view.dispatchTouchEvent(obscuredTouch);
3792         assertTrue(touchListener.hasOnTouch());
3793         touchListener.reset();
3794     }
3795 
testBackgroundTint()3796     public void testBackgroundTint() {
3797         View inflatedView = mActivity.findViewById(R.id.background_tint);
3798 
3799         assertEquals("Background tint inflated correctly",
3800                 Color.WHITE, inflatedView.getBackgroundTintList().getDefaultColor());
3801         assertEquals("Background tint mode inflated correctly",
3802                 PorterDuff.Mode.SRC_OVER, inflatedView.getBackgroundTintMode());
3803 
3804         MockDrawable bg = new MockDrawable();
3805         View view = new View(mActivity);
3806 
3807         view.setBackground(bg);
3808         assertFalse("No background tint applied by default", bg.hasCalledSetTint());
3809 
3810         view.setBackgroundTintList(ColorStateList.valueOf(Color.WHITE));
3811         assertTrue("Background tint applied when setBackgroundTints() called after setBackground()",
3812                 bg.hasCalledSetTint());
3813 
3814         bg.reset();
3815         view.setBackground(null);
3816         view.setBackground(bg);
3817         assertTrue("Background tint applied when setBackgroundTints() called before setBackground()",
3818                 bg.hasCalledSetTint());
3819     }
3820 
testStartActionModeWithParent()3821     public void testStartActionModeWithParent() {
3822         View view = new View(mActivity);
3823         MockViewGroup parent = new MockViewGroup(mActivity);
3824         parent.addView(view);
3825 
3826         ActionMode mode = view.startActionMode(null);
3827 
3828         assertNotNull(mode);
3829         assertEquals(NO_OP_ACTION_MODE, mode);
3830         assertTrue(parent.isStartActionModeForChildCalled);
3831         assertEquals(ActionMode.TYPE_PRIMARY, parent.startActionModeForChildType);
3832     }
3833 
testStartActionModeWithoutParent()3834     public void testStartActionModeWithoutParent() {
3835         View view = new View(mActivity);
3836 
3837         ActionMode mode = view.startActionMode(null);
3838 
3839         assertNull(mode);
3840     }
3841 
testStartActionModeTypedWithParent()3842     public void testStartActionModeTypedWithParent() {
3843         View view = new View(mActivity);
3844         MockViewGroup parent = new MockViewGroup(mActivity);
3845         parent.addView(view);
3846 
3847         ActionMode mode = view.startActionMode(null, ActionMode.TYPE_FLOATING);
3848 
3849         assertNotNull(mode);
3850         assertEquals(NO_OP_ACTION_MODE, mode);
3851         assertTrue(parent.isStartActionModeForChildCalled);
3852         assertEquals(ActionMode.TYPE_FLOATING, parent.startActionModeForChildType);
3853     }
3854 
testStartActionModeTypedWithoutParent()3855     public void testStartActionModeTypedWithoutParent() {
3856         View view = new View(mActivity);
3857 
3858         ActionMode mode = view.startActionMode(null, ActionMode.TYPE_FLOATING);
3859 
3860         assertNull(mode);
3861     }
3862 
testVisibilityAggregated()3863     public void testVisibilityAggregated() throws Throwable {
3864         final View grandparent = mActivity.findViewById(R.id.viewlayout_root);
3865         final View parent = mActivity.findViewById(R.id.aggregate_visibility_parent);
3866         final MockView mv = (MockView) mActivity.findViewById(R.id.mock_view_aggregate_visibility);
3867 
3868         assertEquals(parent, mv.getParent());
3869         assertEquals(grandparent, parent.getParent());
3870 
3871         assertTrue(mv.hasCalledOnVisibilityAggregated());
3872         assertTrue(mv.getLastAggregatedVisibility());
3873 
3874         final Runnable reset = new Runnable() {
3875             @Override
3876             public void run() {
3877                 grandparent.setVisibility(View.VISIBLE);
3878                 parent.setVisibility(View.VISIBLE);
3879                 mv.setVisibility(View.VISIBLE);
3880                 mv.reset();
3881             }
3882         };
3883 
3884         runTestOnUiThread(reset);
3885 
3886         setVisibilityOnUiThread(parent, View.GONE);
3887 
3888         assertTrue(mv.hasCalledOnVisibilityAggregated());
3889         assertFalse(mv.getLastAggregatedVisibility());
3890 
3891         runTestOnUiThread(reset);
3892 
3893         setVisibilityOnUiThread(grandparent, View.GONE);
3894 
3895         assertTrue(mv.hasCalledOnVisibilityAggregated());
3896         assertFalse(mv.getLastAggregatedVisibility());
3897 
3898         runTestOnUiThread(reset);
3899         runTestOnUiThread(new Runnable() {
3900             @Override
3901             public void run() {
3902                 grandparent.setVisibility(View.GONE);
3903                 parent.setVisibility(View.GONE);
3904                 mv.setVisibility(View.VISIBLE);
3905 
3906                 grandparent.setVisibility(View.VISIBLE);
3907             }
3908         });
3909 
3910         assertTrue(mv.hasCalledOnVisibilityAggregated());
3911         assertFalse(mv.getLastAggregatedVisibility());
3912 
3913         runTestOnUiThread(reset);
3914         runTestOnUiThread(new Runnable() {
3915             @Override
3916             public void run() {
3917                 grandparent.setVisibility(View.GONE);
3918                 parent.setVisibility(View.INVISIBLE);
3919 
3920                 grandparent.setVisibility(View.VISIBLE);
3921             }
3922         });
3923 
3924         assertTrue(mv.hasCalledOnVisibilityAggregated());
3925         assertFalse(mv.getLastAggregatedVisibility());
3926 
3927         runTestOnUiThread(new Runnable() {
3928             @Override
3929             public void run() {
3930                 parent.setVisibility(View.VISIBLE);
3931             }
3932         });
3933 
3934         assertTrue(mv.getLastAggregatedVisibility());
3935     }
3936 
testOverlappingRendering()3937     public void testOverlappingRendering() {
3938         View overlappingUnsetView = mActivity.findViewById(R.id.overlapping_rendering_unset);
3939         View overlappingFalseView = mActivity.findViewById(R.id.overlapping_rendering_false);
3940         View overlappingTrueView = mActivity.findViewById(R.id.overlapping_rendering_true);
3941 
3942         assertTrue(overlappingUnsetView.hasOverlappingRendering());
3943         assertTrue(overlappingUnsetView.getHasOverlappingRendering());
3944         overlappingUnsetView.forceHasOverlappingRendering(false);
3945         assertTrue(overlappingUnsetView.hasOverlappingRendering());
3946         assertFalse(overlappingUnsetView.getHasOverlappingRendering());
3947         overlappingUnsetView.forceHasOverlappingRendering(true);
3948         assertTrue(overlappingUnsetView.hasOverlappingRendering());
3949         assertTrue(overlappingUnsetView.getHasOverlappingRendering());
3950 
3951         assertTrue(overlappingTrueView.hasOverlappingRendering());
3952         assertTrue(overlappingTrueView.getHasOverlappingRendering());
3953 
3954         assertTrue(overlappingFalseView.hasOverlappingRendering());
3955         assertFalse(overlappingFalseView.getHasOverlappingRendering());
3956 
3957         View overridingView = new MockOverlappingRenderingSubclass(mActivity, false);
3958         assertFalse(overridingView.hasOverlappingRendering());
3959 
3960         overridingView = new MockOverlappingRenderingSubclass(mActivity, true);
3961         assertTrue(overridingView.hasOverlappingRendering());
3962         overridingView.forceHasOverlappingRendering(false);
3963         assertFalse(overridingView.getHasOverlappingRendering());
3964         assertTrue(overridingView.hasOverlappingRendering());
3965         overridingView.forceHasOverlappingRendering(true);
3966         assertTrue(overridingView.getHasOverlappingRendering());
3967         assertTrue(overridingView.hasOverlappingRendering());
3968     }
3969 
setVisibilityOnUiThread(final View view, final int visibility)3970     private void setVisibilityOnUiThread(final View view, final int visibility) throws Throwable {
3971         runTestOnUiThread(new Runnable() {
3972             @Override
3973             public void run() {
3974                 view.setVisibility(visibility);
3975             }
3976         });
3977     }
3978 
3979     private static class MockOverlappingRenderingSubclass extends View {
3980         boolean mOverlap;
3981 
MockOverlappingRenderingSubclass(Context context, boolean overlap)3982         public MockOverlappingRenderingSubclass(Context context, boolean overlap) {
3983             super(context);
3984             mOverlap = overlap;
3985         }
3986 
3987         @Override
hasOverlappingRendering()3988         public boolean hasOverlappingRendering() {
3989             return mOverlap;
3990         }
3991     }
3992 
3993     private static class MockViewGroup extends ViewGroup {
3994         boolean isStartActionModeForChildCalled = false;
3995         int startActionModeForChildType = ActionMode.TYPE_PRIMARY;
3996 
MockViewGroup(Context context)3997         public MockViewGroup(Context context) {
3998             super(context);
3999         }
4000 
4001         @Override
startActionModeForChild(View originalView, ActionMode.Callback callback)4002         public ActionMode startActionModeForChild(View originalView, ActionMode.Callback callback) {
4003             isStartActionModeForChildCalled = true;
4004             startActionModeForChildType = ActionMode.TYPE_PRIMARY;
4005             return NO_OP_ACTION_MODE;
4006         }
4007 
4008         @Override
startActionModeForChild( View originalView, ActionMode.Callback callback, int type)4009         public ActionMode startActionModeForChild(
4010                 View originalView, ActionMode.Callback callback, int type) {
4011             isStartActionModeForChildCalled = true;
4012             startActionModeForChildType = type;
4013             return NO_OP_ACTION_MODE;
4014         }
4015 
4016         @Override
onLayout(boolean changed, int l, int t, int r, int b)4017         protected void onLayout(boolean changed, int l, int t, int r, int b) {
4018             // no-op
4019         }
4020     }
4021 
4022     private static final ActionMode NO_OP_ACTION_MODE =
4023             new ActionMode() {
4024                 @Override
4025                 public void setTitle(CharSequence title) {}
4026 
4027                 @Override
4028                 public void setTitle(int resId) {}
4029 
4030                 @Override
4031                 public void setSubtitle(CharSequence subtitle) {}
4032 
4033                 @Override
4034                 public void setSubtitle(int resId) {}
4035 
4036                 @Override
4037                 public void setCustomView(View view) {}
4038 
4039                 @Override
4040                 public void invalidate() {}
4041 
4042                 @Override
4043                 public void finish() {}
4044 
4045                 @Override
4046                 public Menu getMenu() {
4047                     return null;
4048                 }
4049 
4050                 @Override
4051                 public CharSequence getTitle() {
4052                     return null;
4053                 }
4054 
4055                 @Override
4056                 public CharSequence getSubtitle() {
4057                     return null;
4058                 }
4059 
4060                 @Override
4061                 public View getCustomView() {
4062                     return null;
4063                 }
4064 
4065                 @Override
4066                 public MenuInflater getMenuInflater() {
4067                     return null;
4068                 }
4069             };
4070 
testTranslationSetter()4071     public void testTranslationSetter() {
4072         View view = new View(mActivity);
4073         float offset = 10.0f;
4074         view.setTranslationX(offset);
4075         view.setTranslationY(offset);
4076         view.setTranslationZ(offset);
4077         view.setElevation(offset);
4078 
4079         assertEquals("Incorrect translationX", offset, view.getTranslationX());
4080         assertEquals("Incorrect translationY", offset, view.getTranslationY());
4081         assertEquals("Incorrect translationZ", offset, view.getTranslationZ());
4082         assertEquals("Incorrect elevation", offset, view.getElevation());
4083     }
4084 
testXYZ()4085     public void testXYZ() {
4086         View view = new View(mActivity);
4087         float offset = 10.0f;
4088         float start = 15.0f;
4089         view.setTranslationX(offset);
4090         view.setLeft((int) start);
4091         view.setTranslationY(offset);
4092         view.setTop((int) start);
4093         view.setTranslationZ(offset);
4094         view.setElevation(start);
4095 
4096         assertEquals("Incorrect X value", offset + start, view.getX());
4097         assertEquals("Incorrect Y value", offset + start, view.getY());
4098         assertEquals("Incorrect Z value", offset + start, view.getZ());
4099     }
4100 
4101     private static class MockDrawable extends Drawable {
4102         private boolean mCalledSetTint = false;
4103 
4104         @Override
draw(Canvas canvas)4105         public void draw(Canvas canvas) {}
4106 
4107         @Override
setAlpha(int alpha)4108         public void setAlpha(int alpha) {}
4109 
4110         @Override
setColorFilter(ColorFilter cf)4111         public void setColorFilter(ColorFilter cf) {}
4112 
4113         @Override
getOpacity()4114         public int getOpacity() {
4115             return 0;
4116         }
4117 
4118         @Override
setTintList(ColorStateList tint)4119         public void setTintList(ColorStateList tint) {
4120             super.setTintList(tint);
4121             mCalledSetTint = true;
4122         }
4123 
hasCalledSetTint()4124         public boolean hasCalledSetTint() {
4125             return mCalledSetTint;
4126         }
4127 
reset()4128         public void reset() {
4129             mCalledSetTint = false;
4130         }
4131     }
4132 
4133     private static class MockEditText extends EditText {
4134         private boolean mCalledCheckInputConnectionProxy = false;
4135         private boolean mCalledOnCreateInputConnection = false;
4136         private boolean mCalledOnCheckIsTextEditor = false;
4137 
MockEditText(Context context)4138         public MockEditText(Context context) {
4139             super(context);
4140         }
4141 
4142         @Override
checkInputConnectionProxy(View view)4143         public boolean checkInputConnectionProxy(View view) {
4144             mCalledCheckInputConnectionProxy = true;
4145             return super.checkInputConnectionProxy(view);
4146         }
4147 
hasCalledCheckInputConnectionProxy()4148         public boolean hasCalledCheckInputConnectionProxy() {
4149             return mCalledCheckInputConnectionProxy;
4150         }
4151 
4152         @Override
onCreateInputConnection(EditorInfo outAttrs)4153         public InputConnection onCreateInputConnection(EditorInfo outAttrs) {
4154             mCalledOnCreateInputConnection = true;
4155             return super.onCreateInputConnection(outAttrs);
4156         }
4157 
hasCalledOnCreateInputConnection()4158         public boolean hasCalledOnCreateInputConnection() {
4159             return mCalledOnCreateInputConnection;
4160         }
4161 
4162         @Override
onCheckIsTextEditor()4163         public boolean onCheckIsTextEditor() {
4164             mCalledOnCheckIsTextEditor = true;
4165             return super.onCheckIsTextEditor();
4166         }
4167 
hasCalledOnCheckIsTextEditor()4168         public boolean hasCalledOnCheckIsTextEditor() {
4169             return mCalledOnCheckIsTextEditor;
4170         }
4171 
reset()4172         public void reset() {
4173             mCalledCheckInputConnectionProxy = false;
4174             mCalledOnCreateInputConnection = false;
4175             mCalledOnCheckIsTextEditor = false;
4176         }
4177     }
4178 
4179     private final static class MockViewParent extends ViewGroup {
4180         private boolean mHasRequestLayout = false;
4181         private boolean mHasCreateContextMenu = false;
4182         private boolean mHasShowContextMenuForChild = false;
4183         private boolean mHasShowContextMenuForChildXY = false;
4184         private boolean mHasChildDrawableStateChanged = false;
4185         private boolean mHasBroughtChildToFront = false;
4186 
4187         private final static int[] DEFAULT_PARENT_STATE_SET = new int[] { 789 };
4188 
4189         @Override
requestChildRectangleOnScreen(View child, Rect rectangle, boolean immediate)4190         public boolean requestChildRectangleOnScreen(View child, Rect rectangle,
4191                 boolean immediate) {
4192             return false;
4193         }
4194 
MockViewParent(Context context)4195         public MockViewParent(Context context) {
4196             super(context);
4197         }
4198 
4199         @Override
bringChildToFront(View child)4200         public void bringChildToFront(View child) {
4201             mHasBroughtChildToFront = true;
4202         }
4203 
hasBroughtChildToFront()4204         public boolean hasBroughtChildToFront() {
4205             return mHasBroughtChildToFront;
4206         }
4207 
4208         @Override
childDrawableStateChanged(View child)4209         public void childDrawableStateChanged(View child) {
4210             mHasChildDrawableStateChanged = true;
4211         }
4212 
hasChildDrawableStateChanged()4213         public boolean hasChildDrawableStateChanged() {
4214             return mHasChildDrawableStateChanged;
4215         }
4216 
4217         @Override
dispatchSetPressed(boolean pressed)4218         public void dispatchSetPressed(boolean pressed) {
4219             super.dispatchSetPressed(pressed);
4220         }
4221 
4222         @Override
dispatchSetSelected(boolean selected)4223         public void dispatchSetSelected(boolean selected) {
4224             super.dispatchSetSelected(selected);
4225         }
4226 
4227         @Override
clearChildFocus(View child)4228         public void clearChildFocus(View child) {
4229 
4230         }
4231 
4232         @Override
createContextMenu(ContextMenu menu)4233         public void createContextMenu(ContextMenu menu) {
4234             mHasCreateContextMenu = true;
4235         }
4236 
hasCreateContextMenu()4237         public boolean hasCreateContextMenu() {
4238             return mHasCreateContextMenu;
4239         }
4240 
4241         @Override
focusSearch(View v, int direction)4242         public View focusSearch(View v, int direction) {
4243             return v;
4244         }
4245 
4246         @Override
focusableViewAvailable(View v)4247         public void focusableViewAvailable(View v) {
4248 
4249         }
4250 
4251         @Override
getChildVisibleRect(View child, Rect r, Point offset)4252         public boolean getChildVisibleRect(View child, Rect r, Point offset) {
4253             return false;
4254         }
4255 
4256         @Override
onLayout(boolean changed, int l, int t, int r, int b)4257         protected void onLayout(boolean changed, int l, int t, int r, int b) {
4258 
4259         }
4260 
4261         @Override
invalidateChildInParent(int[] location, Rect r)4262         public ViewParent invalidateChildInParent(int[] location, Rect r) {
4263             return null;
4264         }
4265 
4266         @Override
isLayoutRequested()4267         public boolean isLayoutRequested() {
4268             return false;
4269         }
4270 
4271         @Override
recomputeViewAttributes(View child)4272         public void recomputeViewAttributes(View child) {
4273 
4274         }
4275 
4276         @Override
requestChildFocus(View child, View focused)4277         public void requestChildFocus(View child, View focused) {
4278 
4279         }
4280 
4281         @Override
requestDisallowInterceptTouchEvent(boolean disallowIntercept)4282         public void requestDisallowInterceptTouchEvent(boolean disallowIntercept) {
4283 
4284         }
4285 
4286         @Override
requestLayout()4287         public void requestLayout() {
4288             mHasRequestLayout = true;
4289         }
4290 
hasRequestLayout()4291         public boolean hasRequestLayout() {
4292             return mHasRequestLayout;
4293         }
4294 
4295         @Override
requestTransparentRegion(View child)4296         public void requestTransparentRegion(View child) {
4297 
4298         }
4299 
4300         @Override
showContextMenuForChild(View originalView)4301         public boolean showContextMenuForChild(View originalView) {
4302             mHasShowContextMenuForChild = true;
4303             return false;
4304         }
4305 
4306         @Override
showContextMenuForChild(View originalView, float x, float y)4307         public boolean showContextMenuForChild(View originalView, float x, float y) {
4308             mHasShowContextMenuForChildXY = true;
4309             return false;
4310         }
4311 
4312         @Override
startActionModeForChild(View originalView, ActionMode.Callback callback)4313         public ActionMode startActionModeForChild(View originalView,
4314                 ActionMode.Callback callback) {
4315             return null;
4316         }
4317 
4318         @Override
startActionModeForChild(View originalView, ActionMode.Callback callback, int type)4319         public ActionMode startActionModeForChild(View originalView,
4320                 ActionMode.Callback callback, int type) {
4321             return null;
4322         }
4323 
hasShowContextMenuForChild()4324         public boolean hasShowContextMenuForChild() {
4325             return mHasShowContextMenuForChild;
4326         }
4327 
hasShowContextMenuForChildXY()4328         public boolean hasShowContextMenuForChildXY() {
4329             return mHasShowContextMenuForChildXY;
4330         }
4331 
4332         @Override
onCreateDrawableState(int extraSpace)4333         protected int[] onCreateDrawableState(int extraSpace) {
4334             return DEFAULT_PARENT_STATE_SET;
4335         }
4336 
4337         @Override
requestSendAccessibilityEvent(View child, AccessibilityEvent event)4338         public boolean requestSendAccessibilityEvent(View child, AccessibilityEvent event) {
4339             return false;
4340         }
4341 
reset()4342         public void reset() {
4343             mHasRequestLayout = false;
4344             mHasCreateContextMenu = false;
4345             mHasShowContextMenuForChild = false;
4346             mHasShowContextMenuForChildXY = false;
4347             mHasChildDrawableStateChanged = false;
4348             mHasBroughtChildToFront = false;
4349         }
4350 
4351         @Override
childHasTransientStateChanged(View child, boolean hasTransientState)4352         public void childHasTransientStateChanged(View child, boolean hasTransientState) {
4353 
4354         }
4355 
4356         @Override
getParentForAccessibility()4357         public ViewParent getParentForAccessibility() {
4358             return null;
4359         }
4360 
4361         @Override
notifySubtreeAccessibilityStateChanged(View child, View source, int changeType)4362         public void notifySubtreeAccessibilityStateChanged(View child,
4363             View source, int changeType) {
4364 
4365         }
4366 
4367         @Override
onStartNestedScroll(View child, View target, int nestedScrollAxes)4368         public boolean onStartNestedScroll(View child, View target, int nestedScrollAxes) {
4369             return false;
4370         }
4371 
4372         @Override
onNestedScrollAccepted(View child, View target, int nestedScrollAxes)4373         public void onNestedScrollAccepted(View child, View target, int nestedScrollAxes) {
4374         }
4375 
4376         @Override
onStopNestedScroll(View target)4377         public void onStopNestedScroll(View target) {
4378         }
4379 
4380         @Override
onNestedScroll(View target, int dxConsumed, int dyConsumed, int dxUnconsumed, int dyUnconsumed)4381         public void onNestedScroll(View target, int dxConsumed, int dyConsumed,
4382                                    int dxUnconsumed, int dyUnconsumed) {
4383         }
4384 
4385         @Override
onNestedPreScroll(View target, int dx, int dy, int[] consumed)4386         public void onNestedPreScroll(View target, int dx, int dy, int[] consumed) {
4387         }
4388 
4389         @Override
onNestedFling(View target, float velocityX, float velocityY, boolean consumed)4390         public boolean onNestedFling(View target, float velocityX, float velocityY,
4391                 boolean consumed) {
4392             return false;
4393         }
4394 
4395         @Override
onNestedPreFling(View target, float velocityX, float velocityY)4396         public boolean onNestedPreFling(View target, float velocityX, float velocityY) {
4397             return false;
4398         }
4399 
4400         @Override
onNestedPrePerformAccessibilityAction(View target, int action, Bundle args)4401         public boolean onNestedPrePerformAccessibilityAction(View target, int action, Bundle args) {
4402             return false;
4403         }
4404     }
4405 
4406     private final class OnCreateContextMenuListenerImpl implements OnCreateContextMenuListener {
4407         private boolean mHasOnCreateContextMenu = false;
4408 
4409         @Override
onCreateContextMenu(ContextMenu menu, View v, ContextMenuInfo menuInfo)4410         public void onCreateContextMenu(ContextMenu menu, View v, ContextMenuInfo menuInfo) {
4411             mHasOnCreateContextMenu = true;
4412         }
4413 
hasOnCreateContextMenu()4414         public boolean hasOnCreateContextMenu() {
4415             return mHasOnCreateContextMenu;
4416         }
4417 
reset()4418         public void reset() {
4419             mHasOnCreateContextMenu = false;
4420         }
4421     }
4422 
4423     private static class MockViewGroupParent extends ViewGroup implements ViewParent {
4424         private boolean mHasRequestChildRectangleOnScreen = false;
4425         private Rect mLastRequestedChildRectOnScreen = new Rect(
4426                 Integer.MIN_VALUE, Integer.MIN_VALUE, Integer.MIN_VALUE, Integer.MIN_VALUE);
4427 
MockViewGroupParent(Context context)4428         public MockViewGroupParent(Context context) {
4429             super(context);
4430         }
4431 
4432         @Override
onLayout(boolean changed, int l, int t, int r, int b)4433         protected void onLayout(boolean changed, int l, int t, int r, int b) {
4434 
4435         }
4436 
4437         @Override
requestChildRectangleOnScreen(View child, Rect rectangle, boolean immediate)4438         public boolean requestChildRectangleOnScreen(View child,
4439                 Rect rectangle, boolean immediate) {
4440             mHasRequestChildRectangleOnScreen = true;
4441             mLastRequestedChildRectOnScreen.set(rectangle);
4442             return super.requestChildRectangleOnScreen(child, rectangle, immediate);
4443         }
4444 
getLastRequestedChildRectOnScreen()4445         public Rect getLastRequestedChildRectOnScreen() {
4446             return mLastRequestedChildRectOnScreen;
4447         }
4448 
hasRequestChildRectangleOnScreen()4449         public boolean hasRequestChildRectangleOnScreen() {
4450             return mHasRequestChildRectangleOnScreen;
4451         }
4452 
4453         @Override
detachViewFromParent(View child)4454         protected void detachViewFromParent(View child) {
4455             super.detachViewFromParent(child);
4456         }
4457 
reset()4458         public void reset() {
4459             mHasRequestChildRectangleOnScreen = false;
4460         }
4461     }
4462 
4463     private static final class OnClickListenerImpl implements OnClickListener {
4464         private boolean mHasOnClick = false;
4465 
4466         @Override
onClick(View v)4467         public void onClick(View v) {
4468             mHasOnClick = true;
4469         }
4470 
hasOnClick()4471         public boolean hasOnClick() {
4472             return mHasOnClick;
4473         }
4474 
reset()4475         public void reset() {
4476             mHasOnClick = false;
4477         }
4478     }
4479 
4480     private static final class OnLongClickListenerImpl implements OnLongClickListener {
4481         private boolean mHasOnLongClick = false;
4482 
hasOnLongClick()4483         public boolean hasOnLongClick() {
4484             return mHasOnLongClick;
4485         }
4486 
reset()4487         public void reset() {
4488             mHasOnLongClick = false;
4489         }
4490 
4491         @Override
onLongClick(View v)4492         public boolean onLongClick(View v) {
4493             mHasOnLongClick = true;
4494             return true;
4495         }
4496     }
4497 
4498     private static final class OnContextClickListenerImpl implements OnContextClickListener {
4499         private boolean mHasContextClick = false;
4500         private View mLastViewContextClicked;
4501 
hasOnContextClick()4502         public boolean hasOnContextClick() {
4503             return mHasContextClick;
4504         }
4505 
reset()4506         public void reset() {
4507             mHasContextClick = false;
4508             mLastViewContextClicked = null;
4509         }
4510 
4511         @Override
onContextClick(View v)4512         public boolean onContextClick(View v) {
4513             mHasContextClick = true;
4514             mLastViewContextClicked = v;
4515             return true;
4516         }
4517 
getLastViewContextClicked()4518         public View getLastViewContextClicked() {
4519             return mLastViewContextClicked;
4520         }
4521     }
4522 
4523     private static final class OnFocusChangeListenerImpl implements OnFocusChangeListener {
4524         private boolean mHasOnFocusChange = false;
4525 
4526         @Override
onFocusChange(View v, boolean hasFocus)4527         public void onFocusChange(View v, boolean hasFocus) {
4528             mHasOnFocusChange = true;
4529         }
4530 
hasOnFocusChange()4531         public boolean hasOnFocusChange() {
4532             return mHasOnFocusChange;
4533         }
4534 
reset()4535         public void reset() {
4536             mHasOnFocusChange = false;
4537         }
4538     }
4539 
4540     private static final class OnKeyListenerImpl implements OnKeyListener {
4541         private boolean mHasOnKey = false;
4542 
4543         @Override
onKey(View v, int keyCode, KeyEvent event)4544         public boolean onKey(View v, int keyCode, KeyEvent event) {
4545             mHasOnKey = true;
4546             return true;
4547         }
4548 
reset()4549         public void reset() {
4550             mHasOnKey = false;
4551         }
4552 
hasOnKey()4553         public boolean hasOnKey() {
4554             return mHasOnKey;
4555         }
4556     }
4557 
4558     private static final class OnTouchListenerImpl implements OnTouchListener {
4559         private boolean mHasOnTouch = false;
4560 
4561         @Override
onTouch(View v, MotionEvent event)4562         public boolean onTouch(View v, MotionEvent event) {
4563             mHasOnTouch = true;
4564             return true;
4565         }
4566 
reset()4567         public void reset() {
4568             mHasOnTouch = false;
4569         }
4570 
hasOnTouch()4571         public boolean hasOnTouch() {
4572             return mHasOnTouch;
4573         }
4574     }
4575 
4576     private static final class MockTouchDelegate extends TouchDelegate {
MockTouchDelegate(Rect bounds, View delegateView)4577         public MockTouchDelegate(Rect bounds, View delegateView) {
4578             super(bounds, delegateView);
4579         }
4580 
4581         private boolean mCalledOnTouchEvent = false;
4582 
4583         @Override
onTouchEvent(MotionEvent event)4584         public boolean onTouchEvent(MotionEvent event) {
4585             mCalledOnTouchEvent = true;
4586             return super.onTouchEvent(event);
4587         }
4588 
hasCalledOnTouchEvent()4589         public boolean hasCalledOnTouchEvent() {
4590             return mCalledOnTouchEvent;
4591         }
4592 
reset()4593         public void reset() {
4594             mCalledOnTouchEvent = false;
4595         }
4596     }
4597 
4598     private static final class ViewData {
4599         public int childCount;
4600         public String tag;
4601         public View firstChild;
4602     }
4603 
4604     private static final class MockRunnable implements Runnable {
4605         public boolean hasRun = false;
4606 
4607         @Override
run()4608         public void run() {
4609             hasRun = true;
4610         }
4611     }
4612 
4613     private static final Class<?> ASYNC_INFLATE_VIEWS[] = {
4614         android.app.FragmentBreadCrumbs.class,
4615 // DISABLED because it doesn't have a AppWidgetHostView(Context, AttributeSet)
4616 // constructor, so it's not inflate-able
4617 //        android.appwidget.AppWidgetHostView.class,
4618         android.gesture.GestureOverlayView.class,
4619         android.inputmethodservice.ExtractEditText.class,
4620         android.inputmethodservice.KeyboardView.class,
4621 //        android.media.tv.TvView.class,
4622 //        android.opengl.GLSurfaceView.class,
4623 //        android.view.SurfaceView.class,
4624         android.view.TextureView.class,
4625         android.view.ViewStub.class,
4626 //        android.webkit.WebView.class,
4627         android.widget.AbsoluteLayout.class,
4628         android.widget.AdapterViewFlipper.class,
4629         android.widget.AnalogClock.class,
4630         android.widget.AutoCompleteTextView.class,
4631         android.widget.Button.class,
4632         android.widget.CalendarView.class,
4633         android.widget.CheckBox.class,
4634         android.widget.CheckedTextView.class,
4635         android.widget.Chronometer.class,
4636         android.widget.DatePicker.class,
4637         android.widget.DialerFilter.class,
4638         android.widget.DigitalClock.class,
4639         android.widget.EditText.class,
4640         android.widget.ExpandableListView.class,
4641         android.widget.FrameLayout.class,
4642         android.widget.Gallery.class,
4643         android.widget.GridView.class,
4644         android.widget.HorizontalScrollView.class,
4645         android.widget.ImageButton.class,
4646         android.widget.ImageSwitcher.class,
4647         android.widget.ImageView.class,
4648         android.widget.LinearLayout.class,
4649         android.widget.ListView.class,
4650         android.widget.MediaController.class,
4651         android.widget.MultiAutoCompleteTextView.class,
4652         android.widget.NumberPicker.class,
4653         android.widget.ProgressBar.class,
4654         android.widget.QuickContactBadge.class,
4655         android.widget.RadioButton.class,
4656         android.widget.RadioGroup.class,
4657         android.widget.RatingBar.class,
4658         android.widget.RelativeLayout.class,
4659         android.widget.ScrollView.class,
4660         android.widget.SeekBar.class,
4661 // DISABLED because it has required attributes
4662 //        android.widget.SlidingDrawer.class,
4663         android.widget.Spinner.class,
4664         android.widget.StackView.class,
4665         android.widget.Switch.class,
4666         android.widget.TabHost.class,
4667         android.widget.TabWidget.class,
4668         android.widget.TableLayout.class,
4669         android.widget.TableRow.class,
4670         android.widget.TextClock.class,
4671         android.widget.TextSwitcher.class,
4672         android.widget.TextView.class,
4673         android.widget.TimePicker.class,
4674         android.widget.ToggleButton.class,
4675         android.widget.TwoLineListItem.class,
4676 //        android.widget.VideoView.class,
4677         android.widget.ViewAnimator.class,
4678         android.widget.ViewFlipper.class,
4679         android.widget.ViewSwitcher.class,
4680         android.widget.ZoomButton.class,
4681         android.widget.ZoomControls.class,
4682     };
4683 }
4684