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 android.view.cts.util.XmlUtils;
20 
21 
22 import android.content.Context;
23 import android.content.Intent;
24 import android.cts.util.CTSResult;
25 import android.content.res.XmlResourceParser;
26 import android.graphics.Bitmap;
27 import android.graphics.Canvas;
28 import android.graphics.Point;
29 import android.graphics.Rect;
30 import android.graphics.Region;
31 import android.graphics.Bitmap.Config;
32 import android.graphics.drawable.BitmapDrawable;
33 import android.os.Parcelable;
34 import android.os.SystemClock;
35 import android.test.InstrumentationTestCase;
36 import android.util.AttributeSet;
37 import android.util.DisplayMetrics;
38 import android.util.SparseArray;
39 import android.view.ActionMode;
40 import android.view.Display;
41 import android.view.KeyEvent;
42 import android.view.Menu;
43 import android.view.MenuInflater;
44 import android.view.MenuItem;
45 import android.view.MotionEvent;
46 import android.view.View;
47 import android.view.ViewGroup;
48 import android.view.WindowManager;
49 import android.view.View.BaseSavedState;
50 import android.view.View.MeasureSpec;
51 import android.view.View.OnTouchListener;
52 import android.view.ViewGroup.LayoutParams;
53 import android.view.ViewGroup.OnHierarchyChangeListener;
54 import android.view.animation.AlphaAnimation;
55 import android.view.animation.Animation;
56 import android.view.animation.LayoutAnimationController;
57 import android.view.animation.RotateAnimation;
58 import android.view.animation.Transformation;
59 import android.view.animation.Animation.AnimationListener;
60 import android.widget.TextView;
61 
62 import java.util.ArrayList;
63 
64 public class ViewGroupTest extends InstrumentationTestCase implements CTSResult{
65 
66     private Context mContext;
67     private MotionEvent mMotionEvent;
68     private int mResultCode;
69 
70     private Sync mSync = new Sync();
71     private static class Sync {
72         boolean mHasNotify;
73     }
74 
75     @Override
setUp()76     protected void setUp() throws Exception {
77         super.setUp();
78         mContext = getInstrumentation().getTargetContext();
79     }
80 
testConstructor()81     public void testConstructor() {
82         new MockViewGroup(mContext);
83         new MockViewGroup(mContext, null);
84         new MockViewGroup(mContext, null, 0);
85     }
86 
testAddFocusables()87     public void testAddFocusables() {
88         MockViewGroup vg = new MockViewGroup(mContext);
89         vg.setFocusable(true);
90 
91         ArrayList<View> list = new ArrayList<View>();
92         TextView textView = new TextView(mContext);
93         list.add(textView);
94         vg.addView(textView);
95         vg.addFocusables(list, 0);
96 
97         assertEquals(2, list.size());
98 
99         list = new ArrayList<View>();
100         list.add(textView);
101         vg.setDescendantFocusability(ViewGroup.FOCUS_BLOCK_DESCENDANTS);
102         vg.setFocusable(false);
103         vg.addFocusables(list, 0);
104         assertEquals(1, list.size());
105     }
106 
testAddStatesFromChildren()107     public void testAddStatesFromChildren() {
108         MockViewGroup vg = new MockViewGroup(mContext);
109         TextView textView = new TextView(mContext);
110         vg.addView(textView);
111         assertFalse(vg.addStatesFromChildren());
112 
113         vg.setAddStatesFromChildren(true);
114         textView.performClick();
115         assertTrue(vg.addStatesFromChildren());
116         assertTrue(vg.isDrawableStateChangedCalled);
117     }
118 
testAddTouchables()119     public void testAddTouchables() {
120         MockViewGroup vg = new MockViewGroup(mContext);
121         vg.setFocusable(true);
122 
123         ArrayList<View> list = new ArrayList<View>();
124         TextView textView = new TextView(mContext);
125         textView.setVisibility(View.VISIBLE);
126         textView.setClickable(true);
127         textView.setEnabled(true);
128 
129         list.add(textView);
130         vg.addView(textView);
131         vg.addTouchables(list);
132 
133         assertEquals(2, list.size());
134 
135         View v = vg.getChildAt(0);
136         assertSame(textView, v);
137 
138         v = vg.getChildAt(-1);
139         assertNull(v);
140 
141         v = vg.getChildAt(1);
142         assertNull(v);
143 
144         v = vg.getChildAt(100);
145         assertNull(v);
146 
147         v = vg.getChildAt(-100);
148         assertNull(v);
149     }
150 
testAddView()151     public void testAddView() {
152         MockViewGroup vg = new MockViewGroup(mContext);
153         TextView textView = new TextView(mContext);
154 
155         assertEquals(0, vg.getChildCount());
156 
157         vg.addView(textView);
158         assertEquals(1, vg.getChildCount());
159     }
160 
testAddViewWithParaViewInt()161     public void testAddViewWithParaViewInt() {
162         MockViewGroup vg = new MockViewGroup(mContext);
163         TextView textView = new TextView(mContext);
164 
165         assertEquals(0, vg.getChildCount());
166 
167         vg.addView(textView, -1);
168         assertEquals(1, vg.getChildCount());
169     }
170 
testAddViewWithParaViewLayoutPara()171     public void testAddViewWithParaViewLayoutPara() {
172         MockViewGroup vg = new MockViewGroup(mContext);
173         TextView textView = new TextView(mContext);
174 
175         assertEquals(0, vg.getChildCount());
176 
177         vg.addView(textView, new ViewGroup.LayoutParams(100, 200));
178 
179         assertEquals(1, vg.getChildCount());
180     }
181 
testAddViewWithParaViewIntInt()182     public void testAddViewWithParaViewIntInt() {
183         final int width = 100;
184         final int height = 200;
185         MockViewGroup vg = new MockViewGroup(mContext);
186         TextView textView = new TextView(mContext);
187 
188         assertEquals(0, vg.getChildCount());
189 
190         vg.addView(textView, width, height);
191         assertEquals(width, textView.getLayoutParams().width);
192         assertEquals(height, textView.getLayoutParams().height);
193 
194         assertEquals(1, vg.getChildCount());
195     }
196 
testAddViewWidthParaViewIntLayoutParam()197     public void testAddViewWidthParaViewIntLayoutParam() {
198         MockViewGroup vg = new MockViewGroup(mContext);
199         TextView textView = new TextView(mContext);
200 
201         assertEquals(0, vg.getChildCount());
202 
203         vg.addView(textView, -1, new ViewGroup.LayoutParams(100, 200));
204 
205         assertEquals(1, vg.getChildCount());
206     }
207 
testAddViewInLayout()208     public void testAddViewInLayout() {
209         MockViewGroup vg = new MockViewGroup(mContext);
210         TextView textView = new TextView(mContext);
211 
212         assertEquals(0, vg.getChildCount());
213 
214         assertTrue(vg.isRequestLayoutCalled);
215         vg.isRequestLayoutCalled = false;
216         assertTrue(vg.addViewInLayout(textView, -1, new ViewGroup.LayoutParams(100, 200)));
217         assertEquals(1, vg.getChildCount());
218         // check that calling addViewInLayout() does not trigger a
219         // requestLayout() on this ViewGroup
220         assertFalse(vg.isRequestLayoutCalled);
221     }
222 
testAttachLayoutAnimationParameters()223     public void testAttachLayoutAnimationParameters() {
224         MockViewGroup vg = new MockViewGroup(mContext);
225         ViewGroup.LayoutParams param = new ViewGroup.LayoutParams(10, 10);
226 
227         vg.attachLayoutAnimationParameters(null, param, 1, 2);
228         assertEquals(2, param.layoutAnimationParameters.count);
229         assertEquals(1, param.layoutAnimationParameters.index);
230     }
231 
testAttachViewToParent()232     public void testAttachViewToParent() {
233         MockViewGroup vg = new MockViewGroup(mContext);
234         vg.setFocusable(true);
235         assertEquals(0, vg.getChildCount());
236 
237         ViewGroup.LayoutParams param = new ViewGroup.LayoutParams(10, 10);
238 
239         TextView child = new TextView(mContext);
240         child.setFocusable(true);
241         vg.attachViewToParent(child, -1, param);
242         assertSame(vg, child.getParent());
243         assertEquals(1, vg.getChildCount());
244         assertSame(child, vg.getChildAt(0));
245     }
246 
testAddViewInLayoutWithParamViewIntLayB()247     public void testAddViewInLayoutWithParamViewIntLayB() {
248         MockViewGroup vg = new MockViewGroup(mContext);
249         TextView textView = new TextView(mContext);
250 
251         assertEquals(0, vg.getChildCount());
252 
253         assertTrue(vg.isRequestLayoutCalled);
254         vg.isRequestLayoutCalled = false;
255         assertTrue(vg.addViewInLayout(textView, -1, new ViewGroup.LayoutParams(100, 200), true));
256 
257         assertEquals(1, vg.getChildCount());
258         // check that calling addViewInLayout() does not trigger a
259         // requestLayout() on this ViewGroup
260         assertFalse(vg.isRequestLayoutCalled);
261     }
262 
testBringChildToFront()263     public void testBringChildToFront() {
264         MockViewGroup vg = new MockViewGroup(mContext);
265         TextView textView1 = new TextView(mContext);
266         TextView textView2 = new TextView(mContext);
267 
268         assertEquals(0, vg.getChildCount());
269 
270         vg.addView(textView1);
271         vg.addView(textView2);
272         assertEquals(2, vg.getChildCount());
273 
274         vg.bringChildToFront(textView1);
275         assertEquals(vg, textView1.getParent());
276         assertEquals(2, vg.getChildCount());
277         assertNotNull(vg.getChildAt(0));
278         assertSame(textView2, vg.getChildAt(0));
279 
280         vg.bringChildToFront(textView2);
281         assertEquals(vg, textView2.getParent());
282         assertEquals(2, vg.getChildCount());
283         assertNotNull(vg.getChildAt(0));
284         assertSame(textView1, vg.getChildAt(0));
285     }
286 
testCanAnimate()287     public void testCanAnimate() {
288         MockViewGroup vg = new MockViewGroup(mContext);
289 
290         assertFalse(vg.canAnimate());
291 
292         RotateAnimation animation = new RotateAnimation(0.1f, 0.1f);
293         LayoutAnimationController la = new LayoutAnimationController(animation);
294         vg.setLayoutAnimation(la);
295         assertTrue(vg.canAnimate());
296     }
297 
testCheckLayoutParams()298     public void testCheckLayoutParams() {
299         MockViewGroup view = new MockViewGroup(mContext);
300         assertFalse(view.checkLayoutParams(null));
301 
302         assertTrue(view.checkLayoutParams(new ViewGroup.LayoutParams(100, 200)));
303     }
304 
testChildDrawableStateChanged()305     public void testChildDrawableStateChanged() {
306         MockViewGroup vg = new MockViewGroup(mContext);
307         vg.setAddStatesFromChildren(true);
308 
309         vg.childDrawableStateChanged(null);
310         assertTrue(vg.isRefreshDrawableStateCalled);
311     }
312 
testCleanupLayoutState()313     public void testCleanupLayoutState() {
314         MockViewGroup vg = new MockViewGroup(mContext);
315         TextView textView = new TextView(mContext);
316 
317         assertTrue(textView.isLayoutRequested());
318 
319         vg.cleanupLayoutState(textView);
320         assertFalse(textView.isLayoutRequested());
321     }
322 
testClearChildFocus()323     public void testClearChildFocus() {
324         MockViewGroup vg = new MockViewGroup(mContext);
325         TextView textView = new TextView(mContext);
326 
327         vg.addView(textView);
328         vg.requestChildFocus(textView, null);
329 
330         View focusedView = vg.getFocusedChild();
331         assertSame(textView, focusedView);
332 
333         vg.clearChildFocus(textView);
334         assertNull(vg.getFocusedChild());
335     }
336 
testClearDisappearingChildren()337     public void testClearDisappearingChildren() {
338 
339         Canvas canvas = new Canvas();
340         MockViewGroup vg = new MockViewGroup(mContext);
341         MockViewGroup son = new MockViewGroup(mContext);
342         son.setAnimation(new MockAnimation());
343         vg.addView(son);
344         assertEquals(1, vg.getChildCount());
345 
346         assertNotNull(son.getAnimation());
347         vg.dispatchDraw(canvas);
348         assertEquals(1, vg.drawChildCalledTime);
349 
350         son.setAnimation(new MockAnimation());
351         vg.removeAllViewsInLayout();
352 
353         vg.drawChildCalledTime = 0;
354         vg.dispatchDraw(canvas);
355         assertEquals(1, vg.drawChildCalledTime);
356 
357         son.setAnimation(new MockAnimation());
358         vg.clearDisappearingChildren();
359 
360         vg.drawChildCalledTime = 0;
361         vg.dispatchDraw(canvas);
362         assertEquals(0, vg.drawChildCalledTime);
363     }
364 
testClearFocus()365     public void testClearFocus() {
366         MockViewGroup vg = new MockViewGroup(mContext);
367         MockTextView textView = new MockTextView(mContext);
368 
369         vg.addView(textView);
370         vg.requestChildFocus(textView, null);
371         vg.clearFocus();
372         assertTrue(textView.isClearFocusCalled);
373     }
374 
testDetachAllViewsFromParent()375     public void testDetachAllViewsFromParent() {
376         MockViewGroup vg = new MockViewGroup(mContext);
377         TextView textView = new TextView(mContext);
378 
379         vg.addView(textView);
380         assertEquals(1, vg.getChildCount());
381         assertSame(vg, textView.getParent());
382         vg.detachAllViewsFromParent();
383         assertEquals(0, vg.getChildCount());
384         assertNull(textView.getParent());
385     }
386 
testDetachViewFromParent()387     public void testDetachViewFromParent() {
388         MockViewGroup vg = new MockViewGroup(mContext);
389         TextView textView = new TextView(mContext);
390 
391         vg.addView(textView);
392         assertEquals(1, vg.getChildCount());
393 
394         vg.detachViewFromParent(0);
395 
396         assertEquals(0, vg.getChildCount());
397         assertNull(textView.getParent());
398     }
399 
testDetachViewFromParentWithParamView()400     public void testDetachViewFromParentWithParamView() {
401         MockViewGroup vg = new MockViewGroup(mContext);
402         TextView textView = new TextView(mContext);
403 
404         vg.addView(textView);
405         assertEquals(1, vg.getChildCount());
406         assertSame(vg, textView.getParent());
407 
408         vg.detachViewFromParent(textView);
409 
410         assertEquals(0, vg.getChildCount());
411         assertNull(vg.getParent());
412     }
413 
testDetachViewsFromParent()414     public void testDetachViewsFromParent() {
415         MockViewGroup vg = new MockViewGroup(mContext);
416         TextView textView1 = new TextView(mContext);
417         TextView textView2 = new TextView(mContext);
418         TextView textView3 = new TextView(mContext);
419 
420         vg.addView(textView1);
421         vg.addView(textView2);
422         vg.addView(textView3);
423         assertEquals(3, vg.getChildCount());
424 
425         vg.detachViewsFromParent(0, 2);
426 
427         assertEquals(1, vg.getChildCount());
428         assertNull(textView1.getParent());
429         assertNull(textView2.getParent());
430     }
431 
testDispatchDraw()432     public void testDispatchDraw() {
433         MockViewGroup vg = new MockViewGroup(mContext);
434         Canvas canvas = new Canvas();
435 
436         vg.draw(canvas);
437         assertTrue(vg.isDispatchDrawCalled);
438         assertSame(canvas, vg.canvas);
439     }
440 
441     @SuppressWarnings("unchecked")
testDispatchFreezeSelfOnly()442     public void testDispatchFreezeSelfOnly() {
443         MockViewGroup vg = new MockViewGroup(mContext);
444         vg.setId(1);
445         vg.setSaveEnabled(true);
446 
447         SparseArray container = new SparseArray();
448         assertEquals(0, container.size());
449         vg.dispatchFreezeSelfOnly(container);
450         assertEquals(1, container.size());
451     }
452 
testDispatchKeyEvent()453     public void testDispatchKeyEvent() {
454         MockViewGroup vg = new MockViewGroup(mContext);
455         KeyEvent event = new KeyEvent(KeyEvent.ACTION_DOWN, KeyEvent.KEYCODE_ENTER);
456         assertFalse(vg.dispatchKeyEvent(event));
457 
458         MockTextView textView = new MockTextView(mContext);
459         vg.addView(textView);
460         vg.requestChildFocus(textView, null);
461         textView.layout(1, 1, 100, 100);
462 
463         assertTrue(vg.dispatchKeyEvent(event));
464     }
465 
466     @SuppressWarnings("unchecked")
testDispatchSaveInstanceState()467     public void testDispatchSaveInstanceState() {
468         MockViewGroup vg = new MockViewGroup(mContext);
469         vg.setId(2);
470         vg.setSaveEnabled(true);
471         MockTextView textView = new MockTextView(mContext);
472         textView.setSaveEnabled(true);
473         textView.setId(1);
474         vg.addView(textView);
475 
476         SparseArray array = new SparseArray();
477         vg.dispatchSaveInstanceState(array);
478 
479         assertTrue(array.size() > 0);
480         assertNotNull(array.get(2));
481 
482         array = new SparseArray();
483         vg.dispatchRestoreInstanceState(array);
484         assertTrue(textView.isDispatchRestoreInstanceStateCalled);
485     }
486 
testDispatchSetPressed()487     public void testDispatchSetPressed() {
488         MockViewGroup vg = new MockViewGroup(mContext);
489         MockTextView textView = new MockTextView(mContext);
490         vg.addView(textView);
491 
492         vg.dispatchSetPressed(true);
493         assertTrue(textView.isPressed());
494 
495         vg.dispatchSetPressed(false);
496         assertFalse(textView.isPressed());
497     }
498 
testDispatchSetSelected()499     public void testDispatchSetSelected() {
500         MockViewGroup vg = new MockViewGroup(mContext);
501         MockTextView textView = new MockTextView(mContext);
502         vg.addView(textView);
503 
504         vg.dispatchSetSelected(true);
505         assertTrue(textView.isSelected());
506 
507         vg.dispatchSetSelected(false);
508         assertFalse(textView.isSelected());
509     }
510 
511     @SuppressWarnings("unchecked")
testDispatchThawSelfOnly()512     public void testDispatchThawSelfOnly() {
513         MockViewGroup vg = new MockViewGroup(mContext);
514         vg.setId(1);
515         SparseArray array = new SparseArray();
516         array.put(1, BaseSavedState.EMPTY_STATE);
517 
518         vg.dispatchThawSelfOnly(array);
519         assertTrue(vg.isOnRestoreInstanceStateCalled);
520 
521     }
522 
testDispatchTouchEvent()523     public void testDispatchTouchEvent() {
524         MockViewGroup vg = new MockViewGroup(mContext);
525 
526         DisplayMetrics metrics = new DisplayMetrics();
527         WindowManager wm = (WindowManager) mContext.getSystemService(Context.WINDOW_SERVICE);
528         Display d = wm.getDefaultDisplay();
529         d.getMetrics(metrics);
530         int screenWidth = metrics.widthPixels;
531         int screenHeight = metrics.heightPixels;
532         vg.layout(0, 0, screenWidth, screenHeight);
533         vg.setLayoutParams(new ViewGroup.LayoutParams(screenWidth, screenHeight));
534 
535         MockTextView textView = new MockTextView(mContext);
536         mMotionEvent = null;
537         textView.setOnTouchListener(new OnTouchListener() {
538             public boolean onTouch(View v, MotionEvent event) {
539                 mMotionEvent = event;
540                 return true;
541             }
542         });
543 
544         textView.setVisibility(View.VISIBLE);
545         textView.setEnabled(true);
546 
547         vg.addView(textView, new LayoutParams(screenWidth, screenHeight));
548 
549         vg.requestDisallowInterceptTouchEvent(true);
550         MotionEvent me = MotionEvent.obtain(SystemClock.uptimeMillis(),
551                 SystemClock.uptimeMillis(), MotionEvent.ACTION_DOWN,
552                 screenWidth / 2, screenHeight / 2, 0);
553 
554         assertFalse(vg.dispatchTouchEvent(me));
555         assertNull(mMotionEvent);
556 
557         textView.layout(0, 0, screenWidth, screenHeight);
558         assertTrue(vg.dispatchTouchEvent(me));
559         assertSame(me, mMotionEvent);
560     }
561 
testDispatchTrackballEvent()562     public void testDispatchTrackballEvent() {
563         MockViewGroup vg = new MockViewGroup(mContext);
564         MotionEvent me = MotionEvent.obtain(SystemClock.uptimeMillis(),
565                 SystemClock.uptimeMillis(), MotionEvent.ACTION_DOWN, 100, 100,
566                 0);
567         assertFalse(vg.dispatchTrackballEvent(me));
568 
569         MockTextView textView = new MockTextView(mContext);
570         vg.addView(textView);
571         textView.layout(1, 1, 100, 100);
572         vg.requestChildFocus(textView, null);
573         assertTrue(vg.dispatchTrackballEvent(me));
574     }
575 
testDispatchUnhandledMove()576     public void testDispatchUnhandledMove() {
577         MockViewGroup vg = new MockViewGroup(mContext);
578         MockTextView textView = new MockTextView(mContext);
579         assertFalse(vg.dispatchUnhandledMove(textView, View.FOCUS_DOWN));
580 
581         vg.addView(textView);
582         textView.layout(1, 1, 100, 100);
583         vg.requestChildFocus(textView, null);
584         assertTrue(vg.dispatchUnhandledMove(textView, View.FOCUS_DOWN));
585     }
586 
testDispatchWindowFocusChanged()587     public void testDispatchWindowFocusChanged() {
588         MockViewGroup vg = new MockViewGroup(mContext);
589         MockTextView textView = new MockTextView(mContext);
590 
591         vg.addView(textView);
592         textView.setPressed(true);
593         assertTrue(textView.isPressed());
594 
595         vg.dispatchWindowFocusChanged(false);
596         assertFalse(textView.isPressed());
597     }
598 
testDispatchWindowVisibilityChanged()599     public void testDispatchWindowVisibilityChanged() {
600         int expected = 10;
601         MockViewGroup vg = new MockViewGroup(mContext);
602         MockTextView textView = new MockTextView(mContext);
603 
604         vg.addView(textView);
605         vg.dispatchWindowVisibilityChanged(expected);
606         assertEquals(expected, textView.visibility);
607     }
608 
testDrawableStateChanged()609     public void testDrawableStateChanged() {
610         MockViewGroup vg = new MockViewGroup(mContext);
611         MockTextView textView = new MockTextView(mContext);
612         textView.setDuplicateParentStateEnabled(true);
613 
614         vg.addView(textView);
615         vg.setAddStatesFromChildren(false);
616         vg.drawableStateChanged();
617         assertTrue(textView.mIsRefreshDrawableStateCalled);
618     }
619 
testDrawChild()620     public void testDrawChild() {
621         MockViewGroup vg = new MockViewGroup(mContext);
622         MockTextView textView = new MockTextView(mContext);
623         vg.addView(textView);
624 
625         MockCanvas canvas = new MockCanvas();
626         textView.setBackgroundDrawable(new BitmapDrawable(Bitmap.createBitmap(100, 100,
627                 Config.ALPHA_8)));
628         assertFalse(vg.drawChild(canvas, textView, 100));
629         // test whether child's draw method is called.
630         assertTrue(textView.isDrawCalled);
631     }
632 
testFindFocus()633     public void testFindFocus() {
634         MockViewGroup vg = new MockViewGroup(mContext);
635 
636         assertNull(vg.findFocus());
637         vg.setDescendantFocusability(ViewGroup.FOCUS_BLOCK_DESCENDANTS);
638         vg.setFocusable(true);
639         vg.setVisibility(View.VISIBLE);
640         vg.setFocusableInTouchMode(true);
641         assertTrue(vg.requestFocus(1, new Rect()));
642 
643         assertSame(vg, vg.findFocus());
644     }
645 
testFitSystemWindows()646     public void testFitSystemWindows() {
647         Rect rect = new Rect(1, 1, 100, 100);
648         MockViewGroup vg = new MockViewGroup(mContext);
649         assertFalse(vg.fitSystemWindows(rect));
650 
651         vg = new MockViewGroup(mContext, null, 0);
652         MockView mv = new MockView(mContext);
653         vg.addView(mv);
654         assertTrue(vg.fitSystemWindows(rect));
655     }
656 
657     static class MockView extends ViewGroup {
658 
659         public int mWidthMeasureSpec;
660         public int mHeightMeasureSpec;
661 
MockView(Context context)662         public MockView(Context context) {
663             super(context);
664         }
665 
666         @Override
onLayout(boolean changed, int l, int t, int r, int b)667         public void onLayout(boolean changed, int l, int t, int r, int b) {
668         }
669 
670         @Override
fitSystemWindows(Rect insets)671         public boolean fitSystemWindows(Rect insets) {
672             return true;
673         }
674 
675         @Override
onMeasure(int widthMeasureSpec, int heightMeasureSpec)676         public void onMeasure(int widthMeasureSpec,
677                 int heightMeasureSpec) {
678             mWidthMeasureSpec = widthMeasureSpec;
679             mHeightMeasureSpec = heightMeasureSpec;
680             super.onMeasure(widthMeasureSpec, heightMeasureSpec);
681         }
682     }
683 
testFocusableViewAvailable()684     public void testFocusableViewAvailable() {
685         MockViewGroup vg = new MockViewGroup(mContext);
686         MockView son = new MockView(mContext);
687         vg.addView(son);
688 
689         son.setDescendantFocusability(ViewGroup.FOCUS_BEFORE_DESCENDANTS);
690         son.focusableViewAvailable(vg);
691 
692         assertTrue(vg.isFocusableViewAvailable);
693     }
694 
testFocusSearch()695     public void testFocusSearch() {
696         MockViewGroup vg = new MockViewGroup(mContext);
697         MockTextView textView = new MockTextView(mContext);
698         MockView son = new MockView(mContext);
699         vg.addView(son);
700         son.addView(textView);
701         assertNotNull(son.focusSearch(textView, 1));
702         assertSame(textView, son.focusSearch(textView, 1));
703     }
704 
testGatherTransparentRegion()705     public void testGatherTransparentRegion() {
706         Region region = new Region();
707         MockViewGroup vg = new MockViewGroup(mContext);
708         MockTextView textView = new MockTextView(mContext);
709         textView.setAnimation(new AlphaAnimation(mContext, null));
710         textView.setVisibility(100);
711         vg.addView(textView);
712         assertEquals(1, vg.getChildCount());
713 
714         assertTrue(vg.gatherTransparentRegion(region));
715         assertTrue(vg.gatherTransparentRegion(null));
716     }
717 
testGenerateDefaultLayoutParams()718     public void testGenerateDefaultLayoutParams(){
719         MockViewGroup vg = new MockViewGroup(mContext);
720         LayoutParams lp = vg.generateDefaultLayoutParams();
721 
722         assertEquals(LayoutParams.WRAP_CONTENT, lp.width);
723         assertEquals(LayoutParams.WRAP_CONTENT, lp.height);
724     }
725 
testGenerateLayoutParamsWithParaAttributeSet()726     public void testGenerateLayoutParamsWithParaAttributeSet() throws Exception{
727         MockViewGroup vg = new MockViewGroup(mContext);
728         XmlResourceParser set = mContext.getResources().getLayout(
729                 com.android.cts.view.R.layout.abslistview_layout);
730         XmlUtils.beginDocument(set, "ViewGroup_Layout");
731         LayoutParams lp = vg.generateLayoutParams(set);
732         assertNotNull(lp);
733         assertEquals(25, lp.height);
734         assertEquals(25, lp.width);
735     }
736 
testGenerateLayoutParams()737     public void testGenerateLayoutParams() {
738         MockViewGroup vg = new MockViewGroup(mContext);
739         LayoutParams p = new LayoutParams(LayoutParams.WRAP_CONTENT,
740                 LayoutParams.MATCH_PARENT);
741         assertSame(p, vg.generateLayoutParams(p));
742     }
743 
testGetChildDrawingOrder()744     public void testGetChildDrawingOrder() {
745         MockViewGroup vg = new MockViewGroup(mContext);
746         assertEquals(1, vg.getChildDrawingOrder(0, 1));
747         assertEquals(2, vg.getChildDrawingOrder(0, 2));
748     }
749 
testGetChildMeasureSpec()750     public void testGetChildMeasureSpec() {
751         int spec = 1;
752         int padding = 1;
753         int childDimension = 1;
754         assertEquals(MeasureSpec.makeMeasureSpec(childDimension, MeasureSpec.EXACTLY),
755                 ViewGroup.getChildMeasureSpec(spec, padding, childDimension));
756         spec = 4;
757         padding = 6;
758         childDimension = 9;
759         assertEquals(MeasureSpec.makeMeasureSpec(childDimension, MeasureSpec.EXACTLY),
760                 ViewGroup.getChildMeasureSpec(spec, padding, childDimension));
761     }
762 
testGetChildStaticTransformation()763     public void testGetChildStaticTransformation() {
764         MockViewGroup vg = new MockViewGroup(mContext);
765         assertFalse(vg.getChildStaticTransformation(null, null));
766     }
767 
testGetChildVisibleRect()768     public void testGetChildVisibleRect() {
769         MockViewGroup vg = new MockViewGroup(mContext);
770         MockTextView textView = new MockTextView(mContext);
771 
772         textView.layout(1, 1, 100, 100);
773         Rect rect = new Rect(1, 1, 50, 50);
774         Point p = new Point();
775         assertFalse(vg.getChildVisibleRect(textView, rect, p));
776 
777         textView.layout(0, 0, 0, 0);
778         vg.layout(20, 20, 60, 60);
779         rect = new Rect(10, 10, 40, 40);
780         p = new Point();
781         assertTrue(vg.getChildVisibleRect(textView, rect, p));
782     }
783 
testGetDescendantFocusability()784     public void testGetDescendantFocusability() {
785         MockViewGroup vg = new MockViewGroup(mContext);
786         final int FLAG_MASK_FOCUSABILITY = 0x60000;
787         assertFalse((vg.getDescendantFocusability() & FLAG_MASK_FOCUSABILITY) == 0);
788 
789         vg.setDescendantFocusability(ViewGroup.FOCUS_BLOCK_DESCENDANTS);
790         assertFalse((vg.getDescendantFocusability() & FLAG_MASK_FOCUSABILITY) == 0);
791     }
792 
testGetLayoutAnimation()793     public void testGetLayoutAnimation() {
794         MockViewGroup vg = new MockViewGroup(mContext);
795 
796         assertNull(vg.getLayoutAnimation());
797         RotateAnimation animation = new RotateAnimation(0.1f, 0.1f);
798         LayoutAnimationController la = new LayoutAnimationController(animation);
799         vg.setLayoutAnimation(la);
800         assertTrue(vg.canAnimate());
801         assertSame(la, vg.getLayoutAnimation());
802     }
803 
testGetLayoutAnimationListener()804     public void testGetLayoutAnimationListener() {
805         MockViewGroup vg = new MockViewGroup(mContext);
806 
807         assertNull(vg.getLayoutAnimationListener());
808 
809         AnimationListener al = new AnimationListener() {
810 
811             public void onAnimationEnd(Animation animation) {
812             }
813 
814             public void onAnimationRepeat(Animation animation) {
815             }
816 
817             public void onAnimationStart(Animation animation) {
818             }
819         };
820         vg.setLayoutAnimationListener(al);
821         assertSame(al, vg.getLayoutAnimationListener());
822     }
823 
testGetPersistentDrawingCache()824     public void testGetPersistentDrawingCache() {
825         MockViewGroup vg = new MockViewGroup(mContext);
826         final int mPersistentDrawingCache1 = 2;
827         final int mPersistentDrawingCache2 = 3;
828         assertEquals(mPersistentDrawingCache1, vg.getPersistentDrawingCache());
829 
830         vg.setPersistentDrawingCache(mPersistentDrawingCache2);
831         assertEquals(mPersistentDrawingCache2, vg.getPersistentDrawingCache());
832     }
833 
testHasFocus()834     public void testHasFocus() {
835         MockViewGroup vg = new MockViewGroup(mContext);
836         assertFalse(vg.hasFocus());
837 
838         TextView textView = new TextView(mContext);
839 
840         vg.addView(textView);
841         vg.requestChildFocus(textView, null);
842 
843         assertTrue(vg.hasFocus());
844     }
845 
testHasFocusable()846     public void testHasFocusable() {
847         MockViewGroup vg = new MockViewGroup(mContext);
848         assertFalse(vg.hasFocusable());
849 
850         vg.setVisibility(View.VISIBLE);
851         vg.setFocusable(true);
852         assertTrue(vg.hasFocusable());
853     }
854 
testIndexOfChild()855     public void testIndexOfChild() {
856         MockViewGroup vg = new MockViewGroup(mContext);
857         TextView textView = new TextView(mContext);
858 
859         assertEquals(-1, vg.indexOfChild(textView));
860 
861         vg.addView(textView);
862         assertEquals(0, vg.indexOfChild(textView));
863     }
864 
setupActivity(String action)865     private void setupActivity(String action) {
866 
867         Intent intent = new Intent(getInstrumentation().getTargetContext(),
868                 ViewGroupCtsActivity.class);
869         intent.setAction(action);
870         intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
871         getInstrumentation().getTargetContext().startActivity(intent);
872     }
873 
testInvalidateChild()874     public void testInvalidateChild() {
875         ViewGroupCtsActivity.setResult(this);
876         setupActivity(ViewGroupCtsActivity.ACTION_INVALIDATE_CHILD);
877         waitForResult();
878         assertEquals(CTSResult.RESULT_OK, mResultCode);
879     }
880 
waitForResult()881     private void waitForResult() {
882         synchronized (mSync) {
883             while(!mSync.mHasNotify) {
884                 try {
885                     mSync.wait();
886                 } catch (InterruptedException e) {
887                 }
888             }
889         }
890     }
891 
testIsAlwaysDrawnWithCacheEnabled()892     public void testIsAlwaysDrawnWithCacheEnabled() {
893         MockViewGroup vg = new MockViewGroup(mContext);
894 
895         assertTrue(vg.isAlwaysDrawnWithCacheEnabled());
896 
897         vg.setAlwaysDrawnWithCacheEnabled(false);
898         assertFalse(vg.isAlwaysDrawnWithCacheEnabled());
899         vg.setAlwaysDrawnWithCacheEnabled(true);
900         assertTrue(vg.isAlwaysDrawnWithCacheEnabled());
901     }
902 
testIsAnimationCacheEnabled()903     public void testIsAnimationCacheEnabled() {
904         MockViewGroup vg = new MockViewGroup(mContext);
905 
906         assertTrue(vg.isAnimationCacheEnabled());
907 
908         vg.setAnimationCacheEnabled(false);
909         assertFalse(vg.isAnimationCacheEnabled());
910         vg.setAnimationCacheEnabled(true);
911         assertTrue(vg.isAnimationCacheEnabled());
912     }
913 
testIsChildrenDrawnWithCacheEnabled()914     public void testIsChildrenDrawnWithCacheEnabled() {
915         MockViewGroup vg = new MockViewGroup(mContext);
916 
917         assertFalse(vg.isChildrenDrawnWithCacheEnabled());
918 
919         vg.setChildrenDrawnWithCacheEnabled(true);
920         assertTrue(vg.isChildrenDrawnWithCacheEnabled());
921     }
922 
testMeasureChild()923     public void testMeasureChild() {
924         final int width = 100;
925         final int height = 200;
926         MockViewGroup vg = new MockViewGroup(mContext);
927         MockView son = new MockView(mContext);
928         son.setLayoutParams(new LayoutParams(width, height));
929         son.forceLayout();
930         vg.addView(son);
931 
932         final int parentWidthMeasureSpec = 1;
933         final int parentHeightMeasureSpec = 2;
934         vg.measureChild(son, parentWidthMeasureSpec, parentHeightMeasureSpec);
935         assertEquals(ViewGroup.getChildMeasureSpec(parentWidthMeasureSpec, 0, width),
936                 son.mWidthMeasureSpec);
937         assertEquals(ViewGroup.getChildMeasureSpec(parentHeightMeasureSpec, 0, height),
938                 son.mHeightMeasureSpec);
939     }
940 
testMeasureChildren()941     public void testMeasureChildren() {
942         final int widthMeasureSpec = 100;
943         final int heightMeasureSpec = 200;
944         MockViewGroup vg = new MockViewGroup(mContext);
945         MockTextView textView1 = new MockTextView(mContext);
946 
947         vg.addView(textView1);
948         vg.measureChildCalledTime = 0;
949         vg.measureChildren(widthMeasureSpec, heightMeasureSpec);
950         assertEquals(1, vg.measureChildCalledTime);
951 
952         MockTextView textView2 = new MockTextView(mContext);
953         textView2.setVisibility(View.GONE);
954         vg.addView(textView2);
955 
956         vg.measureChildCalledTime = 0;
957         vg.measureChildren(widthMeasureSpec, heightMeasureSpec);
958         assertEquals(1, vg.measureChildCalledTime);
959     }
960 
testMeasureChildWithMargins()961     public void testMeasureChildWithMargins() {
962         final int width = 10;
963         final int height = 20;
964         final int parentWidthMeasureSpec = 1;
965         final int widthUsed = 2;
966         final int parentHeightMeasureSpec = 3;
967         final int heightUsed = 4;
968         MockViewGroup vg = new MockViewGroup(mContext);
969         MockView son = new MockView(mContext);
970 
971         vg.addView(son);
972         son.setLayoutParams(new ViewGroup.LayoutParams(width, height));
973         try {
974             vg.measureChildWithMargins(son, parentWidthMeasureSpec, widthUsed,
975                     parentHeightMeasureSpec, heightUsed);
976             fail("measureChildWithMargins should throw out class cast exception");
977         } catch (RuntimeException e) {
978         }
979         son.setLayoutParams(new ViewGroup.MarginLayoutParams(width, height));
980 
981         vg.measureChildWithMargins(son, parentWidthMeasureSpec, widthUsed, parentHeightMeasureSpec,
982                 heightUsed);
983         assertEquals(ViewGroup.getChildMeasureSpec(parentWidthMeasureSpec, parentHeightMeasureSpec,
984                 width), son.mWidthMeasureSpec);
985         assertEquals(ViewGroup.getChildMeasureSpec(widthUsed, heightUsed, height),
986                 son.mHeightMeasureSpec);
987     }
988 
testOffsetDescendantRectToMyCoords()989     public void testOffsetDescendantRectToMyCoords() {
990         MockViewGroup vg = new MockViewGroup(mContext);
991         MockTextView textView = new MockTextView(mContext);
992 
993         try {
994             vg.offsetDescendantRectToMyCoords(textView, new Rect());
995             fail("offsetDescendantRectToMyCoords should throw out "
996                     + "IllegalArgumentException");
997         } catch (RuntimeException e) {
998             // expected
999         }
1000         vg.addView(textView);
1001         textView.layout(1, 2, 3, 4);
1002         Rect rect = new Rect();
1003         vg.offsetDescendantRectToMyCoords(textView, rect);
1004         assertEquals(2, rect.bottom);
1005         assertEquals(2, rect.top);
1006         assertEquals(1, rect.left);
1007         assertEquals(1, rect.right);
1008     }
1009 
testOffsetRectIntoDescendantCoords()1010     public void testOffsetRectIntoDescendantCoords() {
1011         MockViewGroup vg = new MockViewGroup(mContext);
1012         vg.layout(10, 20, 30, 40);
1013         MockTextView textView = new MockTextView(mContext);
1014 
1015         try {
1016             vg.offsetRectIntoDescendantCoords(textView, new Rect());
1017             fail("offsetRectIntoDescendantCoords should throw out "
1018                     + "IllegalArgumentException");
1019         } catch (RuntimeException e) {
1020             // expected
1021         }
1022         textView.layout(1, 2, 3, 4);
1023         vg.addView(textView);
1024 
1025         Rect rect = new Rect(5, 6, 7, 8);
1026         vg.offsetRectIntoDescendantCoords(textView, rect);
1027         assertEquals(6, rect.bottom);
1028         assertEquals(4, rect.top);
1029         assertEquals(4, rect.left);
1030         assertEquals(6, rect.right);
1031     }
1032 
testOnAnimationEnd()1033     public void testOnAnimationEnd() {
1034         // this function is a call back function it should be tested in ViewGroup#drawChild.
1035         MockViewGroup father = new MockViewGroup(mContext);
1036         MockViewGroup son = new MockViewGroup(mContext);
1037         son.setAnimation(new MockAnimation());
1038         // this call will make mPrivateFlags |= ANIMATION_STARTED;
1039         son.onAnimationStart();
1040         father.addView(son);
1041 
1042         MockCanvas canvas = new MockCanvas();
1043         assertFalse(father.drawChild(canvas, son, 100));
1044         assertTrue(son.isOnAnimationEndCalled);
1045     }
1046 
1047     private class MockAnimation extends Animation {
MockAnimation()1048         public MockAnimation() {
1049             super();
1050         }
1051 
MockAnimation(Context context, AttributeSet attrs)1052         public MockAnimation(Context context, AttributeSet attrs) {
1053             super(context, attrs);
1054         }
1055 
1056         @Override
getTransformation(long currentTime, Transformation outTransformation)1057         public boolean getTransformation(long currentTime, Transformation outTransformation) {
1058            super.getTransformation(currentTime, outTransformation);
1059            return false;
1060         }
1061     }
1062 
testOnAnimationStart()1063     public void testOnAnimationStart() {
1064         // This is a call back method. It should be tested in ViewGroup#drawChild.
1065         MockViewGroup father = new MockViewGroup(mContext);
1066         MockViewGroup son = new MockViewGroup(mContext);
1067 
1068         father.addView(son);
1069 
1070         MockCanvas canvas = new MockCanvas();
1071         try {
1072             assertFalse(father.drawChild(canvas, son, 100));
1073             assertFalse(son.isOnAnimationStartCalled);
1074         } catch (Exception e) {
1075             // expected
1076         }
1077 
1078         son.setAnimation(new MockAnimation());
1079         assertFalse(father.drawChild(canvas, son, 100));
1080         assertTrue(son.isOnAnimationStartCalled);
1081     }
1082 
testOnCreateDrawableState()1083     public void testOnCreateDrawableState() {
1084         MockViewGroup vg = new MockViewGroup(mContext);
1085         // Call back function. Called in View#getDrawableState()
1086         int[] data = vg.getDrawableState();
1087         assertTrue(vg.isOnCreateDrawableStateCalled);
1088         assertEquals(1, data.length);
1089     }
1090 
testOnInterceptTouchEvent()1091     public void testOnInterceptTouchEvent() {
1092         MockViewGroup vg = new MockViewGroup(mContext);
1093         MotionEvent me = MotionEvent.obtain(SystemClock.uptimeMillis(),
1094                 SystemClock.uptimeMillis(), MotionEvent.ACTION_DOWN, 100, 100,
1095                 0);
1096 
1097         assertFalse(vg.dispatchTouchEvent(me));
1098         assertTrue(vg.isOnInterceptTouchEventCalled);
1099     }
1100 
testOnLayout()1101     public void testOnLayout() {
1102         final int left = 1;
1103         final int top = 2;
1104         final int right = 100;
1105         final int bottom = 200;
1106         MockViewGroup mv = new MockViewGroup(mContext);
1107         mv.layout(left, top, right, bottom);
1108         assertEquals(left, mv.left);
1109         assertEquals(top, mv.top);
1110         assertEquals(right, mv.right);
1111         assertEquals(bottom, mv.bottom);
1112     }
1113 
testOnRequestFocusInDescendants()1114     public void testOnRequestFocusInDescendants() {
1115         MockViewGroup vg = new MockViewGroup(mContext);
1116 
1117         vg.requestFocus(View.FOCUS_DOWN, new Rect());
1118         assertTrue(vg.isOnRequestFocusInDescendantsCalled);
1119     }
1120 
testRemoveAllViews()1121     public void testRemoveAllViews() {
1122         MockViewGroup vg = new MockViewGroup(mContext);
1123         MockTextView textView = new MockTextView(mContext);
1124         assertEquals(0, vg.getChildCount());
1125 
1126         vg.addView(textView);
1127         assertEquals(1, vg.getChildCount());
1128 
1129         vg.removeAllViews();
1130         assertEquals(0, vg.getChildCount());
1131         assertNull(textView.getParent());
1132     }
1133 
testRemoveAllViewsInLayout()1134     public void testRemoveAllViewsInLayout() {
1135         MockViewGroup father = new MockViewGroup(mContext);
1136         MockViewGroup son = new MockViewGroup(mContext);
1137         MockTextView textView = new MockTextView(mContext);
1138 
1139         assertEquals(0, father.getChildCount());
1140 
1141         son.addView(textView);
1142         father.addView(son);
1143         assertEquals(1, father.getChildCount());
1144 
1145         father.removeAllViewsInLayout();
1146         assertEquals(0, father.getChildCount());
1147         assertEquals(1, son.getChildCount());
1148         assertNull(son.getParent());
1149         assertSame(son, textView.getParent());
1150     }
1151 
testRemoveDetachedView()1152     public void testRemoveDetachedView() {
1153         MockViewGroup father = new MockViewGroup(mContext);
1154         MockViewGroup son1 = new MockViewGroup(mContext);
1155         MockViewGroup son2 = new MockViewGroup(mContext);
1156         MockOnHierarchyChangeListener listener = new MockOnHierarchyChangeListener();
1157         father.setOnHierarchyChangeListener(listener);
1158         father.addView(son1);
1159         father.addView(son2);
1160 
1161         father.removeDetachedView(son1, false);
1162         assertSame(father, listener.sParent);
1163         assertSame(son1, listener.sChild);
1164     }
1165 
1166     static class MockOnHierarchyChangeListener implements OnHierarchyChangeListener {
1167 
1168         public View sParent;
1169         public View sChild;
1170 
onChildViewAdded(View parent, View child)1171         public void onChildViewAdded(View parent, View child) {
1172         }
1173 
onChildViewRemoved(View parent, View child)1174         public void onChildViewRemoved(View parent, View child) {
1175             sParent = parent;
1176             sChild = child;
1177         }
1178     }
1179 
testRemoveView()1180     public void testRemoveView() {
1181         MockViewGroup father = new MockViewGroup(mContext);
1182         MockViewGroup son = new MockViewGroup(mContext);
1183 
1184         assertEquals(0, father.getChildCount());
1185 
1186         father.addView(son);
1187         assertEquals(1, father.getChildCount());
1188 
1189         father.removeView(son);
1190         assertEquals(0, father.getChildCount());
1191         assertNull(son.getParent());
1192     }
1193 
testRemoveViewAt()1194     public void testRemoveViewAt() {
1195         MockViewGroup father = new MockViewGroup(mContext);
1196         MockViewGroup son = new MockViewGroup(mContext);
1197 
1198         assertEquals(0, father.getChildCount());
1199 
1200         father.addView(son);
1201         assertEquals(1, father.getChildCount());
1202 
1203         try {
1204             father.removeViewAt(2);
1205             fail("should throw out null pointer exception");
1206         } catch (RuntimeException e) {
1207             // expected
1208         }
1209         assertEquals(1, father.getChildCount());
1210 
1211         father.removeViewAt(0);
1212         assertEquals(0, father.getChildCount());
1213         assertNull(son.getParent());
1214     }
1215 
testRemoveViewInLayout()1216     public void testRemoveViewInLayout() {
1217         MockViewGroup father = new MockViewGroup(mContext);
1218         MockViewGroup son = new MockViewGroup(mContext);
1219 
1220         assertEquals(0, father.getChildCount());
1221 
1222         father.addView(son);
1223         assertEquals(1, father.getChildCount());
1224 
1225         father.removeViewInLayout(son);
1226         assertEquals(0, father.getChildCount());
1227         assertNull(son.getParent());
1228     }
1229 
testRemoveViews()1230     public void testRemoveViews() {
1231         MockViewGroup father = new MockViewGroup(mContext);
1232         MockViewGroup son1 = new MockViewGroup(mContext);
1233         MockViewGroup son2 = new MockViewGroup(mContext);
1234 
1235         assertEquals(0, father.getChildCount());
1236 
1237         father.addView(son1);
1238         father.addView(son2);
1239         assertEquals(2, father.getChildCount());
1240 
1241         father.removeViews(0, 1);
1242         assertEquals(1, father.getChildCount());
1243         assertNull(son1.getParent());
1244 
1245         father.removeViews(0, 1);
1246         assertEquals(0, father.getChildCount());
1247         assertNull(son2.getParent());
1248     }
1249 
testRemoveViewsInLayout()1250     public void testRemoveViewsInLayout() {
1251         MockViewGroup father = new MockViewGroup(mContext);
1252         MockViewGroup son1 = new MockViewGroup(mContext);
1253         MockViewGroup son2 = new MockViewGroup(mContext);
1254 
1255         assertEquals(0, father.getChildCount());
1256 
1257         father.addView(son1);
1258         father.addView(son2);
1259         assertEquals(2, father.getChildCount());
1260 
1261         father.removeViewsInLayout(0, 1);
1262         assertEquals(1, father.getChildCount());
1263         assertNull(son1.getParent());
1264 
1265         father.removeViewsInLayout(0, 1);
1266         assertEquals(0, father.getChildCount());
1267         assertNull(son2.getParent());
1268     }
1269 
testRequestChildFocus()1270     public void testRequestChildFocus() {
1271         MockViewGroup vg = new MockViewGroup(mContext);
1272         TextView textView = new TextView(mContext);
1273 
1274         vg.addView(textView);
1275         vg.requestChildFocus(textView, null);
1276 
1277         assertNotNull(vg.getFocusedChild());
1278 
1279         vg.clearChildFocus(textView);
1280         assertNull(vg.getFocusedChild());
1281     }
1282 
testRequestChildRectangleOnScreen()1283     public void testRequestChildRectangleOnScreen() {
1284         MockViewGroup vg = new MockViewGroup(mContext);
1285         assertFalse(vg.requestChildRectangleOnScreen(null, null, false));
1286     }
1287 
testRequestDisallowInterceptTouchEvent()1288     public void testRequestDisallowInterceptTouchEvent() {
1289         MockViewGroup father = new MockViewGroup(mContext);
1290         MockView son = new MockView(mContext);
1291 
1292         father.addView(son);
1293         son.requestDisallowInterceptTouchEvent(true);
1294         son.requestDisallowInterceptTouchEvent(false);
1295         assertTrue(father.isRequestDisallowInterceptTouchEventCalled);
1296     }
1297 
testRequestFocus()1298     public void testRequestFocus() {
1299         MockViewGroup vg = new MockViewGroup(mContext);
1300 
1301         vg.requestFocus(View.FOCUS_DOWN, new Rect());
1302         assertTrue(vg.isOnRequestFocusInDescendantsCalled);
1303     }
1304 
testRequestTransparentRegion()1305     public void testRequestTransparentRegion() {
1306         MockViewGroup father = new MockViewGroup(mContext);
1307         MockView son1 = new MockView(mContext);
1308         MockView son2 = new MockView(mContext);
1309         son1.addView(son2);
1310         father.addView(son1);
1311         son1.requestTransparentRegion(son2);
1312         assertTrue(father.isRequestTransparentRegionCalled);
1313     }
1314 
testScheduleLayoutAnimation()1315     public void testScheduleLayoutAnimation() {
1316         MockViewGroup vg = new MockViewGroup(mContext);
1317         Animation animation = new AlphaAnimation(mContext, null);
1318 
1319         MockLayoutAnimationController al = new MockLayoutAnimationController(animation);
1320         vg.setLayoutAnimation(al);
1321         vg.scheduleLayoutAnimation();
1322         vg.dispatchDraw(new Canvas());
1323         assertTrue(al.mIsStartCalled);
1324     }
1325 
1326     static class MockLayoutAnimationController extends LayoutAnimationController {
1327 
1328         public boolean mIsStartCalled;
1329 
MockLayoutAnimationController(Animation animation)1330         public MockLayoutAnimationController(Animation animation) {
1331             super(animation);
1332         }
1333 
1334         @Override
start()1335         public void start() {
1336             mIsStartCalled = true;
1337             super.start();
1338         }
1339     }
1340 
testSetAddStatesFromChildren()1341     public void testSetAddStatesFromChildren() {
1342         MockViewGroup vg = new MockViewGroup(mContext);
1343         vg.setAddStatesFromChildren(true);
1344         assertTrue(vg.addStatesFromChildren());
1345 
1346         vg.setAddStatesFromChildren(false);
1347         assertFalse(vg.addStatesFromChildren());
1348     }
1349 
testSetChildrenDrawingCacheEnabled()1350     public void testSetChildrenDrawingCacheEnabled() {
1351         MockViewGroup vg = new MockViewGroup(mContext);
1352 
1353         assertTrue(vg.isAnimationCacheEnabled());
1354 
1355         vg.setAnimationCacheEnabled(false);
1356         assertFalse(vg.isAnimationCacheEnabled());
1357 
1358         vg.setAnimationCacheEnabled(true);
1359         assertTrue(vg.isAnimationCacheEnabled());
1360     }
1361 
testSetChildrenDrawnWithCacheEnabled()1362     public void testSetChildrenDrawnWithCacheEnabled() {
1363         MockViewGroup vg = new MockViewGroup(mContext);
1364 
1365         assertFalse(vg.isChildrenDrawnWithCacheEnabled());
1366 
1367         vg.setChildrenDrawnWithCacheEnabled(true);
1368         assertTrue(vg.isChildrenDrawnWithCacheEnabled());
1369 
1370         vg.setChildrenDrawnWithCacheEnabled(false);
1371         assertFalse(vg.isChildrenDrawnWithCacheEnabled());
1372     }
1373 
testSetClipChildren()1374     public void testSetClipChildren() {
1375         Bitmap bitmap = Bitmap.createBitmap(100, 100, Bitmap.Config.ARGB_8888);
1376 
1377         MockViewGroup vg = new MockViewGroup(mContext);
1378         MockTextView textView = new MockTextView(mContext);
1379         textView.layout(1, 2, 30, 40);
1380         vg.layout(1, 1, 100, 200);
1381         vg.setClipChildren(true);
1382 
1383         MockCanvas canvas = new MockCanvas(bitmap);
1384         vg.drawChild(canvas, textView, 100);
1385         Rect rect = canvas.getClipBounds();
1386         assertEquals(0, rect.top);
1387         assertEquals(100, rect.bottom);
1388         assertEquals(0, rect.left);
1389         assertEquals(100, rect.right);
1390     }
1391 
1392     class MockCanvas extends Canvas {
1393 
1394         public boolean mIsSaveCalled;
1395         public int mLeft;
1396         public int mTop;
1397         public int mRight;
1398         public int mBottom;
1399 
MockCanvas()1400         public MockCanvas() {
1401             super(Bitmap.createBitmap(100, 100, Bitmap.Config.ARGB_8888));
1402         }
1403 
MockCanvas(Bitmap bitmap)1404         public MockCanvas(Bitmap bitmap) {
1405             super(bitmap);
1406         }
1407 
1408         @Override
quickReject(float left, float top, float right, float bottom, EdgeType type)1409         public boolean quickReject(float left, float top, float right,
1410                 float bottom, EdgeType type) {
1411             super.quickReject(left, top, right, bottom, type);
1412             return false;
1413         }
1414 
1415         @Override
save()1416         public int save() {
1417             mIsSaveCalled = true;
1418             return super.save();
1419         }
1420 
1421         @Override
clipRect(int left, int top, int right, int bottom)1422         public boolean clipRect(int left, int top, int right, int bottom) {
1423             mLeft = left;
1424             mTop = top;
1425             mRight = right;
1426             mBottom = bottom;
1427             return super.clipRect(left, top, right, bottom);
1428         }
1429     }
1430 
testSetClipToPadding()1431     public void testSetClipToPadding() {
1432         final int frameLeft = 1;
1433         final int frameTop = 2;
1434         final int frameRight = 100;
1435         final int frameBottom = 200;
1436         MockViewGroup vg = new MockViewGroup(mContext);
1437         vg.layout(frameLeft, frameTop, frameRight, frameBottom);
1438 
1439         vg.setClipToPadding(true);
1440         MockCanvas canvas = new MockCanvas();
1441         final int paddingLeft = 10;
1442         final int paddingTop = 20;
1443         final int paddingRight = 100;
1444         final int paddingBottom = 200;
1445         vg.setPadding(paddingLeft, paddingTop, paddingRight, paddingBottom);
1446         vg.dispatchDraw(canvas);
1447         //check that the clip region does not contain the padding area
1448         assertTrue(canvas.mIsSaveCalled);
1449         assertEquals(10, canvas.mLeft);
1450         assertEquals(20, canvas.mTop);
1451         assertEquals(-frameLeft, canvas.mRight);
1452         assertEquals(-frameTop, canvas.mBottom);
1453 
1454         vg.setClipToPadding(false);
1455         canvas = new MockCanvas();
1456         vg.dispatchDraw(canvas);
1457         assertFalse(canvas.mIsSaveCalled);
1458         assertEquals(0, canvas.mLeft);
1459         assertEquals(0, canvas.mTop);
1460         assertEquals(0, canvas.mRight);
1461         assertEquals(0, canvas.mBottom);
1462     }
1463 
testSetDescendantFocusability()1464     public void testSetDescendantFocusability() {
1465         MockViewGroup vg = new MockViewGroup(mContext);
1466         final int FLAG_MASK_FOCUSABILITY = 0x60000;
1467         assertFalse((vg.getDescendantFocusability() & FLAG_MASK_FOCUSABILITY) == 0);
1468 
1469         vg.setDescendantFocusability(ViewGroup.FOCUS_BLOCK_DESCENDANTS);
1470         assertFalse((vg.getDescendantFocusability() & FLAG_MASK_FOCUSABILITY) == 0);
1471 
1472         vg.setDescendantFocusability(ViewGroup.FOCUS_BEFORE_DESCENDANTS);
1473         assertFalse((vg.getDescendantFocusability() & FLAG_MASK_FOCUSABILITY) == 0);
1474         assertFalse((vg.getDescendantFocusability() &
1475                 ViewGroup.FOCUS_BEFORE_DESCENDANTS) == 0);
1476     }
1477 
testSetOnHierarchyChangeListener()1478     public void testSetOnHierarchyChangeListener() {
1479         MockViewGroup father = new MockViewGroup(mContext);
1480         MockViewGroup son = new MockViewGroup(mContext);
1481         MockOnHierarchyChangeListener listener = new MockOnHierarchyChangeListener();
1482         father.setOnHierarchyChangeListener(listener);
1483         father.addView(son);
1484 
1485         father.removeDetachedView(son, false);
1486         assertSame(father, listener.sParent);
1487         assertSame(son, listener.sChild);
1488     }
1489 
testSetPadding()1490     public void testSetPadding() {
1491         final int left = 1;
1492         final int top = 2;
1493         final int right = 3;
1494         final int bottom = 4;
1495 
1496         MockViewGroup vg = new MockViewGroup(mContext);
1497 
1498         assertEquals(0, vg.getPaddingBottom());
1499         assertEquals(0, vg.getPaddingTop());
1500         assertEquals(0, vg.getPaddingLeft());
1501         assertEquals(0, vg.getPaddingRight());
1502         assertEquals(0, vg.getPaddingStart());
1503         assertEquals(0, vg.getPaddingEnd());
1504 
1505         vg.setPadding(left, top, right, bottom);
1506 
1507         assertEquals(bottom, vg.getPaddingBottom());
1508         assertEquals(top, vg.getPaddingTop());
1509         assertEquals(left, vg.getPaddingLeft());
1510         assertEquals(right, vg.getPaddingRight());
1511 
1512         assertEquals(left, vg.getPaddingStart());
1513         assertEquals(right, vg.getPaddingEnd());
1514         assertEquals(false, vg.isPaddingRelative());
1515 
1516         // force RTL direction
1517         vg.setLayoutDirection(View.LAYOUT_DIRECTION_RTL);
1518 
1519         assertEquals(bottom, vg.getPaddingBottom());
1520         assertEquals(top, vg.getPaddingTop());
1521         assertEquals(left, vg.getPaddingLeft());
1522         assertEquals(right, vg.getPaddingRight());
1523 
1524         assertEquals(right, vg.getPaddingStart());
1525         assertEquals(left, vg.getPaddingEnd());
1526         assertEquals(false, vg.isPaddingRelative());
1527     }
1528 
testSetPaddingRelative()1529     public void testSetPaddingRelative() {
1530         final int start = 1;
1531         final int top = 2;
1532         final int end = 3;
1533         final int bottom = 4;
1534 
1535         MockViewGroup vg = new MockViewGroup(mContext);
1536 
1537         assertEquals(0, vg.getPaddingBottom());
1538         assertEquals(0, vg.getPaddingTop());
1539         assertEquals(0, vg.getPaddingLeft());
1540         assertEquals(0, vg.getPaddingRight());
1541         assertEquals(0, vg.getPaddingStart());
1542         assertEquals(0, vg.getPaddingEnd());
1543 
1544         vg.setPaddingRelative(start, top, end, bottom);
1545 
1546         assertEquals(bottom, vg.getPaddingBottom());
1547         assertEquals(top, vg.getPaddingTop());
1548         assertEquals(start, vg.getPaddingLeft());
1549         assertEquals(end, vg.getPaddingRight());
1550 
1551         assertEquals(start, vg.getPaddingStart());
1552         assertEquals(end, vg.getPaddingEnd());
1553         assertEquals(true, vg.isPaddingRelative());
1554 
1555         // force RTL direction after setting relative padding
1556         vg.setLayoutDirection(View.LAYOUT_DIRECTION_RTL);
1557 
1558         assertEquals(bottom, vg.getPaddingBottom());
1559         assertEquals(top, vg.getPaddingTop());
1560         assertEquals(end, vg.getPaddingLeft());
1561         assertEquals(start, vg.getPaddingRight());
1562 
1563         assertEquals(start, vg.getPaddingStart());
1564         assertEquals(end, vg.getPaddingEnd());
1565         assertEquals(true, vg.isPaddingRelative());
1566 
1567         // force RTL direction before setting relative padding
1568         vg = new MockViewGroup(mContext);
1569         vg.setLayoutDirection(View.LAYOUT_DIRECTION_RTL);
1570 
1571         assertEquals(0, vg.getPaddingBottom());
1572         assertEquals(0, vg.getPaddingTop());
1573         assertEquals(0, vg.getPaddingLeft());
1574         assertEquals(0, vg.getPaddingRight());
1575         assertEquals(0, vg.getPaddingStart());
1576         assertEquals(0, vg.getPaddingEnd());
1577 
1578         vg.setPaddingRelative(start, top, end, bottom);
1579 
1580         assertEquals(bottom, vg.getPaddingBottom());
1581         assertEquals(top, vg.getPaddingTop());
1582         assertEquals(end, vg.getPaddingLeft());
1583         assertEquals(start, vg.getPaddingRight());
1584 
1585         assertEquals(start, vg.getPaddingStart());
1586         assertEquals(end, vg.getPaddingEnd());
1587         assertEquals(true, vg.isPaddingRelative());
1588     }
1589 
testSetPersistentDrawingCache()1590     public void testSetPersistentDrawingCache() {
1591         MockViewGroup vg = new MockViewGroup(mContext);
1592         vg.setPersistentDrawingCache(1);
1593         assertEquals(1 & ViewGroup.PERSISTENT_ALL_CACHES, vg
1594                 .getPersistentDrawingCache());
1595     }
1596 
testShowContextMenuForChild()1597     public void testShowContextMenuForChild() {
1598         MockViewGroup father = new MockViewGroup(mContext);
1599         MockViewGroup son = new MockViewGroup(mContext);
1600         father.addView(son);
1601 
1602         son.showContextMenuForChild(null);
1603         assertTrue(father.isShowContextMenuForChildCalled);
1604     }
1605 
testStartLayoutAnimation()1606     public void testStartLayoutAnimation() {
1607         MockViewGroup vg = new MockViewGroup(mContext);
1608         RotateAnimation animation = new RotateAnimation(0.1f, 0.1f);
1609         LayoutAnimationController la = new LayoutAnimationController(animation);
1610         vg.setLayoutAnimation(la);
1611 
1612         vg.layout(1, 1, 100, 100);
1613         assertFalse(vg.isLayoutRequested());
1614         vg.startLayoutAnimation();
1615         assertTrue(vg.isLayoutRequested());
1616     }
1617 
testUpdateViewLayout()1618     public void testUpdateViewLayout() {
1619         MockViewGroup father = new MockViewGroup(mContext);
1620         MockViewGroup son = new MockViewGroup(mContext);
1621 
1622         father.addView(son);
1623         LayoutParams param = new LayoutParams(100, 200);
1624         father.updateViewLayout(son, param);
1625         assertEquals(param.width, son.getLayoutParams().width);
1626         assertEquals(param.height, son.getLayoutParams().height);
1627     }
1628 
testDebug()1629     public void testDebug() {
1630         final int EXPECTED = 100;
1631         MockViewGroup father = new MockViewGroup(mContext);
1632         MockViewGroup son = new MockViewGroup(mContext);
1633         father.addView(son);
1634 
1635         father.debug(EXPECTED);
1636         assertEquals(EXPECTED + 1, son.debugDepth);
1637     }
1638 
testDispatchKeyEventPreIme()1639     public void testDispatchKeyEventPreIme() {
1640         MockViewGroup vg = new MockViewGroup(mContext);
1641         KeyEvent event = new KeyEvent(KeyEvent.ACTION_DOWN, KeyEvent.KEYCODE_ENTER);
1642         assertFalse(vg.dispatchKeyEventPreIme(event));
1643         assertFalse(vg.dispatchKeyShortcutEvent(event));
1644         MockTextView textView = new MockTextView(mContext);
1645 
1646         vg.addView(textView);
1647         vg.requestChildFocus(textView, null);
1648         vg.layout(0, 0, 100, 200);
1649         assertFalse(vg.dispatchKeyEventPreIme(event));
1650         assertFalse(vg.dispatchKeyShortcutEvent(event));
1651 
1652         vg.requestChildFocus(textView, null);
1653         textView.layout(0, 0, 50, 50);
1654         assertTrue(vg.dispatchKeyEventPreIme(event));
1655         assertTrue(vg.dispatchKeyShortcutEvent(event));
1656 
1657         vg.setStaticTransformationsEnabled(true);
1658         Canvas canvas = new Canvas();
1659         vg.drawChild(canvas, textView, 100);
1660         assertTrue(vg.isGetChildStaticTransformationCalled);
1661         vg.isGetChildStaticTransformationCalled = false;
1662         vg.setStaticTransformationsEnabled(false);
1663         vg.drawChild(canvas, textView, 100);
1664         assertFalse(vg.isGetChildStaticTransformationCalled);
1665     }
1666 
testStartActionModeForChildRespectsSubclassModeOnPrimary()1667     public void testStartActionModeForChildRespectsSubclassModeOnPrimary() {
1668         MockViewGroupSubclass vgParent = new MockViewGroupSubclass(mContext);
1669         MockViewGroupSubclass vg = new MockViewGroupSubclass(mContext);
1670         vg.shouldReturnOwnTypelessActionMode = true;
1671         vgParent.addView(vg);
1672         MockTextView textView = new MockTextView(mContext);
1673         vg.addView(textView);
1674 
1675         textView.startActionMode(NO_OP_ACTION_MODE_CALLBACK, ActionMode.TYPE_PRIMARY);
1676 
1677         assertTrue(vg.isStartActionModeForChildTypedCalled);
1678         assertTrue(vg.isStartActionModeForChildTypelessCalled);
1679         // Call should not bubble up as we have an intercepting implementation.
1680         assertFalse(vgParent.isStartActionModeForChildTypedCalled);
1681     }
1682 
testStartActionModeForChildIgnoresSubclassModeOnFloating()1683     public void testStartActionModeForChildIgnoresSubclassModeOnFloating() {
1684         MockViewGroupSubclass vgParent = new MockViewGroupSubclass(mContext);
1685         MockViewGroupSubclass vg = new MockViewGroupSubclass(mContext);
1686         vg.shouldReturnOwnTypelessActionMode = true;
1687         vgParent.addView(vg);
1688         MockTextView textView = new MockTextView(mContext);
1689         vg.addView(textView);
1690 
1691         textView.startActionMode(NO_OP_ACTION_MODE_CALLBACK, ActionMode.TYPE_FLOATING);
1692 
1693         assertTrue(vg.isStartActionModeForChildTypedCalled);
1694         assertFalse(vg.isStartActionModeForChildTypelessCalled);
1695         // Call should bubble up as we have a floating type.
1696         assertTrue(vgParent.isStartActionModeForChildTypedCalled);
1697     }
1698 
testStartActionModeForChildTypedBubblesUpToParent()1699     public void testStartActionModeForChildTypedBubblesUpToParent() {
1700         MockViewGroupSubclass vgParent = new MockViewGroupSubclass(mContext);
1701         MockViewGroupSubclass vg = new MockViewGroupSubclass(mContext);
1702         vgParent.addView(vg);
1703         MockTextView textView = new MockTextView(mContext);
1704         vg.addView(textView);
1705 
1706         textView.startActionMode(NO_OP_ACTION_MODE_CALLBACK, ActionMode.TYPE_FLOATING);
1707 
1708         assertTrue(vg.isStartActionModeForChildTypedCalled);
1709         assertTrue(vgParent.isStartActionModeForChildTypedCalled);
1710     }
1711 
testStartActionModeForChildTypelessBubblesUpToParent()1712     public void testStartActionModeForChildTypelessBubblesUpToParent() {
1713         MockViewGroupSubclass vgParent = new MockViewGroupSubclass(mContext);
1714         MockViewGroupSubclass vg = new MockViewGroupSubclass(mContext);
1715         vgParent.addView(vg);
1716         MockTextView textView = new MockTextView(mContext);
1717         vg.addView(textView);
1718 
1719         textView.startActionMode(NO_OP_ACTION_MODE_CALLBACK);
1720 
1721         assertTrue(vg.isStartActionModeForChildTypedCalled);
1722         assertTrue(vg.isStartActionModeForChildTypelessCalled);
1723         assertTrue(vgParent.isStartActionModeForChildTypedCalled);
1724     }
1725 
1726     private static final ActionMode.Callback NO_OP_ACTION_MODE_CALLBACK =
1727             new ActionMode.Callback() {
1728                 @Override
1729                 public boolean onPrepareActionMode(ActionMode mode, Menu menu) {
1730                     return false;
1731                 }
1732 
1733                 @Override
1734                 public void onDestroyActionMode(ActionMode mode) {}
1735 
1736                 @Override
1737                 public boolean onCreateActionMode(ActionMode mode, Menu menu) {
1738                     return false;
1739                 }
1740 
1741                 @Override
1742                 public boolean onActionItemClicked(ActionMode mode, MenuItem item) {
1743                     return false;
1744                 }
1745             };
1746 
1747     private static final ActionMode NO_OP_ACTION_MODE =
1748             new ActionMode() {
1749                 @Override
1750                 public void setTitle(CharSequence title) {}
1751 
1752                 @Override
1753                 public void setTitle(int resId) {}
1754 
1755                 @Override
1756                 public void setSubtitle(CharSequence subtitle) {}
1757 
1758                 @Override
1759                 public void setSubtitle(int resId) {}
1760 
1761                 @Override
1762                 public void setCustomView(View view) {}
1763 
1764                 @Override
1765                 public void invalidate() {}
1766 
1767                 @Override
1768                 public void finish() {}
1769 
1770                 @Override
1771                 public Menu getMenu() {
1772                     return null;
1773                 }
1774 
1775                 @Override
1776                 public CharSequence getTitle() {
1777                     return null;
1778                 }
1779 
1780                 @Override
1781                 public CharSequence getSubtitle() {
1782                     return null;
1783                 }
1784 
1785                 @Override
1786                 public View getCustomView() {
1787                     return null;
1788                 }
1789 
1790                 @Override
1791                 public MenuInflater getMenuInflater() {
1792                     return null;
1793                 }
1794             };
1795 
1796     private static class MockViewGroupSubclass extends ViewGroup {
1797         boolean isStartActionModeForChildTypedCalled = false;
1798         boolean isStartActionModeForChildTypelessCalled = false;
1799         boolean shouldReturnOwnTypelessActionMode = false;
1800 
MockViewGroupSubclass(Context context)1801         public MockViewGroupSubclass(Context context) {
1802             super(context);
1803         }
1804 
1805         @Override
startActionModeForChild(View originalView, ActionMode.Callback callback)1806         public ActionMode startActionModeForChild(View originalView, ActionMode.Callback callback) {
1807             isStartActionModeForChildTypelessCalled = true;
1808             if (shouldReturnOwnTypelessActionMode) {
1809                 return NO_OP_ACTION_MODE;
1810             }
1811             return super.startActionModeForChild(originalView, callback);
1812         }
1813 
1814         @Override
startActionModeForChild( View originalView, ActionMode.Callback callback, int type)1815         public ActionMode startActionModeForChild(
1816                 View originalView, ActionMode.Callback callback, int type) {
1817             isStartActionModeForChildTypedCalled = true;
1818             return super.startActionModeForChild(originalView, callback, type);
1819         }
1820 
1821         @Override
onLayout(boolean changed, int l, int t, int r, int b)1822         protected void onLayout(boolean changed, int l, int t, int r, int b) {
1823             // no-op
1824         }
1825     }
1826 
1827     static public int resetRtlPropertiesCount;
1828     static public int resetResolvedLayoutDirectionCount;
1829     static public int resetResolvedTextDirectionCount;
1830     static public int resetResolvedTextAlignmentCount;
1831     static public int resetResolvedPaddingCount;
1832     static public int resetResolvedDrawablesCount;
1833 
1834 
clearRtlCounters()1835     private static void clearRtlCounters() {
1836         resetRtlPropertiesCount = 0;
1837         resetResolvedLayoutDirectionCount = 0;
1838         resetResolvedTextDirectionCount = 0;
1839         resetResolvedTextAlignmentCount = 0;
1840         resetResolvedPaddingCount = 0;
1841         resetResolvedDrawablesCount = 0;
1842     }
1843 
testResetRtlProperties()1844     public void testResetRtlProperties() {
1845         clearRtlCounters();
1846 
1847         MockViewGroup vg = new MockViewGroup(mContext);
1848         MockView2 v1 = new MockView2(mContext);
1849         MockView2 v2 = new MockView2(mContext);
1850 
1851         MockViewGroup v3 = new MockViewGroup(mContext);
1852         MockView2 v4 = new MockView2(mContext);
1853 
1854         v3.addView(v4);
1855         assertEquals(1, resetRtlPropertiesCount);
1856         assertEquals(1, resetResolvedLayoutDirectionCount);
1857         assertEquals(1, resetResolvedTextDirectionCount);
1858         assertEquals(1, resetResolvedTextAlignmentCount);
1859         assertEquals(1, resetResolvedPaddingCount);
1860         assertEquals(1, resetResolvedDrawablesCount);
1861 
1862         clearRtlCounters();
1863         vg.addView(v1);
1864         vg.addView(v2);
1865         vg.addView(v3);
1866 
1867         assertEquals(3, resetRtlPropertiesCount); // for v1 / v2 / v3 only
1868         assertEquals(4, resetResolvedLayoutDirectionCount); // for v1 / v2 / v3 / v4
1869         assertEquals(4, resetResolvedTextDirectionCount);
1870         assertEquals(3, resetResolvedTextAlignmentCount); // for v1 / v2 / v3 only
1871         assertEquals(4, resetResolvedPaddingCount);
1872         assertEquals(4, resetResolvedDrawablesCount);
1873 
1874         clearRtlCounters();
1875         vg.resetRtlProperties();
1876         assertEquals(1, resetRtlPropertiesCount); // for vg only
1877         assertEquals(5, resetResolvedLayoutDirectionCount); // for all
1878         assertEquals(5, resetResolvedTextDirectionCount);
1879         assertEquals(1, resetResolvedTextAlignmentCount); // for vg only as TextAlignment is not inherited (default is Gravity)
1880         assertEquals(5, resetResolvedPaddingCount);
1881         assertEquals(5, resetResolvedDrawablesCount);
1882     }
1883 
1884     static class MockTextView extends TextView {
1885 
1886         public boolean isClearFocusCalled;
1887         public boolean isDispatchRestoreInstanceStateCalled;
1888         public int visibility;
1889         public boolean mIsRefreshDrawableStateCalled;
1890         public boolean isDrawCalled;
1891 
MockTextView(Context context)1892         public MockTextView(Context context) {
1893             super(context);
1894         }
1895 
1896         @Override
draw(Canvas canvas)1897         public void draw(Canvas canvas) {
1898             super.draw(canvas);
1899             isDrawCalled = true;
1900         }
1901 
1902         @Override
clearFocus()1903         public void clearFocus() {
1904             isClearFocusCalled = true;
1905             super.clearFocus();
1906         }
1907 
1908         @Override
dispatchKeyEvent(KeyEvent event)1909         public boolean dispatchKeyEvent(KeyEvent event) {
1910             return true;
1911         }
1912 
1913         @Override
dispatchRestoreInstanceState( SparseArray<Parcelable> container)1914         public void dispatchRestoreInstanceState(
1915                 SparseArray<Parcelable> container) {
1916             isDispatchRestoreInstanceStateCalled = true;
1917             super.dispatchRestoreInstanceState(container);
1918         }
1919 
1920         @Override
onTrackballEvent(MotionEvent event)1921         public boolean onTrackballEvent(MotionEvent event) {
1922             return true;
1923         }
1924 
1925         @Override
dispatchUnhandledMove(View focused, int direction)1926         public boolean dispatchUnhandledMove(View focused, int direction) {
1927             return true;
1928         }
1929 
1930         @Override
onWindowVisibilityChanged(int visibility)1931         public void onWindowVisibilityChanged(int visibility) {
1932             this.visibility = visibility;
1933             super.onWindowVisibilityChanged(visibility);
1934         }
1935 
1936         @Override
refreshDrawableState()1937         public void refreshDrawableState() {
1938             mIsRefreshDrawableStateCalled = true;
1939             super.refreshDrawableState();
1940         }
1941 
1942         @Override
dispatchTouchEvent(MotionEvent event)1943         public boolean dispatchTouchEvent(MotionEvent event) {
1944             super.dispatchTouchEvent(event);
1945             return true;
1946         }
1947 
1948         @Override
dispatchKeyEventPreIme(KeyEvent event)1949         public boolean dispatchKeyEventPreIme(KeyEvent event) {
1950             return true;
1951         }
1952 
1953         @Override
dispatchKeyShortcutEvent(KeyEvent event)1954         public boolean dispatchKeyShortcutEvent(KeyEvent event) {
1955             return true;
1956         }
1957     }
1958 
1959     static class MockViewGroup extends ViewGroup {
1960 
1961         public boolean isRecomputeViewAttributesCalled;
1962         public boolean isShowContextMenuForChildCalled;
1963         public boolean isRefreshDrawableStateCalled;
1964         public boolean isOnRestoreInstanceStateCalled;
1965         public boolean isOnCreateDrawableStateCalled;
1966         public boolean isOnInterceptTouchEventCalled;
1967         public boolean isOnRequestFocusInDescendantsCalled;
1968         public boolean isFocusableViewAvailable;
1969         public boolean isDispatchDrawCalled;
1970         public boolean isRequestDisallowInterceptTouchEventCalled;
1971         public boolean isRequestTransparentRegionCalled;
1972         public boolean isGetChildStaticTransformationCalled;
1973         public int[] location;
1974         public int measureChildCalledTime;
1975         public boolean isOnAnimationEndCalled;
1976         public boolean isOnAnimationStartCalled;
1977         public int debugDepth;
1978         public int drawChildCalledTime;
1979         public Canvas canvas;
1980         public boolean isInvalidateChildInParentCalled;
1981         public boolean isDrawableStateChangedCalled;
1982         public boolean isRequestLayoutCalled;
1983         public boolean isOnLayoutCalled;
1984         public int left;
1985         public int top;
1986         public int right;
1987         public int bottom;
1988 
MockViewGroup(Context context, AttributeSet attrs, int defStyle)1989         public MockViewGroup(Context context, AttributeSet attrs, int defStyle) {
1990             super(context, attrs, defStyle);
1991         }
1992 
MockViewGroup(Context context, AttributeSet attrs)1993         public MockViewGroup(Context context, AttributeSet attrs) {
1994             super(context, attrs);
1995         }
1996 
MockViewGroup(Context context)1997         public MockViewGroup(Context context) {
1998             super(context);
1999         }
2000 
2001         @Override
onLayout(boolean changed, int l, int t, int r, int b)2002         public void onLayout(boolean changed, int l, int t, int r, int b) {
2003             isOnLayoutCalled = true;
2004             left = l;
2005             top = t;
2006             right = r;
2007             bottom = b;
2008         }
2009 
2010         @Override
addViewInLayout(View child, int index, ViewGroup.LayoutParams params)2011         public boolean addViewInLayout(View child, int index,
2012                 ViewGroup.LayoutParams params) {
2013             return super.addViewInLayout(child, index, params);
2014         }
2015 
2016         @Override
addViewInLayout(View child, int index, ViewGroup.LayoutParams params, boolean preventRequestLayout)2017         public boolean addViewInLayout(View child, int index,
2018                 ViewGroup.LayoutParams params, boolean preventRequestLayout) {
2019             return super.addViewInLayout(child, index, params, preventRequestLayout);
2020         }
2021 
2022         @Override
attachLayoutAnimationParameters(View child, ViewGroup.LayoutParams params, int index, int count)2023         public void attachLayoutAnimationParameters(View child,
2024                 ViewGroup.LayoutParams params, int index, int count) {
2025             super.attachLayoutAnimationParameters(child, params, index, count);
2026         }
2027 
2028         @Override
attachViewToParent(View child, int index, LayoutParams params)2029         public void attachViewToParent(View child, int index,
2030                 LayoutParams params) {
2031             super.attachViewToParent(child, index, params);
2032         }
2033 
2034         @Override
canAnimate()2035         public boolean canAnimate() {
2036             return super.canAnimate();
2037         }
2038 
2039         @Override
checkLayoutParams(LayoutParams p)2040         public boolean checkLayoutParams(LayoutParams p) {
2041             return super.checkLayoutParams(p);
2042         }
2043 
2044         @Override
refreshDrawableState()2045         public void refreshDrawableState() {
2046             isRefreshDrawableStateCalled = true;
2047             super.refreshDrawableState();
2048         }
2049 
2050         @Override
cleanupLayoutState(View child)2051         public void cleanupLayoutState(View child) {
2052             super.cleanupLayoutState(child);
2053         }
2054 
2055         @Override
detachAllViewsFromParent()2056         public void detachAllViewsFromParent() {
2057             super.detachAllViewsFromParent();
2058         }
2059 
2060         @Override
detachViewFromParent(int index)2061         public void detachViewFromParent(int index) {
2062             super.detachViewFromParent(index);
2063         }
2064 
2065         @Override
detachViewFromParent(View child)2066         public void detachViewFromParent(View child) {
2067             super.detachViewFromParent(child);
2068         }
2069         @Override
2070 
detachViewsFromParent(int start, int count)2071         public void detachViewsFromParent(int start, int count) {
2072             super.detachViewsFromParent(start, count);
2073         }
2074 
2075         @Override
dispatchDraw(Canvas canvas)2076         public void dispatchDraw(Canvas canvas) {
2077             isDispatchDrawCalled = true;
2078             super.dispatchDraw(canvas);
2079             this.canvas = canvas;
2080         }
2081 
2082         @Override
dispatchFreezeSelfOnly(SparseArray<Parcelable> container)2083         public void dispatchFreezeSelfOnly(SparseArray<Parcelable> container) {
2084             super.dispatchFreezeSelfOnly(container);
2085         }
2086 
2087         @Override
dispatchRestoreInstanceState( SparseArray<Parcelable> container)2088         public void dispatchRestoreInstanceState(
2089                 SparseArray<Parcelable> container) {
2090             super.dispatchRestoreInstanceState(container);
2091         }
2092 
2093         @Override
dispatchSaveInstanceState( SparseArray<Parcelable> container)2094         public void dispatchSaveInstanceState(
2095                 SparseArray<Parcelable> container) {
2096             super.dispatchSaveInstanceState(container);
2097         }
2098 
2099         @Override
dispatchSetPressed(boolean pressed)2100         public void dispatchSetPressed(boolean pressed) {
2101             super.dispatchSetPressed(pressed);
2102         }
2103 
2104         @Override
dispatchThawSelfOnly(SparseArray<Parcelable> container)2105         public void dispatchThawSelfOnly(SparseArray<Parcelable> container) {
2106             super.dispatchThawSelfOnly(container);
2107         }
2108 
2109         @Override
onRestoreInstanceState(Parcelable state)2110         public void onRestoreInstanceState(Parcelable state) {
2111             isOnRestoreInstanceStateCalled = true;
2112             super.onRestoreInstanceState(state);
2113         }
2114 
2115         @Override
drawableStateChanged()2116         public void drawableStateChanged() {
2117             isDrawableStateChangedCalled = true;
2118             super.drawableStateChanged();
2119         }
2120 
2121         @Override
drawChild(Canvas canvas, View child, long drawingTime)2122         public boolean drawChild(Canvas canvas, View child, long drawingTime) {
2123             drawChildCalledTime++;
2124             return super.drawChild(canvas, child, drawingTime);
2125         }
2126 
2127         @Override
fitSystemWindows(Rect insets)2128         public boolean fitSystemWindows(Rect insets) {
2129             return super.fitSystemWindows(insets);
2130         }
2131 
2132         @Override
generateDefaultLayoutParams()2133         public LayoutParams generateDefaultLayoutParams() {
2134             return super.generateDefaultLayoutParams();
2135         }
2136 
2137         @Override
generateLayoutParams(LayoutParams p)2138         public LayoutParams generateLayoutParams(LayoutParams p) {
2139             return super.generateLayoutParams(p);
2140         }
2141 
2142         @Override
getChildDrawingOrder(int childCount, int i)2143         public int getChildDrawingOrder(int childCount, int i) {
2144             return super.getChildDrawingOrder(childCount, i);
2145         }
2146 
2147         @Override
getChildStaticTransformation(View child, Transformation t)2148         public boolean getChildStaticTransformation(View child,
2149                 Transformation t) {
2150             isGetChildStaticTransformationCalled = true;
2151             return super.getChildStaticTransformation(child, t);
2152         }
2153 
2154         @Override
measureChild(View child, int parentWidthMeasureSpec, int parentHeightMeasureSpec)2155         public void measureChild(View child, int parentWidthMeasureSpec,
2156                 int parentHeightMeasureSpec) {
2157             measureChildCalledTime++;
2158             super.measureChild(child, parentWidthMeasureSpec, parentHeightMeasureSpec);
2159         }
2160 
2161         @Override
measureChildren(int widthMeasureSpec, int heightMeasureSpec)2162         public void measureChildren(int widthMeasureSpec,
2163                 int heightMeasureSpec) {
2164             super.measureChildren(widthMeasureSpec, heightMeasureSpec);
2165         }
2166 
2167         @Override
measureChildWithMargins(View child, int parentWidthMeasureSpec, int widthUsed, int parentHeightMeasureSpec, int heightUsed)2168         public void measureChildWithMargins(View child,
2169                 int parentWidthMeasureSpec, int widthUsed,
2170                 int parentHeightMeasureSpec, int heightUsed) {
2171             super.measureChildWithMargins(child, parentWidthMeasureSpec, widthUsed,
2172                     parentHeightMeasureSpec, heightUsed);
2173         }
2174 
2175         @Override
onAnimationEnd()2176         public void onAnimationEnd() {
2177             isOnAnimationEndCalled = true;
2178             super.onAnimationEnd();
2179         }
2180 
2181         @Override
onAnimationStart()2182         public void onAnimationStart() {
2183             super.onAnimationStart();
2184             isOnAnimationStartCalled = true;
2185         }
2186 
2187         @Override
onCreateDrawableState(int extraSpace)2188         public int[] onCreateDrawableState(int extraSpace) {
2189             isOnCreateDrawableStateCalled = true;
2190             return super.onCreateDrawableState(extraSpace);
2191         }
2192 
2193         @Override
onInterceptTouchEvent(MotionEvent ev)2194         public boolean onInterceptTouchEvent(MotionEvent ev) {
2195             isOnInterceptTouchEventCalled = true;
2196             return super.onInterceptTouchEvent(ev);
2197         }
2198 
2199         @Override
onRequestFocusInDescendants(int direction, Rect previouslyFocusedRect)2200         public boolean onRequestFocusInDescendants(int direction,
2201                 Rect previouslyFocusedRect) {
2202             isOnRequestFocusInDescendantsCalled = true;
2203             return super.onRequestFocusInDescendants(direction, previouslyFocusedRect);
2204         }
2205 
2206         @Override
recomputeViewAttributes(View child)2207         public void recomputeViewAttributes(View child) {
2208             isRecomputeViewAttributesCalled = true;
2209             super.recomputeViewAttributes(child);
2210         }
2211 
2212         @Override
removeDetachedView(View child, boolean animate)2213         public void removeDetachedView(View child, boolean animate) {
2214             super.removeDetachedView(child, animate);
2215         }
2216 
2217         @Override
showContextMenuForChild(View originalView)2218         public boolean showContextMenuForChild(View originalView) {
2219             isShowContextMenuForChildCalled = true;
2220             return super.showContextMenuForChild(originalView);
2221         }
2222 
2223         @Override
isInTouchMode()2224         public boolean isInTouchMode() {
2225             super.isInTouchMode();
2226             return false;
2227         }
2228 
2229         @Override
focusableViewAvailable(View v)2230         public void focusableViewAvailable(View v) {
2231             isFocusableViewAvailable = true;
2232             super.focusableViewAvailable(v);
2233         }
2234 
2235         @Override
focusSearch(View focused, int direction)2236         public View focusSearch(View focused, int direction) {
2237             super.focusSearch(focused, direction);
2238             return focused;
2239         }
2240 
2241         @Override
requestDisallowInterceptTouchEvent(boolean disallowIntercept)2242         public void requestDisallowInterceptTouchEvent(boolean disallowIntercept) {
2243             isRequestDisallowInterceptTouchEventCalled = true;
2244             super.requestDisallowInterceptTouchEvent(disallowIntercept);
2245         }
2246 
2247         @Override
requestTransparentRegion(View child)2248         public void requestTransparentRegion(View child) {
2249             isRequestTransparentRegionCalled = true;
2250             super.requestTransparentRegion(child);
2251         }
2252 
2253         @Override
debug(int depth)2254         public void debug(int depth) {
2255             debugDepth = depth;
2256             super.debug(depth);
2257         }
2258 
2259         @Override
requestLayout()2260         public void requestLayout() {
2261             isRequestLayoutCalled = true;
2262             super.requestLayout();
2263         }
2264 
2265         @Override
setStaticTransformationsEnabled(boolean enabled)2266         public void setStaticTransformationsEnabled(boolean enabled) {
2267             super.setStaticTransformationsEnabled(enabled);
2268         }
2269 
2270         @Override
resetRtlProperties()2271         public void resetRtlProperties() {
2272             super.resetRtlProperties();
2273             resetRtlPropertiesCount++;
2274         }
2275 
2276         @Override
resetResolvedLayoutDirection()2277         public void resetResolvedLayoutDirection() {
2278             super.resetResolvedLayoutDirection();
2279             resetResolvedLayoutDirectionCount++;
2280         }
2281 
2282         @Override
resetResolvedTextDirection()2283         public void resetResolvedTextDirection() {
2284             super.resetResolvedTextDirection();
2285             resetResolvedTextDirectionCount++;
2286         }
2287 
2288         @Override
resetResolvedTextAlignment()2289         public void resetResolvedTextAlignment() {
2290             super.resetResolvedTextAlignment();
2291             resetResolvedTextAlignmentCount++;
2292         }
2293 
2294         @Override
resetResolvedPadding()2295         public void resetResolvedPadding() {
2296             super.resetResolvedPadding();
2297             resetResolvedPaddingCount++;
2298         }
2299 
2300         @Override
resetResolvedDrawables()2301         protected void resetResolvedDrawables() {
2302             super.resetResolvedDrawables();
2303             resetResolvedDrawablesCount++;
2304         }
2305 
2306         @Override
setFrame(int left, int top, int right, int bottom)2307         public boolean setFrame(int left, int top, int right, int bottom) {
2308             return super.setFrame(left, top, right, bottom);
2309         }
2310 
2311         @Override
setChildrenDrawnWithCacheEnabled(boolean enabled)2312         public void setChildrenDrawnWithCacheEnabled(boolean enabled) {
2313             super.setChildrenDrawnWithCacheEnabled(enabled);
2314         }
2315 
2316         @Override
isChildrenDrawnWithCacheEnabled()2317         public boolean isChildrenDrawnWithCacheEnabled() {
2318             return super.isChildrenDrawnWithCacheEnabled();
2319         }
2320     }
2321 
2322     static class MockView2 extends View {
2323 
MockView2(Context context)2324         public MockView2(Context context) {
2325             super(context);
2326         }
2327 
MockView2(Context context, AttributeSet attrs)2328         public MockView2(Context context, AttributeSet attrs) {
2329             super(context, attrs);
2330         }
2331 
MockView2(Context context, AttributeSet attrs, int defStyle)2332         public MockView2(Context context, AttributeSet attrs, int defStyle) {
2333             super(context, attrs, defStyle);
2334         }
2335 
2336         @Override
resetRtlProperties()2337         public void resetRtlProperties() {
2338             super.resetRtlProperties();
2339             resetRtlPropertiesCount++;
2340         }
2341 
2342         @Override
resetResolvedLayoutDirection()2343         public void resetResolvedLayoutDirection() {
2344             super.resetResolvedLayoutDirection();
2345             resetResolvedLayoutDirectionCount++;
2346         }
2347 
2348         @Override
resetResolvedTextDirection()2349         public void resetResolvedTextDirection() {
2350             super.resetResolvedTextDirection();
2351             resetResolvedTextDirectionCount++;
2352         }
2353 
2354         @Override
resetResolvedTextAlignment()2355         public void resetResolvedTextAlignment() {
2356             super.resetResolvedTextAlignment();
2357             resetResolvedTextAlignmentCount++;
2358         }
2359 
2360         @Override
resetResolvedPadding()2361         public void resetResolvedPadding() {
2362             super.resetResolvedPadding();
2363             resetResolvedPaddingCount++;
2364         }
2365 
2366         @Override
resetResolvedDrawables()2367         protected void resetResolvedDrawables() {
2368             super.resetResolvedDrawables();
2369             resetResolvedDrawablesCount++;
2370         }
2371     }
2372 
setResult(int resultCode)2373     public void setResult(int resultCode) {
2374         synchronized (mSync) {
2375             mSync.mHasNotify = true;
2376             mSync.notify();
2377             mResultCode = resultCode;
2378         }
2379     }
2380 }
2381