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.graphics.drawable.cts;
18 
19 import junit.framework.TestCase;
20 
21 import java.util.Arrays;
22 
23 import android.graphics.Canvas;
24 import android.graphics.Color;
25 import android.graphics.ColorFilter;
26 import android.graphics.PixelFormat;
27 import android.graphics.PorterDuff.Mode;
28 import android.graphics.Rect;
29 import android.graphics.drawable.Drawable;
30 import android.graphics.drawable.DrawableContainer;
31 import android.graphics.drawable.DrawableContainer.DrawableContainerState;
32 import android.graphics.drawable.LevelListDrawable;
33 
34 public class DrawableContainerTest extends TestCase {
35     private DrawableContainerState mDrawableContainerState;
36 
37     private MockDrawableContainer mMockDrawableContainer;
38     private DrawableContainer mDrawableContainer;
39 
40     @Override
setUp()41     protected void setUp() throws Exception {
42         super.setUp();
43 
44         // DrawableContainerState has no public constructor. Obtain an instance through
45         // LevelListDrawable.getConstants(). This is fine for testing the final methods of
46         // DrawableContainerState.
47         mDrawableContainerState =
48             (DrawableContainerState) new LevelListDrawable().getConstantState();
49         assertNotNull(mDrawableContainerState);
50 
51         mMockDrawableContainer = new MockDrawableContainer();
52         mDrawableContainer = mMockDrawableContainer;
53     }
54 
testDraw()55     public void testDraw() {
56         assertConstantStateNotSet();
57         assertNull(mDrawableContainer.getCurrent());
58 
59         mDrawableContainer.draw(null);
60         mDrawableContainer.draw(new Canvas());
61 
62         mMockDrawableContainer.setConstantState(mDrawableContainerState);
63         MockDrawable dr = new MockDrawable();
64         addAndSelectDrawable(dr);
65 
66         dr.reset();
67         mDrawableContainer.draw(null);
68         assertTrue(dr.hasDrawCalled());
69 
70         dr.reset();
71         mDrawableContainer.draw(new Canvas());
72         assertTrue(dr.hasDrawCalled());
73     }
74 
testSetEnterFadeDuration()75     public void testSetEnterFadeDuration() {
76         helpTestSetEnterFadeDuration(1000);
77         helpTestSetEnterFadeDuration(0);
78     }
79 
helpTestSetEnterFadeDuration(int enterFadeDuration)80     private void helpTestSetEnterFadeDuration(int enterFadeDuration) {
81         DrawableContainer container = new LevelListDrawable();
82         DrawableContainerState cs = ((DrawableContainerState) container.getConstantState());
83         container.setEnterFadeDuration(enterFadeDuration);
84         assertEquals(enterFadeDuration, cs.getEnterFadeDuration());
85     }
86 
testSetExitFadeDuration()87     public void testSetExitFadeDuration() {
88         helpTestSetExitFadeDuration(1000);
89         helpTestSetExitFadeDuration(0);
90     }
91 
helpTestSetExitFadeDuration(int exitFadeDuration)92     private void helpTestSetExitFadeDuration(int exitFadeDuration) {
93         DrawableContainer container = new LevelListDrawable();
94         DrawableContainerState cs = ((DrawableContainerState) container.getConstantState());
95         container.setExitFadeDuration(exitFadeDuration);
96         assertEquals(exitFadeDuration, cs.getExitFadeDuration());
97     }
98 
testGetChangingConfigurations()99     public void testGetChangingConfigurations() {
100         // Workaround for CTS coverage not recognizing calls on subclasses.
101         DrawableContainer dr = mDrawableContainer;
102 
103         assertConstantStateNotSet();
104 
105         try {
106             mDrawableContainer.getChangingConfigurations();
107             fail("Should throw NullPointerException if the constant state is not set.");
108         } catch (NullPointerException e) {
109         }
110 
111         mMockDrawableContainer.setConstantState(mDrawableContainerState);
112         MockDrawable dr0 = new MockDrawable();
113         dr0.setChangingConfigurations(0x001);
114         mDrawableContainerState.addChild(dr0);
115         MockDrawable dr1 = new MockDrawable();
116         dr1.setChangingConfigurations(0x010);
117         mDrawableContainerState.addChild(dr1);
118         dr.selectDrawable(0);
119         assertSame(dr0, mDrawableContainer.getCurrent());
120 
121         // can not set mDrawableContainerState's ChangingConfigurations
122         mDrawableContainer.setChangingConfigurations(0x100);
123         assertEquals(0x111 | mDrawableContainerState.getChangingConfigurations(),
124                 mDrawableContainer.getChangingConfigurations());
125     }
126 
testGetPadding()127     public void testGetPadding() {
128         // Workaround for CTS coverage not recognizing calls on subclasses.
129         DrawableContainer dr = mDrawableContainer;
130 
131         assertConstantStateNotSet();
132         assertNull(mDrawableContainer.getCurrent());
133 
134         Rect result = new Rect(1, 1, 1, 1);
135         try {
136             mDrawableContainer.getPadding(result);
137             fail("Should throw NullPointerException if the constant state is not set.");
138         } catch (NullPointerException e) {
139         }
140 
141         mMockDrawableContainer.setConstantState(mDrawableContainerState);
142         MockDrawable dr0 = new MockDrawable();
143         dr0.setPadding(new Rect(1, 2, 0, 0));
144         mDrawableContainerState.addChild(dr0);
145         MockDrawable dr1 = new MockDrawable();
146         dr1.setPadding(new Rect(0, 0, 3, 4));
147         mDrawableContainerState.addChild(dr1);
148         dr.selectDrawable(0);
149         assertSame(dr0, mDrawableContainer.getCurrent());
150 
151         // use the current drawable's padding
152         mDrawableContainerState.setVariablePadding(true);
153         assertNull(mDrawableContainerState.getConstantPadding());
154         assertTrue(mDrawableContainer.getPadding(result));
155         assertEquals(new Rect(1, 2, 0, 0), result);
156 
157         // use constant state's padding
158         mDrawableContainerState.setVariablePadding(false);
159         assertNotNull(mDrawableContainerState.getConstantPadding());
160         assertTrue(mDrawableContainer.getPadding(result));
161         assertEquals(mDrawableContainerState.getConstantPadding(), result);
162 
163         // use default padding
164         dr.selectDrawable(-1);
165         assertNull(mDrawableContainer.getCurrent());
166         mDrawableContainerState.setVariablePadding(true);
167         assertNull(mDrawableContainerState.getConstantPadding());
168         assertFalse(mDrawableContainer.getPadding(result));
169         assertEquals(new Rect(0, 0, 0, 0), result);
170 
171         try {
172             mDrawableContainer.getPadding(null);
173             fail("Should throw NullPointerException if the padding is null.");
174         } catch (NullPointerException e) {
175         }
176     }
177 
testSetAlpha()178     public void testSetAlpha() {
179         // Workaround for CTS coverage not recognizing calls on subclasses.
180         DrawableContainer dr = mDrawableContainer;
181 
182         assertConstantStateNotSet();
183         assertNull(mDrawableContainer.getCurrent());
184 
185         dr.setAlpha(0);
186 
187         mMockDrawableContainer.setConstantState(mDrawableContainerState);
188         MockDrawable mockDrawable = new MockDrawable();
189         addAndSelectDrawable(mockDrawable);
190 
191         // call current drawable's setAlpha if alpha is changed.
192         mockDrawable.reset();
193         dr.setAlpha(1);
194         assertTrue(mockDrawable.hasSetAlphaCalled());
195 
196         // does not call it if alpha is not changed.
197         mockDrawable.reset();
198         dr.setAlpha(1);
199         assertFalse(mockDrawable.hasSetAlphaCalled());
200     }
201 
testSetDither()202     public void testSetDither() {
203         assertConstantStateNotSet();
204         assertNull(mDrawableContainer.getCurrent());
205 
206         mMockDrawableContainer.setConstantState(mDrawableContainerState);
207         mDrawableContainer.setDither(false);
208         mDrawableContainer.setDither(true);
209 
210         MockDrawable dr = new MockDrawable();
211         addAndSelectDrawable(dr);
212 
213         // call current drawable's setDither if dither is changed.
214         dr.reset();
215         mDrawableContainer.setDither(false);
216         assertTrue(dr.hasSetDitherCalled());
217 
218         // does not call it if dither is not changed.
219         dr.reset();
220         mDrawableContainer.setDither(true);
221         assertTrue(dr.hasSetDitherCalled());
222     }
223 
testSetHotspotBounds()224     public void testSetHotspotBounds() {
225         Rect bounds = new Rect(10, 15, 100, 150);
226         assertConstantStateNotSet();
227         assertNull(mDrawableContainer.getCurrent());
228 
229         mMockDrawableContainer.setConstantState(mDrawableContainerState);
230 
231         MockDrawable dr = new MockDrawable();
232         addAndSelectDrawable(dr);
233 
234         dr.reset();
235         mDrawableContainer.setHotspotBounds(bounds.left, bounds.top, bounds.right, bounds.bottom);
236         Rect outRect = new Rect();
237         mDrawableContainer.getHotspotBounds(outRect);
238         assertEquals(bounds, outRect);
239 
240         dr.reset();
241     }
242 
testGetHotspotBounds()243     public void testGetHotspotBounds() {
244         Rect bounds = new Rect(10, 15, 100, 150);
245         assertConstantStateNotSet();
246         assertNull(mDrawableContainer.getCurrent());
247 
248         mMockDrawableContainer.setConstantState(mDrawableContainerState);
249 
250         MockDrawable dr = new MockDrawable();
251         addAndSelectDrawable(dr);
252 
253         dr.reset();
254         mDrawableContainer.setHotspotBounds(bounds.left, bounds.top, bounds.right, bounds.bottom);
255         Rect outRect = new Rect();
256         mDrawableContainer.getHotspotBounds(outRect);
257         assertEquals(bounds, outRect);
258 
259         dr.reset();
260     }
261 
testSetColorFilter()262     public void testSetColorFilter() {
263         // Workaround for CTS coverage not recognizing calls on subclasses.
264         DrawableContainer dr = mDrawableContainer;
265 
266         assertConstantStateNotSet();
267         assertNull(mDrawableContainer.getCurrent());
268 
269         mMockDrawableContainer.setConstantState(mDrawableContainerState);
270         dr.setColorFilter(null);
271         dr.setColorFilter(new ColorFilter());
272 
273         MockDrawable mockDrawable = new MockDrawable();
274         addAndSelectDrawable(mockDrawable);
275 
276         // call current drawable's setColorFilter if filter is changed.
277         mockDrawable.reset();
278         dr.setColorFilter(null);
279         assertTrue(mockDrawable.hasSetColorFilterCalled());
280 
281         // does not call it if filter is not changed.
282         mockDrawable.reset();
283         dr.setColorFilter(new ColorFilter());
284         assertTrue(mockDrawable.hasSetColorFilterCalled());
285     }
286 
testSetTint()287     public void testSetTint() {
288         assertConstantStateNotSet();
289         assertNull(mDrawableContainer.getCurrent());
290 
291         mMockDrawableContainer.setConstantState(mDrawableContainerState);
292         mDrawableContainer.setTint(Color.BLACK);
293         mDrawableContainer.setTintMode(Mode.SRC_OVER);
294 
295         MockDrawable dr = new MockDrawable();
296         addAndSelectDrawable(dr);
297 
298         assertEquals("Initial tint propagates", Mode.SRC_OVER, dr.getTintMode());
299 
300         dr.reset();
301         mDrawableContainer.setTintList(null);
302         mDrawableContainer.setTintMode(null);
303         assertTrue("setImageTintList() propagates", dr.hasSetTintCalled());
304     }
305 
testOnBoundsChange()306     public void testOnBoundsChange() {
307         assertConstantStateNotSet();
308         assertNull(mDrawableContainer.getCurrent());
309 
310         mMockDrawableContainer.onBoundsChange(new Rect());
311         mMockDrawableContainer.onBoundsChange(null);
312 
313         mMockDrawableContainer.setConstantState(mDrawableContainerState);
314         MockDrawable dr = new MockDrawable();
315         dr.setBounds(new Rect());
316         addAndSelectDrawable(dr);
317 
318         // set current drawable's bounds.
319         dr.reset();
320         assertEquals(new Rect(), dr.getBounds());
321         mMockDrawableContainer.onBoundsChange(new Rect(1, 1, 1, 1));
322         assertTrue(dr.hasOnBoundsChangedCalled());
323         assertEquals(new Rect(1, 1, 1, 1), dr.getBounds());
324 
325         dr.reset();
326         mMockDrawableContainer.onBoundsChange(new Rect(1, 1, 1, 1));
327         assertFalse(dr.hasOnBoundsChangedCalled());
328         assertEquals(new Rect(1, 1, 1, 1), dr.getBounds());
329 
330         try {
331             mMockDrawableContainer.onBoundsChange(null);
332             fail("Should throw NullPointerException if the bounds is null.");
333         } catch (NullPointerException e) {
334         }
335     }
336 
testIsStateful()337     public void testIsStateful() {
338         assertConstantStateNotSet();
339 
340         try {
341             mDrawableContainer.isStateful();
342             fail("Should throw NullPointerException if the constant state is not set.");
343         } catch (NullPointerException e) {
344         }
345 
346         mMockDrawableContainer.setConstantState(mDrawableContainerState);
347         MockDrawable dr0 = new MockDrawable();
348         dr0.setStateful(true);
349         mDrawableContainerState.addChild(dr0);
350         MockDrawable dr1 = new MockDrawable();
351         dr1.setStateful(false);
352         mDrawableContainerState.addChild(dr1);
353 
354         // return result of constant state's isStateful
355         assertEquals(mDrawableContainerState.isStateful(), mDrawableContainer.isStateful());
356         assertEquals(true, mDrawableContainer.isStateful());
357 
358         mDrawableContainer.selectDrawable(1);
359         assertEquals(mDrawableContainerState.isStateful(), mDrawableContainer.isStateful());
360         assertEquals(true, mDrawableContainer.isStateful());
361     }
362 
testOnStateChange()363     public void testOnStateChange() {
364         assertConstantStateNotSet();
365         assertNull(mDrawableContainer.getCurrent());
366 
367         assertFalse(mMockDrawableContainer.onStateChange(new int[] { 0 }));
368         assertFalse(mMockDrawableContainer.onStateChange(null));
369 
370         mMockDrawableContainer.setConstantState(mDrawableContainerState);
371         MockDrawable dr = new MockDrawable();
372         dr.setState(new int[] { 0 });
373         addAndSelectDrawable(dr);
374 
375         // set current drawable's state.
376         dr.reset();
377         assertNotNull(dr.getState());
378         mMockDrawableContainer.onStateChange(null);
379         assertTrue(dr.hasOnStateChangedCalled());
380         assertNull(dr.getState());
381 
382         dr.reset();
383         mMockDrawableContainer.onStateChange(new int[] { 0 });
384         assertTrue(dr.hasOnStateChangedCalled());
385         assertTrue(Arrays.equals(new int[] { 0 }, dr.getState()));
386 
387         dr.reset();
388         assertFalse(mMockDrawableContainer.onStateChange(new int[] { 0 }));
389         assertFalse(dr.hasOnStateChangedCalled());
390         assertTrue(Arrays.equals(new int[] { 0 }, dr.getState()));
391     }
392 
testOnLevelChange()393     public void testOnLevelChange() {
394         assertConstantStateNotSet();
395         assertNull(mDrawableContainer.getCurrent());
396 
397         assertFalse(mMockDrawableContainer.onLevelChange(Integer.MAX_VALUE));
398         assertFalse(mMockDrawableContainer.onLevelChange(Integer.MIN_VALUE));
399 
400         mMockDrawableContainer.setConstantState(mDrawableContainerState);
401         MockDrawable dr = new MockDrawable();
402         dr.setLevel(0);
403         addAndSelectDrawable(dr);
404 
405         // set current drawable's level.
406         dr.reset();
407         assertEquals(0, dr.getLevel());
408         mMockDrawableContainer.onLevelChange(Integer.MAX_VALUE);
409         assertEquals(Integer.MAX_VALUE, dr.getLevel());
410         assertTrue(dr.hasOnLevelChangedCalled());
411 
412         dr.reset();
413         assertEquals(Integer.MAX_VALUE, dr.getLevel());
414         mMockDrawableContainer.onLevelChange(Integer.MIN_VALUE);
415         assertEquals(Integer.MIN_VALUE, dr.getLevel());
416         assertTrue(dr.hasOnLevelChangedCalled());
417 
418         dr.reset();
419         assertEquals(Integer.MIN_VALUE, dr.getLevel());
420         assertFalse(mMockDrawableContainer.onLevelChange(Integer.MIN_VALUE));
421         assertEquals(Integer.MIN_VALUE, dr.getLevel());
422         assertFalse(dr.hasOnLevelChangedCalled());
423     }
424 
testGetIntrinsicWidth()425     public void testGetIntrinsicWidth() {
426         assertConstantStateNotSet();
427 
428         try {
429             mDrawableContainer.getIntrinsicWidth();
430             fail("Should throw NullPointerException if the constant state is not set.");
431         } catch (NullPointerException e) {
432         }
433 
434         mMockDrawableContainer.setConstantState(mDrawableContainerState);
435         MockDrawable dr0 = new MockDrawable();
436         dr0.setIntrinsicWidth(1);
437         mDrawableContainerState.addChild(dr0);
438         MockDrawable dr1 = new MockDrawable();
439         dr1.setIntrinsicWidth(2);
440         mDrawableContainerState.addChild(dr1);
441 
442         // return result of constant state's getConstantWidth
443         mDrawableContainerState.setConstantSize(true);
444         assertEquals(mDrawableContainerState.getConstantWidth(),
445                 mDrawableContainer.getIntrinsicWidth());
446         assertEquals(2, mDrawableContainer.getIntrinsicWidth());
447 
448         // return default value
449         mDrawableContainerState.setConstantSize(false);
450         assertNull(mDrawableContainer.getCurrent());
451         assertEquals(-1, mDrawableContainer.getIntrinsicWidth());
452 
453         // return current drawable's getIntrinsicWidth
454         mDrawableContainer.selectDrawable(0);
455         assertSame(dr0, mDrawableContainer.getCurrent());
456         assertEquals(1, mDrawableContainer.getIntrinsicWidth());
457     }
458 
testGetIntrinsicHeight()459     public void testGetIntrinsicHeight() {
460         assertConstantStateNotSet();
461 
462         try {
463             mDrawableContainer.getIntrinsicHeight();
464             fail("Should throw NullPointerException if the constant state is not set.");
465         } catch (NullPointerException e) {
466         }
467 
468         mMockDrawableContainer.setConstantState(mDrawableContainerState);
469         MockDrawable dr0 = new MockDrawable();
470         dr0.setIntrinsicHeight(1);
471         mDrawableContainerState.addChild(dr0);
472         MockDrawable dr1 = new MockDrawable();
473         dr1.setIntrinsicHeight(2);
474         mDrawableContainerState.addChild(dr1);
475 
476         // return result of constant state's getConstantHeight
477         mDrawableContainerState.setConstantSize(true);
478         assertEquals(mDrawableContainerState.getConstantHeight(),
479                 mDrawableContainer.getIntrinsicHeight());
480         assertEquals(2, mDrawableContainer.getIntrinsicHeight());
481 
482         // return default value
483         mDrawableContainerState.setConstantSize(false);
484         assertNull(mDrawableContainer.getCurrent());
485         assertEquals(-1, mDrawableContainer.getIntrinsicHeight());
486 
487         // return current drawable's getIntrinsicHeight
488         mDrawableContainer.selectDrawable(0);
489         assertSame(dr0, mDrawableContainer.getCurrent());
490         assertEquals(1, mDrawableContainer.getIntrinsicHeight());
491     }
492 
testGetMinimumWidth()493     public void testGetMinimumWidth() {
494         assertConstantStateNotSet();
495 
496         try {
497             mDrawableContainer.getMinimumWidth();
498             fail("Should throw NullPointerException if the constant state is not set.");
499         } catch (NullPointerException e) {
500         }
501 
502         mMockDrawableContainer.setConstantState(mDrawableContainerState);
503         MockDrawable dr0 = new MockDrawable();
504         dr0.setMinimumWidth(1);
505         mDrawableContainerState.addChild(dr0);
506         MockDrawable dr1 = new MockDrawable();
507         dr1.setMinimumWidth(2);
508         mDrawableContainerState.addChild(dr1);
509 
510         // return result of constant state's getConstantMinimumWidth
511         mDrawableContainerState.setConstantSize(true);
512         assertEquals(mDrawableContainerState.getConstantMinimumWidth(),
513                 mDrawableContainer.getMinimumWidth());
514         assertEquals(2, mDrawableContainer.getMinimumWidth());
515 
516         // return default value
517         mDrawableContainerState.setConstantSize(false);
518         assertNull(mDrawableContainer.getCurrent());
519         assertEquals(0, mDrawableContainer.getMinimumWidth());
520 
521         // return current drawable's getMinimumWidth
522         mDrawableContainer.selectDrawable(0);
523         assertSame(dr0, mDrawableContainer.getCurrent());
524         assertEquals(1, mDrawableContainer.getMinimumWidth());
525     }
526 
testGetMinimumHeight()527     public void testGetMinimumHeight() {
528         assertConstantStateNotSet();
529 
530         try {
531             mDrawableContainer.getMinimumHeight();
532             fail("Should throw NullPointerException if the constant state is not set.");
533         } catch (NullPointerException e) {
534         }
535 
536         mMockDrawableContainer.setConstantState(mDrawableContainerState);
537         MockDrawable dr0 = new MockDrawable();
538         dr0.setMinimumHeight(1);
539         mDrawableContainerState.addChild(dr0);
540         MockDrawable dr1 = new MockDrawable();
541         dr1.setMinimumHeight(2);
542         mDrawableContainerState.addChild(dr1);
543 
544         // return result of constant state's getConstantMinimumHeight
545         mDrawableContainerState.setConstantSize(true);
546         assertEquals(mDrawableContainerState.getConstantMinimumHeight(),
547                 mDrawableContainer.getMinimumHeight());
548         assertEquals(2, mDrawableContainer.getMinimumHeight());
549 
550         // return default value
551         mDrawableContainerState.setConstantSize(false);
552         assertNull(mDrawableContainer.getCurrent());
553         assertEquals(0, mDrawableContainer.getMinimumHeight());
554 
555         // return current drawable's getMinimumHeight
556         mDrawableContainer.selectDrawable(0);
557         assertSame(dr0, mDrawableContainer.getCurrent());
558         assertEquals(1, mDrawableContainer.getMinimumHeight());
559     }
560 
testInvalidateDrawable()561     public void testInvalidateDrawable() {
562         // Workaround for CTS coverage not recognizing calls on subclasses.
563         DrawableContainer dr = mDrawableContainer;
564 
565         assertConstantStateNotSet();
566         assertNull(mDrawableContainer.getCurrent());
567 
568         mDrawableContainer.setCallback(null);
569         dr.invalidateDrawable(mDrawableContainer);
570         dr.invalidateDrawable(null);
571 
572         MockCallBack callback = new MockCallBack();
573         mDrawableContainer.setCallback(callback);
574 
575         callback.reset();
576         dr.invalidateDrawable(mDrawableContainer);
577         assertFalse(callback.hasInvalidateDrawableCalled());
578 
579         // the callback method can be called if the drawable passed in and the
580         // current drawble are both null
581         callback.reset();
582         dr.invalidateDrawable(null);
583         assertTrue(callback.hasInvalidateDrawableCalled());
584 
585         mMockDrawableContainer.setConstantState(mDrawableContainerState);
586         MockDrawable mockDrawable = new MockDrawable();
587         addAndSelectDrawable(mockDrawable);
588 
589         callback.reset();
590         dr.invalidateDrawable(mDrawableContainer);
591         assertFalse(callback.hasInvalidateDrawableCalled());
592 
593         callback.reset();
594         dr.invalidateDrawable(null);
595         assertFalse(callback.hasInvalidateDrawableCalled());
596 
597         // Call the callback method if the drawable is selected.
598         callback.reset();
599         dr.invalidateDrawable(mockDrawable);
600         assertTrue(callback.hasInvalidateDrawableCalled());
601     }
602 
testScheduleDrawable()603     public void testScheduleDrawable() {
604         // Workaround for CTS coverage not recognizing calls on subclasses.
605         DrawableContainer dr = mDrawableContainer;
606 
607         assertConstantStateNotSet();
608         assertNull(mDrawableContainer.getCurrent());
609 
610         mDrawableContainer.setCallback(null);
611         dr.scheduleDrawable(mDrawableContainer, null, 0);
612         dr.scheduleDrawable(null, new Runnable() {
613                 public void run() {
614                 }
615             }, 0);
616 
617         MockCallBack callback = new MockCallBack();
618         mDrawableContainer.setCallback(callback);
619 
620         callback.reset();
621         dr.scheduleDrawable(mDrawableContainer, null, 0);
622         assertFalse(callback.hasScheduleDrawableCalled());
623 
624         // the callback method can be called if the drawable passed in and the
625         // current drawble are both null
626         callback.reset();
627         dr.scheduleDrawable(null, new Runnable() {
628                 public void run() {
629                 }
630             }, 0);
631         assertTrue(callback.hasScheduleDrawableCalled());
632 
633         mMockDrawableContainer.setConstantState(mDrawableContainerState);
634         MockDrawable mockDrawable = new MockDrawable();
635         addAndSelectDrawable(mockDrawable);
636 
637         callback.reset();
638         dr.scheduleDrawable(mDrawableContainer, null, 0);
639         assertFalse(callback.hasScheduleDrawableCalled());
640 
641         callback.reset();
642         dr.scheduleDrawable(null, new Runnable() {
643                 public void run() {
644                 }
645             }, 0);
646         assertFalse(callback.hasScheduleDrawableCalled());
647 
648         // Call the callback method if the drawable is selected.
649         callback.reset();
650         dr.scheduleDrawable(mockDrawable, null, 0);
651         assertTrue(callback.hasScheduleDrawableCalled());
652     }
653 
testUnscheduleDrawable()654     public void testUnscheduleDrawable() {
655         // Workaround for CTS coverage not recognizing calls on subclasses.
656         DrawableContainer dr = mDrawableContainer;
657 
658         assertConstantStateNotSet();
659         assertNull(mDrawableContainer.getCurrent());
660 
661         mDrawableContainer.setCallback(null);
662         dr.unscheduleDrawable(mDrawableContainer, null);
663         dr.unscheduleDrawable(null, new Runnable() {
664                 public void run() {
665                 }
666             });
667 
668         MockCallBack callback = new MockCallBack();
669         mDrawableContainer.setCallback(callback);
670 
671         callback.reset();
672         dr.unscheduleDrawable(mDrawableContainer, null);
673         assertFalse(callback.hasUnscheduleDrawableCalled());
674 
675         // the callback method can be called if the drawable passed in and the
676         // current drawble are both null
677         callback.reset();
678         dr.unscheduleDrawable(null, new Runnable() {
679                 public void run() {
680                 }
681             });
682         assertTrue(callback.hasUnscheduleDrawableCalled());
683 
684         mMockDrawableContainer.setConstantState(mDrawableContainerState);
685         MockDrawable mockDrawable = new MockDrawable();
686         addAndSelectDrawable(mockDrawable);
687 
688         callback.reset();
689         dr.unscheduleDrawable(mDrawableContainer, null);
690         assertFalse(callback.hasUnscheduleDrawableCalled());
691 
692         callback.reset();
693         dr.unscheduleDrawable(null, new Runnable() {
694                 public void run() {
695                 }
696             });
697         assertFalse(callback.hasUnscheduleDrawableCalled());
698 
699         // Call the callback method if the drawable is selected.
700         callback.reset();
701         dr.unscheduleDrawable(mockDrawable, null);
702         assertTrue(callback.hasUnscheduleDrawableCalled());
703     }
704 
testSetVisible()705     public void testSetVisible() {
706         assertConstantStateNotSet();
707         assertNull(mDrawableContainer.getCurrent());
708 
709         assertTrue(mDrawableContainer.isVisible());
710         assertFalse(mDrawableContainer.setVisible(true, false));
711         assertTrue(mDrawableContainer.setVisible(false, false));
712         assertFalse(mDrawableContainer.setVisible(false, false));
713         assertTrue(mDrawableContainer.setVisible(true, false));
714 
715         mMockDrawableContainer.setConstantState(mDrawableContainerState);
716         MockDrawable dr = new MockDrawable();
717         addAndSelectDrawable(dr);
718 
719         // set current drawable's visibility
720         assertTrue(mDrawableContainer.isVisible());
721         assertTrue(dr.isVisible());
722         assertTrue(mDrawableContainer.setVisible(false, false));
723         assertFalse(mDrawableContainer.isVisible());
724         assertFalse(dr.isVisible());
725     }
726 
testGetOpacity()727     public void testGetOpacity() {
728         // Workaround for CTS coverage not recognizing calls on subclasses.
729         DrawableContainer dr = mDrawableContainer;
730 
731         assertConstantStateNotSet();
732 
733         // there is no child, so the container is transparent
734         assertEquals(PixelFormat.TRANSPARENT, dr.getOpacity());
735 
736         mMockDrawableContainer.setConstantState(mDrawableContainerState);
737         MockDrawable dr0 = new MockDrawable();
738         dr0.setOpacity(PixelFormat.OPAQUE);
739         mDrawableContainerState.addChild(dr0);
740         // no child selected yet
741         assertEquals(PixelFormat.TRANSPARENT, dr.getOpacity());
742 
743         dr.selectDrawable(0);
744         assertEquals(mDrawableContainerState.getOpacity(), dr.getOpacity());
745         assertEquals(PixelFormat.OPAQUE, mDrawableContainer.getOpacity());
746 
747         MockDrawable dr1 = new MockDrawable();
748         dr1.setOpacity(PixelFormat.TRANSLUCENT);
749         mDrawableContainerState.addChild(dr1);
750 
751         dr.selectDrawable(1);
752         assertEquals(mDrawableContainerState.getOpacity(), dr.getOpacity());
753         assertEquals(PixelFormat.TRANSLUCENT, dr.getOpacity());
754     }
755 
testAccessCurrentDrawable()756     public void testAccessCurrentDrawable() {
757         // Workaround for CTS coverage not recognizing calls on subclasses.
758         DrawableContainer dr = mDrawableContainer;
759 
760         assertConstantStateNotSet();
761 
762         assertNull(mDrawableContainer.getCurrent());
763         try {
764             dr.selectDrawable(0);
765             fail("Should throw NullPointerException if the constant state is not set.");
766         } catch (NullPointerException e) {
767         }
768 
769         mMockDrawableContainer.setConstantState(mDrawableContainerState);
770         MockDrawable dr0 = new MockDrawable();
771         dr0.setVisible(false, false);
772         assertFalse(dr0.isVisible());
773         mDrawableContainerState.addChild(dr0);
774         MockDrawable dr1 = new MockDrawable();
775         dr1.setVisible(false, false);
776         assertFalse(dr1.isVisible());
777         mDrawableContainerState.addChild(dr1);
778 
779         assertTrue(dr.selectDrawable(0));
780         assertSame(dr0, mDrawableContainer.getCurrent());
781         assertTrue(dr0.isVisible());
782 
783         assertFalse(dr.selectDrawable(0));
784 
785         assertTrue(dr.selectDrawable(1));
786         assertSame(dr1, mDrawableContainer.getCurrent());
787         assertTrue(dr1.isVisible());
788         assertFalse(dr0.isVisible());
789 
790         assertFalse(dr.selectDrawable(1));
791 
792         assertTrue(dr.selectDrawable(-1));
793         assertNull(mDrawableContainer.getCurrent());
794         assertFalse(dr0.isVisible());
795         assertFalse(dr1.isVisible());
796 
797         assertTrue(dr.selectDrawable(2));
798         assertNull(mDrawableContainer.getCurrent());
799         assertFalse(dr0.isVisible());
800         assertFalse(dr1.isVisible());
801     }
802 
testAccessConstantState()803     public void testAccessConstantState() {
804         try {
805             mDrawableContainer.getConstantState();
806             fail("Should throw NullPointerException if the constant state is not set.");
807         } catch (NullPointerException e) {
808         }
809 
810         mMockDrawableContainer.setConstantState(mDrawableContainerState);
811         assertSame(mDrawableContainerState, mDrawableContainer.getConstantState());
812 
813         mMockDrawableContainer.setConstantState(null);
814         assertConstantStateNotSet();
815     }
816 
testMutate()817     public void testMutate() {
818         assertConstantStateNotSet();
819         try {
820             mDrawableContainer.mutate();
821             fail("Should throw NullPointerException.");
822         } catch (NullPointerException e) {
823         }
824 
825         mMockDrawableContainer.setConstantState(mDrawableContainerState);
826         MockDrawable dr0 = new MockDrawable();
827         mDrawableContainerState.addChild(dr0);
828         mDrawableContainer.mutate();
829         assertTrue(dr0.hasMutateCalled());
830     }
831 
addAndSelectDrawable(MockDrawable mockDrawable)832     private void addAndSelectDrawable(MockDrawable mockDrawable) {
833         // Workaround for CTS coverage not recognizing calls on subclasses.
834         DrawableContainer dr = mDrawableContainer;
835 
836         int pos = mDrawableContainerState.addChild(mockDrawable);
837         dr.selectDrawable(pos);
838         assertSame(mockDrawable, dr.getCurrent());
839     }
840 
assertConstantStateNotSet()841     private void assertConstantStateNotSet() {
842         try {
843             mDrawableContainer.getConstantState();
844             fail("Should throw NullPointerException.");
845         } catch (NullPointerException e) {
846         }
847     }
848 
849     private class MockDrawableContainer extends DrawableContainer {
850         @Override
onBoundsChange(Rect bounds)851         protected void onBoundsChange(Rect bounds) {
852             super.onBoundsChange(bounds);
853         }
854 
855         @Override
onLevelChange(int level)856         protected boolean onLevelChange(int level) {
857             return super.onLevelChange(level);
858         }
859 
860         @Override
onStateChange(int[] state)861         protected boolean onStateChange(int[] state) {
862             return super.onStateChange(state);
863         }
864 
865         @Override
setConstantState(DrawableContainerState state)866         protected void setConstantState(DrawableContainerState state) {
867             super.setConstantState(state);
868         }
869     }
870 
871     private class MockDrawable extends Drawable {
872         private boolean mHasCalledDraw;
873         private boolean mHasCalledSetAlpha;
874         private boolean mHasCalledSetColorFilter;
875         private boolean mHasCalledSetDither;
876         private boolean mHasCalledSetTint;
877         private boolean mHasCalledOnBoundsChanged;
878         private boolean mHasCalledOnStateChanged;
879         private boolean mHasCalledOnLevelChanged;
880         private boolean mHasCalledMutate;
881 
882         private boolean mIsStateful;
883 
884         private Rect mPadding;
885 
886         private int mIntrinsicHeight;
887         private int mIntrinsicWidth;
888 
889         private int mMinimumHeight;
890         private int mMinimumWidth;
891 
892         private int mOpacity;
893 
894         private Mode mTintMode;
895 
896         @Override
getOpacity()897         public int getOpacity() {
898             return mOpacity;
899         }
900 
901         @Override
isStateful()902         public boolean isStateful() {
903             return mIsStateful;
904         }
905 
setStateful(boolean isStateful)906         public void setStateful(boolean isStateful) {
907             mIsStateful = isStateful;
908         }
909 
getTintMode()910         public Mode getTintMode() {
911             return mTintMode;
912         }
913 
setPadding(Rect rect)914         public void setPadding(Rect rect) {
915             if (mPadding == null) {
916                 mPadding = new Rect();
917             }
918             mPadding.set(rect);
919         }
920 
921         @Override
getPadding(Rect padding)922         public boolean getPadding(Rect padding) {
923             if (padding == null || mPadding == null) {
924                 return false;
925             }
926             padding.set(mPadding);
927             return true;
928         }
929 
930         @Override
getMinimumHeight()931         public int getMinimumHeight() {
932             return mMinimumHeight;
933         }
934 
935         @Override
getMinimumWidth()936         public int getMinimumWidth() {
937             return mMinimumWidth;
938         }
939 
940         @Override
getIntrinsicHeight()941         public int getIntrinsicHeight() {
942             return mIntrinsicHeight;
943         }
944 
945         @Override
getIntrinsicWidth()946         public int getIntrinsicWidth() {
947             return mIntrinsicWidth;
948         }
949 
950         @Override
mutate()951         public Drawable mutate() {
952             mHasCalledMutate = true;
953             return this;
954         }
955 
956         @Override
setTintMode(Mode tintMode)957         public void setTintMode(Mode tintMode) {
958             mTintMode = tintMode;
959             mHasCalledSetTint = true;
960         }
961 
setMinimumHeight(int h)962         public void setMinimumHeight(int h) {
963             mMinimumHeight = h;
964         }
965 
setMinimumWidth(int w)966         public void setMinimumWidth(int w) {
967             mMinimumWidth = w;
968         }
969 
setIntrinsicHeight(int h)970         public void setIntrinsicHeight(int h) {
971             mIntrinsicHeight = h;
972         }
973 
setIntrinsicWidth(int w)974         public void setIntrinsicWidth(int w) {
975             mIntrinsicWidth = w;
976         }
977 
setOpacity(int opacity)978         public void setOpacity(int opacity) {
979             mOpacity = opacity;
980         }
981 
hasDrawCalled()982         public boolean hasDrawCalled() {
983             return mHasCalledDraw;
984         }
985 
hasSetAlphaCalled()986         public boolean hasSetAlphaCalled() {
987             return mHasCalledSetAlpha;
988         }
989 
hasSetColorFilterCalled()990         public boolean hasSetColorFilterCalled() {
991             return mHasCalledSetColorFilter;
992         }
993 
hasSetDitherCalled()994         public boolean hasSetDitherCalled() {
995             return mHasCalledSetDither;
996         }
997 
hasSetTintCalled()998         public boolean hasSetTintCalled() {
999             return mHasCalledSetTint;
1000         }
1001 
hasOnBoundsChangedCalled()1002         public boolean hasOnBoundsChangedCalled() {
1003             return mHasCalledOnBoundsChanged;
1004         }
1005 
hasOnStateChangedCalled()1006         public boolean hasOnStateChangedCalled() {
1007             return mHasCalledOnStateChanged;
1008         }
1009 
hasOnLevelChangedCalled()1010         public boolean hasOnLevelChangedCalled() {
1011             return mHasCalledOnLevelChanged;
1012         }
1013 
hasMutateCalled()1014         public boolean hasMutateCalled() {
1015             return mHasCalledMutate;
1016         }
1017 
reset()1018         public void reset() {
1019             mHasCalledOnLevelChanged = false;
1020             mHasCalledOnStateChanged = false;
1021             mHasCalledOnBoundsChanged = false;
1022             mHasCalledSetDither = false;
1023             mHasCalledSetColorFilter = false;
1024             mHasCalledSetAlpha = false;
1025             mHasCalledDraw = false;
1026             mHasCalledMutate = false;
1027         }
1028 
1029         @Override
draw(Canvas canvas)1030         public void draw(Canvas canvas) {
1031             mHasCalledDraw = true;
1032         }
1033 
1034         @Override
setAlpha(int alpha)1035         public void setAlpha(int alpha) {
1036             mHasCalledSetAlpha = true;
1037         }
1038 
1039         @Override
setColorFilter(ColorFilter cf)1040         public void setColorFilter(ColorFilter cf) {
1041             mHasCalledSetColorFilter = true;
1042         }
1043 
1044         @Override
onBoundsChange(Rect bounds)1045         protected void onBoundsChange(Rect bounds) {
1046             super.onBoundsChange(bounds);
1047             mHasCalledOnBoundsChanged = true;
1048         }
1049 
1050         @Override
onLevelChange(int level)1051         protected boolean onLevelChange(int level) {
1052             boolean result = super.onLevelChange(level);
1053             mHasCalledOnLevelChanged = true;
1054             return result;
1055         }
1056 
1057         @Override
onStateChange(int[] state)1058         protected boolean onStateChange(int[] state) {
1059             boolean result = super.onStateChange(state);
1060             mHasCalledOnStateChanged = true;
1061             return result;
1062 
1063         }
1064 
1065         @Override
setDither(boolean dither)1066         public void setDither(boolean dither) {
1067             super.setDither(dither);
1068             mHasCalledSetDither = true;
1069         }
1070     }
1071 
1072     private class MockCallBack implements Drawable.Callback {
1073         private boolean mCalledInvalidateDrawable;
1074 
1075         private boolean mCalledScheduleDrawable;
1076 
1077         private boolean mCalledUnscheduleDrawable;
1078 
hasInvalidateDrawableCalled()1079         public boolean hasInvalidateDrawableCalled() {
1080             return mCalledInvalidateDrawable;
1081         }
1082 
hasScheduleDrawableCalled()1083         public boolean hasScheduleDrawableCalled() {
1084             return mCalledScheduleDrawable;
1085         }
1086 
hasUnscheduleDrawableCalled()1087         public boolean hasUnscheduleDrawableCalled() {
1088             return mCalledUnscheduleDrawable;
1089         }
1090 
reset()1091         public void reset() {
1092             mCalledUnscheduleDrawable = false;
1093             mCalledScheduleDrawable = false;
1094             mCalledInvalidateDrawable = false;
1095         }
1096 
invalidateDrawable(Drawable who)1097         public void invalidateDrawable(Drawable who) {
1098             mCalledInvalidateDrawable = true;
1099         }
1100 
scheduleDrawable(Drawable who, Runnable what, long when)1101         public void scheduleDrawable(Drawable who, Runnable what, long when) {
1102             mCalledScheduleDrawable = true;
1103         }
1104 
unscheduleDrawable(Drawable who, Runnable what)1105         public void unscheduleDrawable(Drawable who, Runnable what) {
1106             mCalledUnscheduleDrawable = true;
1107         }
1108 
getResolvedLayoutDirection(Drawable who)1109         public int getResolvedLayoutDirection(Drawable who) {
1110             return 0;
1111         }
1112     }
1113 }
1114