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