Home | History | Annotate | Download | only in cts
      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 static org.junit.Assert.assertEquals;
     20 import static org.junit.Assert.assertFalse;
     21 import static org.junit.Assert.assertNotNull;
     22 import static org.junit.Assert.assertNotSame;
     23 import static org.junit.Assert.assertNull;
     24 import static org.junit.Assert.assertSame;
     25 import static org.junit.Assert.assertTrue;
     26 import static org.junit.Assert.fail;
     27 import static org.mockito.ArgumentMatchers.anyInt;
     28 import static org.mockito.Matchers.any;
     29 import static org.mockito.Matchers.anyBoolean;
     30 import static org.mockito.Matchers.anyLong;
     31 import static org.mockito.Mockito.doAnswer;
     32 import static org.mockito.Mockito.doNothing;
     33 import static org.mockito.Mockito.doReturn;
     34 import static org.mockito.Mockito.mock;
     35 import static org.mockito.Mockito.never;
     36 import static org.mockito.Mockito.reset;
     37 import static org.mockito.Mockito.spy;
     38 import static org.mockito.Mockito.times;
     39 import static org.mockito.Mockito.verify;
     40 
     41 import android.content.Context;
     42 import android.content.res.ColorStateList;
     43 import android.content.res.Resources;
     44 import android.content.res.Resources.Theme;
     45 import android.content.res.XmlResourceParser;
     46 import android.graphics.BitmapFactory;
     47 import android.graphics.Canvas;
     48 import android.graphics.Color;
     49 import android.graphics.ColorFilter;
     50 import android.graphics.PixelFormat;
     51 import android.graphics.PorterDuff;
     52 import android.graphics.Rect;
     53 import android.graphics.cts.R;
     54 import android.graphics.drawable.BitmapDrawable;
     55 import android.graphics.drawable.ColorDrawable;
     56 import android.graphics.drawable.Drawable;
     57 import android.graphics.drawable.Drawable.ConstantState;
     58 import android.graphics.drawable.GradientDrawable;
     59 import android.graphics.drawable.LayerDrawable;
     60 import android.graphics.drawable.RippleDrawable;
     61 import android.graphics.drawable.RotateDrawable;
     62 import android.graphics.drawable.ShapeDrawable;
     63 import android.graphics.drawable.StateListDrawable;
     64 import android.support.test.InstrumentationRegistry;
     65 import android.support.test.filters.SmallTest;
     66 import android.support.test.runner.AndroidJUnit4;
     67 import android.util.AttributeSet;
     68 import android.util.StateSet;
     69 import android.util.Xml;
     70 import android.view.Gravity;
     71 import android.view.View;
     72 
     73 import org.junit.Before;
     74 import org.junit.Test;
     75 import org.junit.runner.RunWith;
     76 import org.xmlpull.v1.XmlPullParserException;
     77 
     78 import java.io.IOException;
     79 
     80 @SmallTest
     81 @RunWith(AndroidJUnit4.class)
     82 public class LayerDrawableTest {
     83     private Context mContext;
     84     private ColorDrawable mColorDrawable;
     85     private BitmapDrawable mBitmapDrawable;
     86 
     87     @Before
     88     public void setup() {
     89         mContext = InstrumentationRegistry.getTargetContext();
     90         Resources resources = mContext.getResources();
     91         mColorDrawable = new ColorDrawable(Color.BLUE);
     92         mBitmapDrawable = new BitmapDrawable(resources,
     93                 BitmapFactory.decodeResource(resources, R.drawable.icon_blue));
     94     }
     95 
     96     @Test
     97     public void testConstructor() {
     98         Drawable[] array = new Drawable[]{mBitmapDrawable, mColorDrawable};
     99         LayerDrawable layerDrawable = new LayerDrawable(array);
    100         assertEquals(array.length, layerDrawable.getNumberOfLayers());
    101         assertSame(mBitmapDrawable, layerDrawable.getDrawable(0));
    102         assertSame(mColorDrawable, layerDrawable.getDrawable(1));
    103 
    104         array = new Drawable[0];
    105         layerDrawable = new LayerDrawable(array);
    106         assertEquals(0, layerDrawable.getNumberOfLayers());
    107     }
    108 
    109     @Test(expected=IllegalArgumentException.class)
    110     public void testConstructorNull() {
    111         new LayerDrawable(null);
    112     }
    113 
    114     @Test
    115     public void testInflate() throws XmlPullParserException, IOException {
    116         Drawable[] array = new Drawable[0];
    117         LayerDrawable layerDrawable = new LayerDrawable(array);
    118 
    119         XmlResourceParser parser = mContext.getResources().getXml(R.xml.layerdrawable);
    120         AttributeSet attrs = DrawableTestUtils.getAttributeSet(parser, "layer-list_full");
    121 
    122         layerDrawable.inflate(mContext.getResources(), parser, attrs);
    123 
    124         assertEquals(4, layerDrawable.getNumberOfLayers());
    125         assertEquals(ColorDrawable.class, layerDrawable.getDrawable(0).getClass());
    126         assertEquals(0x88, layerDrawable.getDrawable(0).getAlpha());
    127         assertEquals(View.NO_ID, layerDrawable.getId(0));
    128         assertEquals(BitmapDrawable.class, layerDrawable.getDrawable(1).getClass());
    129         assertEquals(View.NO_ID, layerDrawable.getId(1));
    130         assertEquals(RotateDrawable.class, layerDrawable.getDrawable(2).getClass());
    131         assertEquals(View.NO_ID, layerDrawable.getId(2));
    132         assertEquals(GradientDrawable.class, layerDrawable.getDrawable(3).getClass());
    133         assertEquals(R.id.background, layerDrawable.getId(3));
    134 
    135         layerDrawable = new LayerDrawable(array);
    136         parser = mContext.getResources().getXml(R.xml.layerdrawable);
    137         attrs = DrawableTestUtils.getAttributeSet(parser, "layer-list_empty");
    138         layerDrawable.inflate(mContext.getResources(), parser, attrs);
    139         assertEquals(0, layerDrawable.getNumberOfLayers());
    140 
    141         parser = mContext.getResources().getXml(R.xml.layerdrawable);
    142         attrs = DrawableTestUtils.getAttributeSet(parser, "layer-list_exception");
    143         try {
    144             layerDrawable.inflate(mContext.getResources(), parser, attrs);
    145             fail("Should throw XmlPullParserException if neither 'drawable' attribute" +
    146                     " nor child tag defining a drawable in <item> tag.");
    147         } catch (XmlPullParserException e) {
    148         }
    149 
    150         try {
    151             layerDrawable.inflate(null, parser, attrs);
    152             fail("Should throw NullPointerException if resource is null");
    153         } catch (NullPointerException e) {
    154         }
    155 
    156         try {
    157             layerDrawable.inflate(mContext.getResources(), null, attrs);
    158             fail("Should throw NullPointerException if parser is null");
    159         } catch (NullPointerException e) {
    160         }
    161 
    162         try {
    163             layerDrawable.inflate(mContext.getResources(), parser, null);
    164             fail("Should throw NullPointerException if attribute set is null");
    165         } catch (NullPointerException e) {
    166         }
    167     }
    168 
    169     @Test
    170     public void testFindDrawableByLayerId() {
    171         Drawable[] array = new Drawable[] { mBitmapDrawable, mColorDrawable };
    172         LayerDrawable layerDrawable = new LayerDrawable(array);
    173 
    174         layerDrawable.setId(0, 10);
    175         layerDrawable.setId(1, 20);
    176         assertSame(mBitmapDrawable, layerDrawable.findDrawableByLayerId(10));
    177         assertSame(mColorDrawable, layerDrawable.findDrawableByLayerId(20));
    178         assertNull(layerDrawable.findDrawableByLayerId(30));
    179 
    180         layerDrawable.setId(0, Integer.MIN_VALUE);
    181         layerDrawable.setId(1, Integer.MAX_VALUE);
    182         assertSame(mBitmapDrawable, layerDrawable.findDrawableByLayerId(Integer.MIN_VALUE));
    183         assertSame(mColorDrawable, layerDrawable.findDrawableByLayerId(Integer.MAX_VALUE));
    184 
    185         layerDrawable.setId(0, 10);
    186         layerDrawable.setId(1, 10);
    187         assertSame(mColorDrawable, layerDrawable.findDrawableByLayerId(10));
    188         assertNull(layerDrawable.findDrawableByLayerId(30));
    189     }
    190 
    191     @Test
    192     public void testAccessId() {
    193         Drawable[] array = new Drawable[] { mBitmapDrawable, mColorDrawable };
    194         LayerDrawable layerDrawable = new LayerDrawable(array);
    195 
    196         layerDrawable.setId(0, 10);
    197         layerDrawable.setId(1, 20);
    198         assertEquals(10, layerDrawable.getId(0));
    199         assertEquals(20, layerDrawable.getId(1));
    200 
    201         layerDrawable.setId(0, Integer.MIN_VALUE);
    202         layerDrawable.setId(1, Integer.MAX_VALUE);
    203         assertEquals(Integer.MIN_VALUE, layerDrawable.getId(0));
    204         assertEquals(Integer.MAX_VALUE, layerDrawable.getId(1));
    205     }
    206 
    207     @Test(expected=IndexOutOfBoundsException.class)
    208     public void testSetIdIndexTooLow() {
    209         Drawable[] array = new Drawable[] { mBitmapDrawable, mColorDrawable };
    210         LayerDrawable layerDrawable = new LayerDrawable(array);
    211         layerDrawable.setId(-1, 20);
    212     }
    213 
    214     @Test(expected=IndexOutOfBoundsException.class)
    215     public void testSetIdIndexTooHigh() {
    216         Drawable[] array = new Drawable[] { mBitmapDrawable, mColorDrawable };
    217         LayerDrawable layerDrawable = new LayerDrawable(array);
    218         layerDrawable.setId(layerDrawable.getNumberOfLayers(), 20);
    219     }
    220 
    221     @Test(expected=IndexOutOfBoundsException.class)
    222     public void testGetIdIndexTooLow() {
    223         Drawable[] array = new Drawable[] { mBitmapDrawable, mColorDrawable };
    224         LayerDrawable layerDrawable = new LayerDrawable(array);
    225         layerDrawable.getId(-1);
    226     }
    227 
    228     @Test(expected=IndexOutOfBoundsException.class)
    229     public void testGetIdIndexTooHigh() {
    230         Drawable[] array = new Drawable[] { mBitmapDrawable, mColorDrawable };
    231         LayerDrawable layerDrawable = new LayerDrawable(array);
    232         layerDrawable.getId(layerDrawable.getNumberOfLayers());
    233     }
    234 
    235     @Test
    236     public void testGetNumberOfLayers() {
    237         Drawable[] array = new Drawable[] { mBitmapDrawable, mColorDrawable };
    238         LayerDrawable layerDrawable = new LayerDrawable(array);
    239         assertEquals(2, layerDrawable.getNumberOfLayers());
    240 
    241         array = new Drawable[5];
    242         for (int i = 0; i < 5; i++) {
    243             array[i] = new BitmapDrawable();
    244         }
    245         layerDrawable = new LayerDrawable(array);
    246         assertEquals(5, layerDrawable.getNumberOfLayers());
    247 
    248         array = new Drawable[0];
    249         layerDrawable = new LayerDrawable(array);
    250         assertEquals(0, layerDrawable.getNumberOfLayers());
    251     }
    252 
    253     @Test
    254     public void testAccessDrawable() {
    255         Drawable[] array = new Drawable[] { mBitmapDrawable, mColorDrawable };
    256         LayerDrawable layerDrawable = new LayerDrawable(array);
    257         assertSame(mBitmapDrawable, layerDrawable.getDrawable(0));
    258         assertSame(mColorDrawable, layerDrawable.getDrawable(1));
    259 
    260         layerDrawable.setId(0, 10);
    261         layerDrawable.setId(1, 20);
    262         Drawable d1 = new ColorDrawable(Color.GREEN);
    263         Drawable d2 = new BitmapDrawable();
    264         layerDrawable.setDrawableByLayerId(10, d1);
    265         layerDrawable.setDrawableByLayerId(20, d2);
    266         assertEquals(d1, layerDrawable.getDrawable(0));
    267         assertEquals(d2, layerDrawable.getDrawable(1));
    268 
    269         assertFalse(layerDrawable.setDrawableByLayerId(30, d1));
    270 
    271         try {
    272             layerDrawable.getDrawable(layerDrawable.getNumberOfLayers());
    273             fail("Should throw IndexOutOfBoundsException");
    274         } catch (IndexOutOfBoundsException e) {
    275         }
    276 
    277         try {
    278             layerDrawable.getDrawable(-1);
    279             fail("Should throw IndexOutOfBoundsException");
    280         } catch (IndexOutOfBoundsException e) {
    281         }
    282     }
    283 
    284     @Test
    285     public void testSetDrawableByLayerId() {
    286         Drawable layer1A  = new ColorDrawable(Color.RED);
    287         Drawable layer2A  = new ColorDrawable(Color.BLUE);
    288         LayerDrawable layerDrawable = new LayerDrawable(new Drawable[] { layer1A, layer2A });
    289         layerDrawable.setId(0, 10);
    290         layerDrawable.setId(1, 20);
    291 
    292         Drawable layer1B = new ColorDrawable(Color.GREEN);
    293         layer1B.setLevel(10000);
    294         Drawable layer2B = new ColorDrawable(Color.YELLOW);
    295         layer2B.setLevel(5000);
    296         layerDrawable.setDrawableByLayerId(10, layer1B);
    297         layerDrawable.setDrawableByLayerId(20, layer2B);
    298 
    299         assertEquals("Level is unchanged after setDrawableByLayerId()",
    300                 10000, layerDrawable.findDrawableByLayerId(10).getLevel());
    301         assertEquals("Level is unchanged after setDrawableByLayerId()",
    302                 5000, layerDrawable.findDrawableByLayerId(20).getLevel());
    303     }
    304 
    305     @Test
    306     public void testSetLayerInset() {
    307         Drawable firstLayer = spy(new ColorDrawable(Color.YELLOW));
    308         doReturn(10).when(firstLayer).getIntrinsicWidth();
    309         doReturn(10).when(firstLayer).getIntrinsicHeight();
    310         Drawable secondLayer = spy(new ColorDrawable(Color.YELLOW));
    311         doReturn(-1).when(secondLayer).getIntrinsicWidth();
    312         doReturn(-1).when(secondLayer).getIntrinsicHeight();
    313 
    314         Drawable[] array = new Drawable[] { firstLayer, secondLayer };
    315         LayerDrawable layerDrawable = new LayerDrawable(array);
    316 
    317         // set inset for layer 0
    318         int left = 10;
    319         int top = 20;
    320         int right = 30;
    321         int bottom = 40;
    322         layerDrawable.setLayerInset(0, left, top, right, bottom);
    323         assertEquals(layerDrawable.getDrawable(0).getIntrinsicWidth() + left + right,
    324                 layerDrawable.getIntrinsicWidth());
    325         assertEquals(layerDrawable.getDrawable(0).getIntrinsicHeight() + top + bottom,
    326                 layerDrawable.getIntrinsicHeight());
    327 
    328         // The drawable at index 0 has no intrinsic width or height, so it
    329         // won't be counted for the overall intrinsic width or height.
    330         layerDrawable.setLayerInset(1, 10, 10, 10, 10);
    331         assertEquals(layerDrawable.getDrawable(0).getIntrinsicWidth() + left + right,
    332                 layerDrawable.getIntrinsicWidth());
    333         assertEquals(layerDrawable.getDrawable(0).getIntrinsicHeight() + top + bottom,
    334                 layerDrawable.getIntrinsicHeight());
    335 
    336         try {
    337             layerDrawable.setLayerInset(-1, left, top, right, bottom);
    338             fail("Should throw IndexOutOfBoundsException");
    339         } catch (IndexOutOfBoundsException e) {
    340         }
    341     }
    342 
    343     @Test
    344     public void testInvalidateDrawable() {
    345         Drawable[] array = new Drawable[0];
    346         LayerDrawable layerDrawable = new LayerDrawable(array);
    347 
    348         Drawable.Callback cb = mock(Drawable.Callback.class);
    349         layerDrawable.setCallback(cb);
    350         layerDrawable.invalidateDrawable(null);
    351         verify(cb, times(1)).invalidateDrawable(any());
    352 
    353         reset(cb);
    354         layerDrawable.invalidateDrawable(new BitmapDrawable());
    355         verify(cb, times(1)).invalidateDrawable(any());
    356 
    357         reset(cb);
    358         layerDrawable.setCallback(null);
    359         layerDrawable.invalidateDrawable(null);
    360         verify(cb, never()).invalidateDrawable(any());
    361     }
    362 
    363     @Test
    364     public void testScheduleDrawable() {
    365         Drawable[] array = new Drawable[0];
    366         LayerDrawable layerDrawable = new LayerDrawable(array);
    367 
    368         Drawable.Callback cb = mock(Drawable.Callback.class);
    369         layerDrawable.setCallback(cb);
    370         layerDrawable.scheduleDrawable(null, null, 0);
    371         verify(cb, times(1)).scheduleDrawable(any(), any(), anyLong());
    372 
    373         reset(cb);
    374         layerDrawable.scheduleDrawable(mBitmapDrawable, () -> {}, 1000L);
    375         verify(cb, times(1)).scheduleDrawable(any(), any(), anyLong());
    376 
    377         reset(cb);
    378         layerDrawable.setCallback(null);
    379         layerDrawable.scheduleDrawable(null, null, 0);
    380         verify(cb, never()).scheduleDrawable(any(), any(), anyLong());
    381     }
    382 
    383     @Test
    384     public void testUnscheduleDrawable() {
    385         Drawable[] array = new Drawable[0];
    386         LayerDrawable layerDrawable = new LayerDrawable(array);
    387 
    388         Drawable.Callback cb = mock(Drawable.Callback.class);
    389         layerDrawable.setCallback(cb);
    390         layerDrawable.unscheduleDrawable(null, null);
    391         verify(cb, times(1)).unscheduleDrawable(any(), any());
    392 
    393         reset(cb);
    394         layerDrawable.unscheduleDrawable(mBitmapDrawable, () -> {});
    395         verify(cb, times(1)).unscheduleDrawable(any(), any());
    396 
    397         reset(cb);
    398         layerDrawable.setCallback(null);
    399         layerDrawable.unscheduleDrawable(null, null);
    400         verify(cb, never()).unscheduleDrawable(any(), any());
    401     }
    402 
    403     @Test
    404     public void testDraw() {
    405         Drawable mockDrawable1 = spy(new ColorDrawable(Color.BLUE));
    406         Drawable mockDrawable2 = spy(new ColorDrawable(Color.RED));
    407         Drawable[] array = new Drawable[] { mockDrawable1, mockDrawable2 };
    408         LayerDrawable layerDrawable = new LayerDrawable(array);
    409 
    410         // this method will call each child's draw().
    411         layerDrawable.draw(new Canvas());
    412         verify(mockDrawable1, times(1)).draw(any());
    413         verify(mockDrawable2, times(1)).draw(any());
    414 
    415         reset(mockDrawable1);
    416         reset(mockDrawable2);
    417         doNothing().when(mockDrawable1).draw(any());
    418         doNothing().when(mockDrawable2).draw(any());
    419         layerDrawable.draw(null);
    420         verify(mockDrawable1, times(1)).draw(any());
    421         verify(mockDrawable2, times(1)).draw(any());
    422     }
    423 
    424     @Test
    425     public void testGetChangingConfigurations() {
    426         final int superConfig = 1;
    427         final int gradientDrawableConfig = 2;
    428         final int colorDrawableConfig = 4;
    429         final int childConfig = gradientDrawableConfig | colorDrawableConfig;
    430 
    431         mBitmapDrawable.setChangingConfigurations(gradientDrawableConfig);
    432         mColorDrawable.setChangingConfigurations(colorDrawableConfig);
    433         Drawable[] array = new Drawable[] { mBitmapDrawable, mColorDrawable };
    434         LayerDrawable layerDrawable = new LayerDrawable(array);
    435 
    436         assertEquals(childConfig, layerDrawable.getChangingConfigurations());
    437 
    438         layerDrawable.setChangingConfigurations(superConfig);
    439         assertEquals(superConfig | childConfig, layerDrawable.getChangingConfigurations());
    440     }
    441 
    442     @Test
    443     public void testAccessPadding() {
    444         Drawable[] array = new Drawable[] { new ShapeDrawable(), new ShapeDrawable() };
    445         LayerDrawable layerDrawable = new LayerDrawable(array);
    446 
    447         Rect rc = new Rect();
    448         layerDrawable.getPadding(rc);
    449         assertEquals(0, rc.left);
    450         assertEquals(0, rc.top);
    451         assertEquals(0, rc.right);
    452         assertEquals(0, rc.bottom);
    453 
    454         Rect padding0 = new Rect(10, 20, 30, 40);
    455         ((ShapeDrawable) layerDrawable.getDrawable(0)).setPadding(padding0);
    456         layerDrawable.getPadding(rc);
    457         assertEquals(padding0.left, rc.left);
    458         assertEquals(padding0.top, rc.top);
    459         assertEquals(padding0.right, rc.right);
    460         assertEquals(padding0.bottom, rc.bottom);
    461 
    462         Rect padding1 = new Rect(20, 30, 40, 50);
    463         ((ShapeDrawable) layerDrawable.getDrawable(1)).setPadding(padding1);
    464         layerDrawable.getPadding(rc);
    465         assertEquals(padding0.left + padding1.left, rc.left);
    466         assertEquals(padding0.top + padding1.top, rc.top);
    467         assertEquals(padding0.right + padding1.right, rc.right);
    468         assertEquals(padding0.bottom + padding1.bottom, rc.bottom);
    469     }
    470 
    471     @Test
    472     public void testAccessPaddingMode() {
    473         Rect padding = new Rect();
    474         Drawable dr0 = new IntrinsicSizeDrawable(20, 30, new Rect(1, 2, 3, 4));
    475         Drawable dr1 = new IntrinsicSizeDrawable(30, 40, new Rect(9, 8, 7, 6));
    476         LayerDrawable layerDrawable = new LayerDrawable(new Drawable[] { dr0, dr1 });
    477 
    478         assertEquals("Default padding mode is NEST",
    479                 LayerDrawable.PADDING_MODE_NEST, layerDrawable.getPaddingMode());
    480         assertEquals(34, layerDrawable.getIntrinsicWidth());
    481         assertEquals(46, layerDrawable.getIntrinsicHeight());
    482         assertTrue(layerDrawable.getPadding(padding));
    483         assertEquals(new Rect(10, 10, 10, 10), padding);
    484 
    485         layerDrawable.setPaddingMode(LayerDrawable.PADDING_MODE_STACK);
    486         assertEquals(LayerDrawable.PADDING_MODE_STACK, layerDrawable.getPaddingMode());
    487         assertEquals(30, layerDrawable.getIntrinsicWidth());
    488         assertEquals(40, layerDrawable.getIntrinsicHeight());
    489         assertTrue(layerDrawable.getPadding(padding));
    490         assertEquals(new Rect(9, 8, 7, 6), padding);
    491     }
    492 
    493     @Test
    494     public void testSetVisible() {
    495         Drawable[] array = new Drawable[] { mBitmapDrawable, mColorDrawable };
    496         LayerDrawable layerDrawable = new LayerDrawable(array);
    497 
    498         assertTrue(layerDrawable.setVisible(false, true));
    499         assertFalse(layerDrawable.isVisible());
    500         assertFalse(layerDrawable.getDrawable(0).isVisible());
    501         assertFalse(layerDrawable.getDrawable(1).isVisible());
    502 
    503         assertFalse(layerDrawable.setVisible(false, false));
    504 
    505         assertTrue(layerDrawable.setVisible(true, false));
    506         assertTrue(layerDrawable.isVisible());
    507         assertTrue(layerDrawable.getDrawable(0).isVisible());
    508         assertTrue(layerDrawable.getDrawable(1).isVisible());
    509     }
    510 
    511     @Test
    512     public void testSetDither() {
    513         Drawable mockDrawable1 = spy(new ColorDrawable(Color.BLUE));
    514         Drawable mockDrawable2 = spy(new ColorDrawable(Color.BLACK));
    515         Drawable[] array = new Drawable[] { mockDrawable1, mockDrawable2 };
    516         LayerDrawable layerDrawable = new LayerDrawable(array);
    517 
    518         layerDrawable.setDither(true);
    519         verify(mockDrawable1, times(1)).setDither(anyBoolean());
    520         verify(mockDrawable2, times(1)).setDither(anyBoolean());
    521 
    522         reset(mockDrawable1);
    523         reset(mockDrawable2);
    524         layerDrawable.setDither(false);
    525         verify(mockDrawable1, times(1)).setDither(anyBoolean());
    526         verify(mockDrawable2, times(1)).setDither(anyBoolean());
    527     }
    528 
    529     @Test
    530     public void testSetHotspotBounds() {
    531         Rect bounds = new Rect(10, 15, 100, 150);
    532         Drawable mockDrawable1 = new ColorDrawable(Color.BLUE);
    533         Drawable mockDrawable2 = new ColorDrawable(Color.GREEN);
    534         Drawable[] array = new Drawable[] { mockDrawable1, mockDrawable2 };
    535         LayerDrawable layerDrawable = new LayerDrawable(array);
    536 
    537         layerDrawable.setHotspotBounds(bounds.left, bounds.top, bounds.right, bounds.bottom);
    538         Rect outRect = new Rect();
    539         layerDrawable.getHotspotBounds(outRect);
    540         assertTrue(bounds.equals(outRect));
    541     }
    542 
    543     @Test
    544     public void testGetHotspotBounds() {
    545         Rect bounds = new Rect(10, 15, 100, 150);
    546         Drawable mockDrawable1 = new ColorDrawable(Color.BLUE);
    547         Drawable mockDrawable2 = new ColorDrawable(Color.GREEN);
    548         Drawable[] array = new Drawable[] { mockDrawable1, mockDrawable2 };
    549         LayerDrawable layerDrawable = new LayerDrawable(array);
    550 
    551         layerDrawable.setHotspotBounds(bounds.left, bounds.top, bounds.right, bounds.bottom);
    552         Rect outRect = new Rect();
    553         layerDrawable.getHotspotBounds(outRect);
    554         assertTrue(bounds.equals(outRect));
    555     }
    556 
    557     @Test
    558     public void testSetAlpha() {
    559         Drawable mockDrawable1 = spy(new ColorDrawable(Color.BLUE));
    560         Drawable mockDrawable2 = spy(new ColorDrawable(Color.BLACK));
    561         Drawable[] array = new Drawable[] { mockDrawable1, mockDrawable2 };
    562         LayerDrawable layerDrawable = new LayerDrawable(array);
    563 
    564         layerDrawable.setAlpha(0);
    565         verify(mockDrawable1, times(1)).setAlpha(anyInt());
    566         verify(mockDrawable2, times(1)).setAlpha(anyInt());
    567 
    568         reset(mockDrawable1);
    569         reset(mockDrawable2);
    570         layerDrawable.setAlpha(Integer.MAX_VALUE);
    571         verify(mockDrawable1, times(1)).setAlpha(anyInt());
    572         verify(mockDrawable2, times(1)).setAlpha(anyInt());
    573     }
    574 
    575     @Test
    576     public void testSetColorFilter() {
    577         Drawable mockDrawable1 = spy(new ColorDrawable(Color.BLUE));
    578         Drawable mockDrawable2 = spy(new ColorDrawable(Color.BLACK));
    579         Drawable[] array = new Drawable[] { mockDrawable1, mockDrawable2 };
    580         LayerDrawable layerDrawable = new LayerDrawable(array);
    581 
    582         layerDrawable.setColorFilter(new ColorFilter());
    583         verify(mockDrawable1, times(1)).setColorFilter(any());
    584         verify(mockDrawable2, times(1)).setColorFilter(any());
    585 
    586         reset(mockDrawable1);
    587         reset(mockDrawable2);
    588         layerDrawable.setColorFilter(null);
    589         verify(mockDrawable1, times(1)).setColorFilter(any());
    590         verify(mockDrawable2, times(1)).setColorFilter(any());
    591     }
    592 
    593     @Test
    594     public void testAccessOpacity() {
    595         Drawable[] array = new Drawable[0];
    596         LayerDrawable layerDrawable = new LayerDrawable(array);
    597         assertEquals(PixelFormat.TRANSPARENT, layerDrawable.getOpacity());
    598 
    599         Drawable mockDrawable1 = spy(new ColorDrawable(Color.BLUE));
    600         Drawable mockDrawable2 = spy(new ColorDrawable(Color.GREEN));
    601         array = new Drawable[] { mockDrawable1, mockDrawable2 };
    602         layerDrawable = new LayerDrawable(array);
    603         assertEquals(PixelFormat.OPAQUE, layerDrawable.getOpacity());
    604 
    605         layerDrawable = new LayerDrawable(array);
    606         doReturn(PixelFormat.OPAQUE).when(mockDrawable1).getOpacity();
    607         doReturn(PixelFormat.TRANSPARENT).when(mockDrawable2).getOpacity();
    608         assertEquals(PixelFormat.TRANSPARENT, layerDrawable.getOpacity());
    609 
    610         layerDrawable = new LayerDrawable(array);
    611         doReturn(PixelFormat.TRANSLUCENT).when(mockDrawable1).getOpacity();
    612         doReturn(PixelFormat.TRANSPARENT).when(mockDrawable2).getOpacity();
    613         assertEquals(PixelFormat.TRANSLUCENT, layerDrawable.getOpacity());
    614 
    615         layerDrawable = new LayerDrawable(array);
    616         doReturn(PixelFormat.TRANSLUCENT).when(mockDrawable1).getOpacity();
    617         doReturn(PixelFormat.UNKNOWN).when(mockDrawable2).getOpacity();
    618         assertEquals(PixelFormat.UNKNOWN, layerDrawable.getOpacity());
    619 
    620         layerDrawable = new LayerDrawable(array);
    621         layerDrawable.setOpacity(PixelFormat.OPAQUE);
    622         doReturn(PixelFormat.TRANSLUCENT).when(mockDrawable1).getOpacity();
    623         doReturn(PixelFormat.UNKNOWN).when(mockDrawable2).getOpacity();
    624         assertEquals(PixelFormat.OPAQUE, layerDrawable.getOpacity());
    625 
    626     }
    627 
    628     @Test
    629     public void testIsStateful() {
    630         Drawable[] array = new Drawable[0];
    631         LayerDrawable layerDrawable = new LayerDrawable(array);
    632         assertFalse(layerDrawable.isStateful());
    633 
    634         array = new Drawable[] { new GradientDrawable(), new MockDrawable(false) };
    635         layerDrawable = new LayerDrawable(array);
    636         assertFalse(layerDrawable.isStateful());
    637 
    638         array = new Drawable[] { new GradientDrawable(), new StateListDrawable() };
    639         layerDrawable = new LayerDrawable(array);
    640         assertTrue(layerDrawable.isStateful());
    641     }
    642 
    643     @Test
    644     public void testSetState() {
    645         MockDrawable mockDrawable1 = new MockDrawable(true);
    646         MockDrawable mockDrawable2 = new MockDrawable(true);
    647         Drawable[] array = new Drawable[] { mockDrawable1, mockDrawable2 };
    648         LayerDrawable layerDrawable = new LayerDrawable(array);
    649 
    650         // Call onStateChange() without actually changing the state.
    651         assertFalse(layerDrawable.setState(StateSet.WILD_CARD));
    652         assertFalse(mockDrawable1.hasCalledSetState());
    653         assertFalse(mockDrawable2.hasCalledSetState());
    654         assertFalse(mockDrawable1.hasCalledOnBoundsChange());
    655         assertFalse(mockDrawable2.hasCalledOnBoundsChange());
    656 
    657         // Call onStateChange() to change the state from WILD_CARD to null.
    658         // This alters the padding of both layers, which forces a bounds change
    659         // for the second layer due to the default "nest" padding mode.
    660         mockDrawable1.reset();
    661         mockDrawable2.reset();
    662         assertTrue(layerDrawable.setState(null));
    663         assertTrue(mockDrawable1.hasCalledSetState());
    664         assertTrue(mockDrawable2.hasCalledSetState());
    665         assertFalse(mockDrawable1.hasCalledOnBoundsChange());
    666         assertTrue(mockDrawable2.hasCalledOnBoundsChange());
    667 
    668         // Call onStateChange() to change the state from null to valid state
    669         // set. This alters the padding of both layers, which forces a bounds
    670         // change for the second layer due to the default "nest" padding mode.
    671         mockDrawable1.reset();
    672         mockDrawable2.reset();
    673         assertTrue(layerDrawable.setState(new int[]{
    674                 android.R.attr.state_checked, android.R.attr.state_empty}));
    675         assertTrue(mockDrawable1.hasCalledSetState());
    676         assertTrue(mockDrawable2.hasCalledSetState());
    677         assertFalse(mockDrawable1.hasCalledOnBoundsChange());
    678         assertTrue(mockDrawable2.hasCalledOnBoundsChange());
    679     }
    680 
    681     @Test
    682     public void testJumpToCurrentState() {
    683         Drawable mockDrawable1 = spy(new ColorDrawable(Color.BLUE));
    684         Drawable mockDrawable2 = spy(new ColorDrawable(Color.BLACK));
    685         Drawable[] array = new Drawable[] { mockDrawable1, mockDrawable2 };
    686         LayerDrawable layerDrawable = new LayerDrawable(array);
    687 
    688         verify(mockDrawable1, never()).jumpToCurrentState();
    689         verify(mockDrawable2, never()).jumpToCurrentState();
    690 
    691         layerDrawable.jumpToCurrentState();
    692 
    693         verify(mockDrawable1, times(1)).jumpToCurrentState();
    694         verify(mockDrawable2, times(1)).jumpToCurrentState();
    695     }
    696 
    697     @Test
    698     public void testSetLevel() {
    699         MockDrawable mockDrawable1 = new MockDrawable();
    700         MockDrawable mockDrawable2 = new MockDrawable();
    701         Drawable[] array = new Drawable[] { mockDrawable1, mockDrawable2 };
    702         LayerDrawable layerDrawable = new LayerDrawable(array);
    703 
    704         // Call onLevelChange() without actually changing the level.
    705         assertFalse(layerDrawable.setLevel(0));
    706         assertFalse(mockDrawable1.hasCalledOnLevelChange());
    707         assertFalse(mockDrawable2.hasCalledOnLevelChange());
    708         assertFalse(mockDrawable1.hasCalledOnBoundsChange());
    709         assertFalse(mockDrawable2.hasCalledOnBoundsChange());
    710 
    711         // Call onLevelChange() to change the level from 0 to MAX_VALUE. This
    712         // alters the padding of both layers, which forces a bounds change for
    713         // the second layer due to the default "nest" padding mode.
    714         mockDrawable1.reset();
    715         mockDrawable2.reset();
    716         assertTrue(layerDrawable.setLevel(Integer.MAX_VALUE));
    717         assertTrue(mockDrawable1.hasCalledOnLevelChange());
    718         assertTrue(mockDrawable2.hasCalledOnLevelChange());
    719         assertFalse(mockDrawable1.hasCalledOnBoundsChange());
    720         assertTrue(mockDrawable2.hasCalledOnBoundsChange());
    721 
    722         // Call onLevelChange() to change the level from MAX_VALUE to
    723         // MIN_VALUE. This alters the padding of both layers, which forces a
    724         // bounds change for the second layer due to the default "nest" padding
    725         // mode.
    726         mockDrawable1.reset();
    727         mockDrawable2.reset();
    728         assertTrue(layerDrawable.setLevel(Integer.MIN_VALUE));
    729         assertTrue(mockDrawable1.hasCalledOnLevelChange());
    730         assertTrue(mockDrawable2.hasCalledOnLevelChange());
    731         assertFalse(mockDrawable1.hasCalledOnBoundsChange());
    732         assertTrue(mockDrawable2.hasCalledOnBoundsChange());
    733     }
    734 
    735     @Test
    736     public void testSetBounds() {
    737         Drawable mockDrawable1 = spy(new ColorDrawable(Color.GREEN));
    738         Drawable mockDrawable2 = spy(new ColorDrawable(Color.BLUE));
    739         Drawable[] array = new Drawable[] { mockDrawable1, mockDrawable2 };
    740         LayerDrawable layerDrawable = new LayerDrawable(array);
    741 
    742         Rect inset1 = new Rect(1, 2, 3, 4);
    743         Rect inset2 = new Rect(2, 4, 6, 7);
    744         Rect padding1 = new Rect(11, 22, 33, 44);
    745         Rect padding2 = new Rect(21, 32, 43, 54);
    746         layerDrawable.setLayerInset(0, inset1.left, inset1.top, inset1.right, inset1.bottom);
    747         layerDrawable.setLayerInset(1, inset2.left, inset2.top, inset2.right, inset2.bottom);
    748         doAnswer(invocation -> {
    749             Rect target = (Rect) invocation.getArguments() [0];
    750             target.set(padding1);
    751             return true;
    752         }).when(mockDrawable1).getPadding(any());
    753         doAnswer(invocation -> {
    754             Rect target = (Rect) invocation.getArguments() [0];
    755             target.set(padding2);
    756             return true;
    757         }).when(mockDrawable2).getPadding(any());
    758         layerDrawable.getPadding(new Rect());
    759 
    760         // the children's bounds before call onBoundsChange
    761         assertEquals(0, mockDrawable1.getBounds().left);
    762         assertEquals(0, mockDrawable1.getBounds().top);
    763         assertEquals(0, mockDrawable1.getBounds().right);
    764         assertEquals(0, mockDrawable1.getBounds().bottom);
    765         assertEquals(0, mockDrawable2.getBounds().left);
    766         assertEquals(0, mockDrawable2.getBounds().top);
    767         assertEquals(0, mockDrawable2.getBounds().right);
    768         assertEquals(0, mockDrawable2.getBounds().bottom);
    769 
    770         Rect bounds = new Rect(10, 20, 30, 40);
    771         layerDrawable.setBounds(bounds);
    772 
    773         // all children's bounds will be changed after call onBoundsChange
    774         assertEquals(bounds.left + inset1.left, mockDrawable1.getBounds().left);
    775         assertEquals(bounds.top + inset1.top, mockDrawable1.getBounds().top);
    776         assertEquals(bounds.right - inset1.right, mockDrawable1.getBounds().right);
    777         assertEquals(bounds.bottom - inset1.bottom, mockDrawable1.getBounds().bottom);
    778         assertEquals(bounds.left + inset2.left + padding1.left, mockDrawable2.getBounds().left);
    779         assertEquals(bounds.top + inset2.top + padding1.top, mockDrawable2.getBounds().top);
    780         assertEquals(bounds.right - inset2.right - padding1.right,
    781                 mockDrawable2.getBounds().right);
    782         assertEquals(bounds.bottom - inset2.bottom - padding1.bottom,
    783                 mockDrawable2.getBounds().bottom);
    784     }
    785 
    786     @Test
    787     public void testGetIntrinsicWidth() {
    788         Drawable largeMockDrawable = spy(new ColorDrawable(Color.YELLOW));
    789         doReturn(10).when(largeMockDrawable).getIntrinsicWidth();
    790         doReturn(10).when(largeMockDrawable).getIntrinsicHeight();
    791         Drawable smallMockDrawable = spy(new ColorDrawable(Color.MAGENTA));
    792         doReturn(1).when(smallMockDrawable).getIntrinsicWidth();
    793         doReturn(1).when(smallMockDrawable).getIntrinsicHeight();
    794 
    795         Drawable[] array = new Drawable[] { largeMockDrawable, smallMockDrawable };
    796         LayerDrawable layerDrawable = new LayerDrawable(array);
    797         assertEquals(largeMockDrawable.getIntrinsicWidth(), layerDrawable.getIntrinsicWidth());
    798 
    799         Rect inset1 = new Rect(1, 2, 3, 4);
    800         Rect inset2 = new Rect(2, 4, 6, 7);
    801         final Rect padding1 = new Rect(11, 22, 33, 44);
    802         final Rect padding2 = new Rect(21, 32, 43, 54);
    803         layerDrawable.setLayerInset(0, inset1.left, inset1.top, inset1.right, inset1.bottom);
    804         layerDrawable.setLayerInset(1, inset2.left, inset2.top, inset2.right, inset2.bottom);
    805 
    806         doAnswer(invocation -> {
    807             Rect target = (Rect) invocation.getArguments() [0];
    808             target.set(padding1);
    809             return true;
    810         }).when(largeMockDrawable).getPadding(any());
    811         doAnswer(invocation -> {
    812             Rect target = (Rect) invocation.getArguments() [0];
    813             target.set(padding2);
    814             return true;
    815         }).when(smallMockDrawable).getPadding(any());
    816 
    817         layerDrawable.getPadding(new Rect());
    818         assertEquals(smallMockDrawable.getIntrinsicWidth() + inset2.left
    819                 + inset2.right + padding1.left + padding1.right,
    820                 layerDrawable.getIntrinsicWidth());
    821 
    822         inset1 = new Rect(inset2.left + padding1.left + 1, inset2.top + padding1.top + 1,
    823                 inset2.right + padding1.right + 1, inset2.bottom + padding1.bottom + 1);
    824         layerDrawable.setLayerInset(0, inset1.left, inset1.top, inset1.right, inset1.bottom);
    825         assertEquals(largeMockDrawable.getIntrinsicWidth() + inset1.left + inset1.right,
    826                 layerDrawable.getIntrinsicWidth());
    827     }
    828 
    829     @Test
    830     public void testGetIntrinsicHeight() {
    831         Drawable largeMockDrawable = spy(new ColorDrawable(Color.CYAN));
    832         doReturn(10).when(largeMockDrawable).getIntrinsicWidth();
    833         doReturn(10).when(largeMockDrawable).getIntrinsicHeight();
    834         Drawable smallMockDrawable = spy(new ColorDrawable(Color.DKGRAY));
    835         doReturn(1).when(smallMockDrawable).getIntrinsicWidth();
    836         doReturn(1).when(smallMockDrawable).getIntrinsicHeight();
    837 
    838         Drawable[] array = new Drawable[] { largeMockDrawable, smallMockDrawable };
    839         LayerDrawable layerDrawable = new LayerDrawable(array);
    840         assertEquals(largeMockDrawable.getIntrinsicHeight(), layerDrawable.getIntrinsicHeight());
    841 
    842         Rect inset1 = new Rect(1, 2, 3, 4);
    843         Rect inset2 = new Rect(2, 4, 6, 7);
    844         final Rect padding1 = new Rect(11, 22, 33, 44);
    845         final Rect padding2 = new Rect(21, 32, 43, 54);
    846         layerDrawable.setLayerInset(0, inset1.left, inset1.top, inset1.right, inset1.bottom);
    847         layerDrawable.setLayerInset(1, inset2.left, inset2.top, inset2.right, inset2.bottom);
    848 
    849         doAnswer(invocation -> {
    850             Rect target = (Rect) invocation.getArguments() [0];
    851             target.set(padding1);
    852             return true;
    853         }).when(largeMockDrawable).getPadding(any());
    854         doAnswer(invocation -> {
    855             Rect target = (Rect) invocation.getArguments() [0];
    856             target.set(padding2);
    857             return true;
    858         }).when(smallMockDrawable).getPadding(any());
    859 
    860         layerDrawable.getPadding(new Rect());
    861         assertEquals(smallMockDrawable.getIntrinsicHeight() + inset2.top
    862                 + inset2.bottom + padding1.top + padding1.bottom,
    863                 layerDrawable.getIntrinsicHeight());
    864 
    865         inset1 = new Rect(inset2.left + padding1.left + 1, inset2.top + padding1.top + 1,
    866                 inset2.right + padding1.right + 1, inset2.bottom + padding1.bottom + 1);
    867         layerDrawable.setLayerInset(0, inset1.left, inset1.top, inset1.right, inset1.bottom);
    868         assertEquals(largeMockDrawable.getIntrinsicHeight() + inset1.top + inset1.bottom,
    869                 layerDrawable.getIntrinsicHeight());
    870     }
    871 
    872     @Test
    873     public void testGetConstantState() {
    874         Drawable[] array = new Drawable[] { mBitmapDrawable, mColorDrawable };
    875         LayerDrawable layerDrawable = new LayerDrawable(array);
    876         ConstantState constantState = layerDrawable.getConstantState();
    877         assertNotNull(constantState);
    878         assertEquals(0, constantState.getChangingConfigurations());
    879 
    880         layerDrawable.setChangingConfigurations(1);
    881         constantState = layerDrawable.getConstantState();
    882         assertNotNull(constantState);
    883         assertEquals(1, constantState.getChangingConfigurations());
    884     }
    885 
    886     @Test
    887     public void testAddLayer() {
    888         Drawable[] array = new Drawable[] { new GradientDrawable(), new ColorDrawable(Color.BLUE) };
    889         LayerDrawable layerDrawable = new LayerDrawable(array);
    890         GradientDrawable newDrawable = new GradientDrawable();
    891         int index = layerDrawable.addLayer(newDrawable);
    892 
    893         final int numLayers = layerDrawable.getNumberOfLayers();
    894         assertEquals(index, numLayers - 1);
    895         assertEquals(newDrawable, layerDrawable.getDrawable(index));
    896     }
    897 
    898     @Test
    899     public void testGetDrawable() {
    900         Drawable[] array = new Drawable[] { mBitmapDrawable, mColorDrawable };
    901         LayerDrawable layerDrawable = new LayerDrawable(array);
    902 
    903         assertEquals(array[0], layerDrawable.getDrawable(0));
    904         assertEquals(array[1], layerDrawable.getDrawable(1));
    905         try {
    906             assertEquals(null, layerDrawable.getDrawable(2));
    907             fail("Should throw IndexOutOfBoundsException");
    908         } catch (IndexOutOfBoundsException e) {
    909         }
    910     }
    911 
    912     @Test
    913     public void testFindIndexByLayerId() {
    914         Drawable[] array = new Drawable[] { mBitmapDrawable, mColorDrawable };
    915         LayerDrawable layerDrawable = new LayerDrawable(array);
    916 
    917         layerDrawable.setId(0, 10);
    918         layerDrawable.setId(1, 20);
    919 
    920         assertEquals(0, layerDrawable.findIndexByLayerId(10));
    921         assertEquals(1, layerDrawable.findIndexByLayerId(20));
    922         assertEquals(-1, layerDrawable.findIndexByLayerId(30));
    923     }
    924 
    925     @Test
    926     public void testSetDrawable() {
    927         Drawable[] array = new Drawable[] { mBitmapDrawable, mColorDrawable };
    928         LayerDrawable layerDrawable = new LayerDrawable(array);
    929         BitmapDrawable newBitmapDrawable = new BitmapDrawable();
    930         ColorDrawable newColorDrawable = new ColorDrawable(Color.GREEN);
    931         layerDrawable.setDrawable(0, newColorDrawable);
    932         layerDrawable.setDrawable(1, newBitmapDrawable);
    933 
    934         final int numLayers = layerDrawable.getNumberOfLayers();
    935         assertEquals(2, numLayers);
    936         assertEquals(newColorDrawable, layerDrawable.getDrawable(0));
    937         assertEquals(newBitmapDrawable, layerDrawable.getDrawable(1));
    938         try {
    939             assertEquals(null, layerDrawable.getDrawable(2));
    940             fail("Should throw IndexOutOfBoundsException");
    941         } catch (IndexOutOfBoundsException e) {
    942         }
    943     }
    944 
    945     @Test
    946     public void testGetLeftPadding() {
    947         Drawable[] array = new Drawable[] { mBitmapDrawable };
    948         LayerDrawable layerDrawable = new LayerDrawable(array);
    949         layerDrawable.setPadding(10, 11, 20, 21);
    950 
    951         assertEquals(10, layerDrawable.getLeftPadding());
    952     }
    953 
    954     @Test
    955     public void testGetTopPadding() {
    956         Drawable[] array = new Drawable[] { mBitmapDrawable };
    957         LayerDrawable layerDrawable = new LayerDrawable(array);
    958         layerDrawable.setPadding(10, 11, 20, 21);
    959 
    960         assertEquals(11, layerDrawable.getTopPadding());
    961     }
    962 
    963     @Test
    964     public void testGetRightPadding() {
    965         Drawable[] array = new Drawable[] { mBitmapDrawable };
    966         LayerDrawable layerDrawable = new LayerDrawable(array);
    967         layerDrawable.setPadding(10, 11, 20, 21);
    968 
    969         assertEquals(20, layerDrawable.getRightPadding());
    970     }
    971 
    972     @Test
    973     public void testGetBottomPadding() {
    974         Drawable[] array = new Drawable[] { mBitmapDrawable };
    975         LayerDrawable layerDrawable = new LayerDrawable(array);
    976         layerDrawable.setPadding(10, 11, 20, 21);
    977 
    978         assertEquals(21, layerDrawable.getBottomPadding());
    979     }
    980 
    981     @Test
    982     public void testGetStartPadding() {
    983         Drawable[] array = new Drawable[] { mBitmapDrawable };
    984         LayerDrawable layerDrawable = new LayerDrawable(array);
    985         layerDrawable.setPadding(10, 11, 20, 21);
    986 
    987         assertEquals(-1, layerDrawable.getStartPadding());
    988         layerDrawable.setPaddingRelative(10, 11, 20, 21);
    989         assertEquals(10, layerDrawable.getStartPadding());
    990     }
    991 
    992     @Test
    993     public void testGetEndPadding() {
    994         Drawable[] array = new Drawable[] { mBitmapDrawable };
    995         LayerDrawable layerDrawable = new LayerDrawable(array);
    996         layerDrawable.setPadding(10, 11, 20, 21);
    997 
    998         assertEquals(-1, layerDrawable.getEndPadding());
    999         layerDrawable.setPaddingRelative(10, 11, 20, 21);
   1000         assertEquals(20, layerDrawable.getEndPadding());
   1001     }
   1002 
   1003     @Test
   1004     public void testSetPadding() {
   1005         Drawable[] array = new Drawable[] { mBitmapDrawable };
   1006         LayerDrawable layerDrawable = new LayerDrawable(array);
   1007         layerDrawable.setPadding(10, 11, 20, 21);
   1008 
   1009         assertEquals(10, layerDrawable.getLeftPadding());
   1010         assertEquals(11, layerDrawable.getTopPadding());
   1011         assertEquals(20, layerDrawable.getRightPadding());
   1012         assertEquals(21, layerDrawable.getBottomPadding());
   1013         assertEquals(-1, layerDrawable.getStartPadding());
   1014         assertEquals(-1, layerDrawable.getEndPadding());
   1015     }
   1016 
   1017     @Test
   1018     public void testSetPaddingRelative() {
   1019         Drawable[] array = new Drawable[] { mBitmapDrawable };
   1020         LayerDrawable layerDrawable = new LayerDrawable(array);
   1021         layerDrawable.setPaddingRelative(10, 11, 20, 21);
   1022 
   1023         assertEquals(10, layerDrawable.getStartPadding());
   1024         assertEquals(11, layerDrawable.getTopPadding());
   1025         assertEquals(20, layerDrawable.getEndPadding());
   1026         assertEquals(21, layerDrawable.getBottomPadding());
   1027         assertEquals(-1, layerDrawable.getLeftPadding());
   1028         assertEquals(-1, layerDrawable.getRightPadding());
   1029     }
   1030 
   1031     @Test
   1032     public void testSetLayerGravity() {
   1033         Drawable[] array = new Drawable[] { mBitmapDrawable, mColorDrawable };
   1034         LayerDrawable layerDrawable = new LayerDrawable(array);
   1035 
   1036         layerDrawable.setLayerGravity(0, Gravity.CENTER);
   1037         layerDrawable.setLayerGravity(1, Gravity.NO_GRAVITY);
   1038 
   1039         try {
   1040             layerDrawable.setLayerGravity(2, Gravity.TOP);
   1041             fail("Should throw ArrayIndexOutOfBoundsException");
   1042         } catch (ArrayIndexOutOfBoundsException e) {
   1043         }
   1044         assertEquals(Gravity.CENTER, layerDrawable.getLayerGravity(0));
   1045         assertEquals(Gravity.NO_GRAVITY, layerDrawable.getLayerGravity(1));
   1046     }
   1047 
   1048     @Test
   1049     public void testGetLayerGravity() {
   1050         Drawable[] array = new Drawable[] { mBitmapDrawable, mColorDrawable };
   1051         LayerDrawable layerDrawable = new LayerDrawable(array);
   1052 
   1053         layerDrawable.setLayerGravity(0, Gravity.CENTER);
   1054         layerDrawable.setLayerGravity(1, Gravity.NO_GRAVITY);
   1055 
   1056         assertEquals(Gravity.CENTER, layerDrawable.getLayerGravity(0));
   1057         assertEquals(Gravity.NO_GRAVITY, layerDrawable.getLayerGravity(1));
   1058         try {
   1059             layerDrawable.getLayerGravity(2);
   1060             fail("Should throw ArrayIndexOutOfBoundsException");
   1061         } catch (ArrayIndexOutOfBoundsException e) {
   1062         }
   1063     }
   1064 
   1065     @Test
   1066     public void testSetLayerWidth() {
   1067         Drawable[] array = new Drawable[] { mBitmapDrawable, mColorDrawable };
   1068         LayerDrawable layerDrawable = new LayerDrawable(array);
   1069 
   1070         layerDrawable.setLayerWidth(0, 100);
   1071         layerDrawable.setLayerWidth(1, 200);
   1072 
   1073         try {
   1074             layerDrawable.setLayerWidth(2, 300);
   1075             fail("Should throw ArrayIndexOutOfBoundsException");
   1076         } catch (ArrayIndexOutOfBoundsException e) {
   1077         }
   1078         assertEquals(100, layerDrawable.getLayerWidth(0));
   1079         assertEquals(200, layerDrawable.getLayerWidth(1));
   1080     }
   1081 
   1082     @Test
   1083     public void testGetLayerWidth() {
   1084         Drawable[] array = new Drawable[] { mBitmapDrawable, mColorDrawable };
   1085         LayerDrawable layerDrawable = new LayerDrawable(array);
   1086 
   1087         layerDrawable.setLayerWidth(0, 100);
   1088         layerDrawable.setLayerWidth(1, 200);
   1089 
   1090         assertEquals(100, layerDrawable.getLayerWidth(0));
   1091         assertEquals(200, layerDrawable.getLayerWidth(1));
   1092         try {
   1093             layerDrawable.getLayerWidth(2);
   1094             fail("Should throw ArrayIndexOutOfBoundsException");
   1095         } catch (ArrayIndexOutOfBoundsException e) {
   1096         }
   1097     }
   1098 
   1099     @Test
   1100     public void testSetLayerHeight() {
   1101         Drawable[] array = new Drawable[] { mBitmapDrawable, mColorDrawable };
   1102         LayerDrawable layerDrawable = new LayerDrawable(array);
   1103 
   1104         layerDrawable.setLayerHeight(0, 100);
   1105         layerDrawable.setLayerHeight(1, 200);
   1106 
   1107         try {
   1108             layerDrawable.setLayerHeight(2, 300);
   1109             fail("Should throw ArrayIndexOutOfBoundsException");
   1110         } catch (ArrayIndexOutOfBoundsException e) {
   1111         }
   1112         assertEquals(100, layerDrawable.getLayerHeight(0));
   1113         assertEquals(200, layerDrawable.getLayerHeight(1));
   1114     }
   1115 
   1116     @Test
   1117     public void testGetLayerHeight() {
   1118         Drawable[] array = new Drawable[] { mBitmapDrawable, mColorDrawable };
   1119         LayerDrawable layerDrawable = new LayerDrawable(array);
   1120 
   1121         layerDrawable.setLayerHeight(0, 100);
   1122         layerDrawable.setLayerHeight(1, 200);
   1123 
   1124         assertEquals(100, layerDrawable.getLayerHeight(0));
   1125         assertEquals(200, layerDrawable.getLayerHeight(1));
   1126         try {
   1127             layerDrawable.getLayerHeight(2);
   1128             fail("Should throw ArrayIndexOutOfBoundsException");
   1129         } catch (ArrayIndexOutOfBoundsException e) {
   1130         }
   1131     }
   1132 
   1133     @Test
   1134     public void testSetLayerSize() {
   1135         Drawable[] array = new Drawable[] { mBitmapDrawable, mColorDrawable };
   1136         LayerDrawable layerDrawable = new LayerDrawable(array);
   1137 
   1138         layerDrawable.setLayerSize(0, 100, 200);
   1139         layerDrawable.setLayerSize(1, 300, 400);
   1140 
   1141         try {
   1142             layerDrawable.setLayerSize(2, 500, 600);
   1143             fail("Should throw ArrayIndexOutOfBoundsException");
   1144         } catch (ArrayIndexOutOfBoundsException e) {
   1145         }
   1146         assertEquals(100, layerDrawable.getLayerWidth(0));
   1147         assertEquals(200, layerDrawable.getLayerHeight(0));
   1148         assertEquals(300, layerDrawable.getLayerWidth(1));
   1149         assertEquals(400, layerDrawable.getLayerHeight(1));
   1150     }
   1151 
   1152     @Test
   1153     public void testSetLayerInsetRelative() {
   1154         Drawable firstLayer = spy(new ColorDrawable(Color.YELLOW));
   1155         doReturn(10).when(firstLayer).getIntrinsicWidth();
   1156         doReturn(10).when(firstLayer).getIntrinsicHeight();
   1157         Drawable secondLayer = spy(new ColorDrawable(Color.YELLOW));
   1158         doReturn(-1).when(secondLayer).getIntrinsicWidth();
   1159         doReturn(-1).when(secondLayer).getIntrinsicHeight();
   1160 
   1161         Drawable[] array = new Drawable[] { firstLayer, secondLayer };
   1162         LayerDrawable layerDrawable = new LayerDrawable(array);
   1163 
   1164         int start = 10;
   1165         int top = 20;
   1166         int end = 30;
   1167         int bottom = 40;
   1168         layerDrawable.setLayerInsetRelative(0, start, top, end, bottom);
   1169         assertEquals(layerDrawable.getDrawable(0).getIntrinsicWidth() + start + end,
   1170                 layerDrawable.getIntrinsicWidth());
   1171         assertEquals(layerDrawable.getDrawable(0).getIntrinsicHeight() + top + bottom,
   1172                 layerDrawable.getIntrinsicHeight());
   1173         assertEquals(start, layerDrawable.getLayerInsetStart(0));
   1174         assertEquals(top, layerDrawable.getLayerInsetTop(0));
   1175         assertEquals(end, layerDrawable.getLayerInsetEnd(0));
   1176         assertEquals(bottom, layerDrawable.getLayerInsetBottom(0));
   1177         assertEquals(0, layerDrawable.getLayerInsetLeft(0));
   1178         assertEquals(0, layerDrawable.getLayerInsetRight(0));
   1179 
   1180         // The drawable at index 1 has no intrinsic width or height, so it
   1181         // won't be counted for the overall intrinsic width or height.
   1182         layerDrawable.setLayerInsetRelative(1, 10, 10, 10, 10);
   1183         assertEquals(layerDrawable.getDrawable(0).getIntrinsicWidth() + start + end,
   1184                 layerDrawable.getIntrinsicWidth());
   1185         assertEquals(layerDrawable.getDrawable(0).getIntrinsicHeight() + top + bottom,
   1186                 layerDrawable.getIntrinsicHeight());
   1187 
   1188         try {
   1189             layerDrawable.setLayerInsetRelative(-1, start, top, end, bottom);
   1190             fail("Should throw IndexOutOfBoundsException");
   1191         } catch (IndexOutOfBoundsException e) {
   1192         }
   1193     }
   1194 
   1195     @Test
   1196     public void testSetLayerInsetLeft() {
   1197         Drawable[] array = new Drawable[] { mBitmapDrawable };
   1198         LayerDrawable layerDrawable = new LayerDrawable(array);
   1199 
   1200         // set inset for layer 0
   1201         int left = 10;
   1202         int top = 20;
   1203         int right = 30;
   1204         int bottom = 40;
   1205         layerDrawable.setLayerInset(0, left, top, right, bottom);
   1206         assertEquals(layerDrawable.getDrawable(0).getIntrinsicWidth() + left + right,
   1207                 layerDrawable.getIntrinsicWidth());
   1208         left += 5;
   1209         layerDrawable.setLayerInsetLeft(0, left);
   1210         assertEquals(layerDrawable.getDrawable(0).getIntrinsicWidth() + left + right,
   1211                 layerDrawable.getIntrinsicWidth());
   1212         assertEquals(left, layerDrawable.getLayerInsetLeft(0));
   1213 
   1214         try {
   1215             layerDrawable.setLayerInsetLeft(1, left);
   1216             fail("Should throw IndexOutOfBoundsException");
   1217         } catch (IndexOutOfBoundsException e) {
   1218         }
   1219     }
   1220 
   1221     @Test
   1222     public void testGetLayerInsetLeft() {
   1223         Drawable[] array = new Drawable[] { mBitmapDrawable };
   1224         LayerDrawable layerDrawable = new LayerDrawable(array);
   1225 
   1226         // set inset for layer 0
   1227         int left = 10;
   1228         int top = 20;
   1229         int right = 30;
   1230         int bottom = 40;
   1231         layerDrawable.setLayerInset(0, left, top, right, bottom);
   1232         assertEquals(left, layerDrawable.getLayerInsetLeft(0));
   1233         left += 5;
   1234         layerDrawable.setLayerInsetLeft(0, left);
   1235         assertEquals(left, layerDrawable.getLayerInsetLeft(0));
   1236 
   1237         try {
   1238             layerDrawable.getLayerInsetLeft(1);
   1239             fail("Should throw IndexOutOfBoundsException");
   1240         } catch (IndexOutOfBoundsException e) {
   1241         }
   1242     }
   1243 
   1244     @Test
   1245     public void testSetLayerInsetTop() {
   1246         Drawable[] array = new Drawable[] { mBitmapDrawable };
   1247         LayerDrawable layerDrawable = new LayerDrawable(array);
   1248 
   1249         // set inset for layer 0
   1250         int left = 10;
   1251         int top = 20;
   1252         int right = 30;
   1253         int bottom = 40;
   1254         layerDrawable.setLayerInset(0, left, top, right, bottom);
   1255         assertEquals(layerDrawable.getDrawable(0).getIntrinsicHeight() + top + bottom,
   1256                 layerDrawable.getIntrinsicHeight());
   1257         top += 5;
   1258         layerDrawable.setLayerInsetTop(0, top);
   1259         assertEquals(layerDrawable.getDrawable(0).getIntrinsicHeight() + top + bottom,
   1260                 layerDrawable.getIntrinsicHeight());
   1261         assertEquals(top, layerDrawable.getLayerInsetTop(0));
   1262 
   1263         try {
   1264             layerDrawable.setLayerInsetTop(1, top);
   1265             fail("Should throw IndexOutOfBoundsException");
   1266         } catch (IndexOutOfBoundsException e) {
   1267         }
   1268     }
   1269 
   1270     @Test
   1271     public void testGetLayerInsetTop() {
   1272         Drawable[] array = new Drawable[] { mBitmapDrawable };
   1273         LayerDrawable layerDrawable = new LayerDrawable(array);
   1274 
   1275         // set inset for layer 0
   1276         int left = 10;
   1277         int top = 20;
   1278         int right = 30;
   1279         int bottom = 40;
   1280         layerDrawable.setLayerInset(0, left, top, right, bottom);
   1281         assertEquals(top, layerDrawable.getLayerInsetTop(0));
   1282         top += 5;
   1283         layerDrawable.setLayerInsetTop(0, top);
   1284         assertEquals(top, layerDrawable.getLayerInsetTop(0));
   1285 
   1286         try {
   1287             layerDrawable.getLayerInsetTop(1);
   1288             fail("Should throw IndexOutOfBoundsException");
   1289         } catch (IndexOutOfBoundsException e) {
   1290         }
   1291     }
   1292 
   1293     @Test
   1294     public void testSetLayerInsetRight() {
   1295         Drawable[] array = new Drawable[] { mBitmapDrawable };
   1296         LayerDrawable layerDrawable = new LayerDrawable(array);
   1297 
   1298         // set inset for layer 0
   1299         int left = 10;
   1300         int top = 20;
   1301         int right = 30;
   1302         int bottom = 40;
   1303         layerDrawable.setLayerInset(0, left, top, right, bottom);
   1304         assertEquals(layerDrawable.getDrawable(0).getIntrinsicWidth() + left + right,
   1305                 layerDrawable.getIntrinsicWidth());
   1306         right += 5;
   1307         layerDrawable.setLayerInsetRight(0, right);
   1308         assertEquals(layerDrawable.getDrawable(0).getIntrinsicWidth() + left + right,
   1309                 layerDrawable.getIntrinsicWidth());
   1310         assertEquals(right, layerDrawable.getLayerInsetRight(0));
   1311 
   1312         try {
   1313             layerDrawable.setLayerInsetRight(1, right);
   1314             fail("Should throw IndexOutOfBoundsException");
   1315         } catch (IndexOutOfBoundsException e) {
   1316         }
   1317     }
   1318 
   1319     @Test
   1320     public void testGetLayerInsetRight() {
   1321         Drawable[] array = new Drawable[] { mBitmapDrawable };
   1322         LayerDrawable layerDrawable = new LayerDrawable(array);
   1323 
   1324         // set inset for layer 0
   1325         int left = 10;
   1326         int top = 20;
   1327         int right = 30;
   1328         int bottom = 40;
   1329         layerDrawable.setLayerInset(0, left, top, right, bottom);
   1330         assertEquals(right, layerDrawable.getLayerInsetRight(0));
   1331         right += 5;
   1332         layerDrawable.setLayerInsetRight(0, right);
   1333         assertEquals(right, layerDrawable.getLayerInsetRight(0));
   1334 
   1335         try {
   1336             layerDrawable.getLayerInsetRight(1);
   1337             fail("Should throw IndexOutOfBoundsException");
   1338         } catch (IndexOutOfBoundsException e) {
   1339         }
   1340     }
   1341 
   1342     @Test
   1343     public void testSetLayerInsetBottom() {
   1344         Drawable[] array = new Drawable[] { mBitmapDrawable };
   1345         LayerDrawable layerDrawable = new LayerDrawable(array);
   1346 
   1347         // set inset for layer 0
   1348         int left = 10;
   1349         int top = 20;
   1350         int right = 30;
   1351         int bottom = 40;
   1352         layerDrawable.setLayerInset(0, left, top, right, bottom);
   1353         assertEquals(layerDrawable.getDrawable(0).getIntrinsicHeight() + top + bottom,
   1354                 layerDrawable.getIntrinsicHeight());
   1355         bottom += 5;
   1356         layerDrawable.setLayerInsetBottom(0, bottom);
   1357         assertEquals(layerDrawable.getDrawable(0).getIntrinsicHeight() + top + bottom,
   1358                 layerDrawable.getIntrinsicHeight());
   1359         assertEquals(bottom, layerDrawable.getLayerInsetBottom(0));
   1360 
   1361         try {
   1362             layerDrawable.setLayerInsetBottom(1, bottom);
   1363             fail("Should throw IndexOutOfBoundsException");
   1364         } catch (IndexOutOfBoundsException e) {
   1365         }
   1366     }
   1367 
   1368     @Test
   1369     public void testGetLayerInsetBottom() {
   1370         Drawable[] array = new Drawable[] { mBitmapDrawable };
   1371         LayerDrawable layerDrawable = new LayerDrawable(array);
   1372 
   1373         // set inset for layer 0
   1374         int left = 10;
   1375         int top = 20;
   1376         int right = 30;
   1377         int bottom = 40;
   1378         layerDrawable.setLayerInset(0, left, top, right, bottom);
   1379         assertEquals(bottom, layerDrawable.getLayerInsetBottom(0));
   1380         bottom += 5;
   1381         layerDrawable.setLayerInsetBottom(0, bottom);
   1382         assertEquals(bottom, layerDrawable.getLayerInsetBottom(0));
   1383 
   1384         try {
   1385             layerDrawable.getLayerInsetBottom(1);
   1386             fail("Should throw IndexOutOfBoundsException");
   1387         } catch (IndexOutOfBoundsException e) {
   1388         }
   1389     }
   1390 
   1391     @Test
   1392     public void testSetLayerInsetStart() {
   1393         Drawable[] array = new Drawable[] { mBitmapDrawable };
   1394         LayerDrawable layerDrawable = new LayerDrawable(array);
   1395 
   1396         // set inset for layer 0
   1397         int start = 10;
   1398         int top = 20;
   1399         int end = 30;
   1400         int bottom = 40;
   1401         layerDrawable.setLayerInsetRelative(0, start, top, end, bottom);
   1402         assertEquals(layerDrawable.getDrawable(0).getIntrinsicWidth() + start + end,
   1403                 layerDrawable.getIntrinsicWidth());
   1404         start += 5;
   1405         layerDrawable.setLayerInsetStart(0, start);
   1406         assertEquals(layerDrawable.getDrawable(0).getIntrinsicWidth() + start + end,
   1407                 layerDrawable.getIntrinsicWidth());
   1408         assertEquals(start, layerDrawable.getLayerInsetStart(0));
   1409 
   1410         try {
   1411             layerDrawable.setLayerInset(1, start, top, end, bottom);
   1412             fail("Should throw IndexOutOfBoundsException");
   1413         } catch (IndexOutOfBoundsException e) {
   1414         }
   1415     }
   1416 
   1417     @Test
   1418     public void testGetLayerInsetStart() {
   1419         Drawable[] array = new Drawable[] { mBitmapDrawable };
   1420         LayerDrawable layerDrawable = new LayerDrawable(array);
   1421 
   1422         // set inset for layer 0
   1423         int start = 10;
   1424         int top = 20;
   1425         int end = 30;
   1426         int bottom = 40;
   1427         layerDrawable.setLayerInsetRelative(0, start, top, end, bottom);
   1428         assertEquals(start, layerDrawable.getLayerInsetStart(0));
   1429         start += 5;
   1430         layerDrawable.setLayerInsetStart(0, start);
   1431         assertEquals(start, layerDrawable.getLayerInsetStart(0));
   1432 
   1433         try {
   1434             layerDrawable.getLayerInsetStart(1);
   1435             fail("Should throw IndexOutOfBoundsException");
   1436         } catch (IndexOutOfBoundsException e) {
   1437         }
   1438     }
   1439 
   1440     @Test
   1441     public void testSetLayerInsetEnd() {
   1442         Drawable[] array = new Drawable[] { mBitmapDrawable };
   1443         LayerDrawable layerDrawable = new LayerDrawable(array);
   1444 
   1445         // set inset for layer 0
   1446         int start = 10;
   1447         int top = 20;
   1448         int end = 30;
   1449         int bottom = 40;
   1450         layerDrawable.setLayerInsetRelative(0, start, top, end, bottom);
   1451         assertEquals(end, layerDrawable.getLayerInsetEnd(0));
   1452         assertEquals(layerDrawable.getDrawable(0).getIntrinsicWidth() + start + end,
   1453                 layerDrawable.getIntrinsicWidth());
   1454         end += 5;
   1455         layerDrawable.setLayerInsetEnd(0, end);
   1456         assertEquals(layerDrawable.getDrawable(0).getIntrinsicWidth() + start + end,
   1457                 layerDrawable.getIntrinsicWidth());
   1458         assertEquals(end, layerDrawable.getLayerInsetEnd(0));
   1459 
   1460         try {
   1461             layerDrawable.setLayerInsetEnd(1, end);
   1462             fail("Should throw IndexOutOfBoundsException");
   1463         } catch (IndexOutOfBoundsException e) {
   1464         }
   1465     }
   1466 
   1467     @Test
   1468     public void testGetLayerInsetEnd() {
   1469         Drawable[] array = new Drawable[] { mBitmapDrawable };
   1470         LayerDrawable layerDrawable = new LayerDrawable(array);
   1471 
   1472         // set inset for layer 0
   1473         int start = 10;
   1474         int top = 20;
   1475         int end = 30;
   1476         int bottom = 40;
   1477         layerDrawable.setLayerInsetRelative(0, start, top, end, bottom);
   1478         assertEquals(end, layerDrawable.getLayerInsetEnd(0));
   1479         end += 5;
   1480         layerDrawable.setLayerInsetEnd(0, end);
   1481         assertEquals(end, layerDrawable.getLayerInsetEnd(0));
   1482 
   1483         try {
   1484             layerDrawable.getLayerInsetEnd(1);
   1485             fail("Should throw IndexOutOfBoundsException");
   1486         } catch (IndexOutOfBoundsException e) {
   1487         }
   1488     }
   1489 
   1490     @Test
   1491     public void testChildIntrinsicSize() {
   1492         LayerDrawable dr;
   1493 
   1494         // Ensure that a child with no intrinsic size correctly reports bounds.
   1495         dr = (LayerDrawable) mContext.getDrawable(R.drawable.layer_drawable_intrinsic);
   1496         assertEquals(-1, dr.getIntrinsicWidth());
   1497         assertEquals(-1, dr.getIntrinsicHeight());
   1498 
   1499         // Check when creating the drawble from code.
   1500         dr = new LayerDrawable(new Drawable[] { new ColorDrawable(Color.RED) });
   1501         dr.setLayerInset(0, 10, 10, 10, 10);
   1502         assertEquals(-1, dr.getIntrinsicWidth());
   1503         assertEquals(-1, dr.getIntrinsicHeight());
   1504 
   1505         // Ensure mixed children report bounds correctly as well.
   1506         dr = (LayerDrawable) mContext.getDrawable(R.drawable.layer_drawable_intrinsic_mixed);
   1507         int width = dr.getLayerInsetLeft(0) + dr.getLayerInsetRight(0)
   1508                 + dr.getDrawable(0).getIntrinsicWidth();
   1509         int height = dr.getLayerInsetTop(0) + dr.getLayerInsetBottom(0)
   1510                 + dr.getDrawable(0).getIntrinsicHeight();
   1511         assertEquals(width, dr.getIntrinsicWidth());
   1512         assertEquals(height, dr.getIntrinsicHeight());
   1513     }
   1514 
   1515     // Since Mockito can't mock or spy on protected methods, we have a custom extension
   1516     // of Drawable to track calls to protected methods. This class also has empty implementations
   1517     // of the base abstract methods. In addition, this class also updates its padding on every
   1518     // change in level or state.
   1519     private static class MockDrawable extends Drawable {
   1520         private boolean mCalledSetState = false;
   1521         private boolean mCalledOnLevelChange = false;
   1522         private boolean mCalledOnBoundsChange = false;
   1523 
   1524         private boolean mIsStateful = false;
   1525 
   1526         private Rect mPadding = null;
   1527 
   1528         public MockDrawable() {
   1529             this(false);
   1530         }
   1531 
   1532         public MockDrawable(boolean isStateful) {
   1533             mIsStateful = isStateful;
   1534         }
   1535 
   1536         @Override
   1537         public void draw(Canvas canvas) {
   1538         }
   1539 
   1540         @Override
   1541         public int getOpacity() {
   1542             return PixelFormat.OPAQUE;
   1543         }
   1544 
   1545         @Override
   1546         public void setAlpha(int alpha) {
   1547         }
   1548 
   1549         @Override
   1550         public void setColorFilter(ColorFilter cf) {
   1551         }
   1552 
   1553         public void reset() {
   1554             mCalledSetState = false;
   1555             mCalledOnLevelChange = false;
   1556             mCalledOnBoundsChange = false;
   1557         }
   1558 
   1559         @Override
   1560         protected boolean onStateChange(int[] state) {
   1561             increasePadding();
   1562             return mIsStateful;
   1563         }
   1564 
   1565         private void increasePadding() {
   1566             Rect padding = new Rect();
   1567             getPadding(padding);
   1568             padding.left++;
   1569             padding.top++;
   1570             padding.right++;
   1571             padding.bottom++;
   1572 
   1573             setPadding(padding);
   1574         }
   1575 
   1576         @Override
   1577         protected boolean onLevelChange(int level) {
   1578             increasePadding();
   1579             mCalledOnLevelChange = true;
   1580             return true;
   1581         }
   1582 
   1583         @Override
   1584         protected void onBoundsChange(Rect bounds) {
   1585             mCalledOnBoundsChange = true;
   1586             super.onBoundsChange(bounds);
   1587         }
   1588 
   1589         public boolean hasCalledOnBoundsChange() {
   1590             return mCalledOnBoundsChange;
   1591         }
   1592 
   1593         @Override
   1594         public boolean isStateful() {
   1595             return mIsStateful;
   1596         }
   1597 
   1598         public boolean hasCalledSetState() {
   1599             return mCalledSetState;
   1600         }
   1601 
   1602         @Override
   1603         public boolean setState(final int[] stateSet) {
   1604             mCalledSetState = true;
   1605             return super.setState(stateSet);
   1606         }
   1607 
   1608         public boolean hasCalledOnLevelChange() {
   1609             return mCalledOnLevelChange;
   1610         }
   1611 
   1612         private void setPadding(Rect padding) {
   1613             if (padding == null) {
   1614                 mPadding = null;
   1615             } else {
   1616                 if (mPadding == null) {
   1617                     mPadding = new Rect();
   1618                 }
   1619                 mPadding.set(padding);
   1620             }
   1621         }
   1622 
   1623         @Override
   1624         public boolean getPadding(Rect padding) {
   1625             if (mPadding != null) {
   1626                 padding.set(mPadding);
   1627                 return true;
   1628             } else {
   1629                 return super.getPadding(padding);
   1630             }
   1631         }
   1632     }
   1633 
   1634     @Test
   1635     public void testMutate() {
   1636         LayerDrawable d1 = (LayerDrawable) mContext.getDrawable(R.drawable.layerdrawable);
   1637         LayerDrawable d2 = (LayerDrawable) mContext.getDrawable(R.drawable.layerdrawable);
   1638         LayerDrawable d3 = (LayerDrawable) mContext.getDrawable(R.drawable.layerdrawable);
   1639         int restoreAlpha = d1.getAlpha();
   1640 
   1641         try {
   1642             // verify bad behavior - modify before mutate pollutes other drawables
   1643             d1.setAlpha(100);
   1644             assertEquals(100, ((BitmapDrawable) d1.getDrawable(0)).getPaint().getAlpha());
   1645             assertEquals(100, ((BitmapDrawable) d1.getDrawable(0)).getPaint().getAlpha());
   1646             assertEquals(100, ((BitmapDrawable) d2.getDrawable(0)).getPaint().getAlpha());
   1647             assertEquals(100, ((BitmapDrawable) d2.getDrawable(0)).getPaint().getAlpha());
   1648             assertEquals(100, ((BitmapDrawable) d3.getDrawable(0)).getPaint().getAlpha());
   1649             assertEquals(100, ((BitmapDrawable) d2.getDrawable(0)).getPaint().getAlpha());
   1650 
   1651             d1.mutate();
   1652             d1.setAlpha(200);
   1653             assertEquals(200, ((BitmapDrawable) d1.getDrawable(0)).getPaint().getAlpha());
   1654             assertEquals(200, ((BitmapDrawable) d1.getDrawable(0)).getPaint().getAlpha());
   1655             assertEquals(100, ((BitmapDrawable) d2.getDrawable(0)).getPaint().getAlpha());
   1656             assertEquals(100, ((BitmapDrawable) d2.getDrawable(0)).getPaint().getAlpha());
   1657             assertEquals(100, ((BitmapDrawable) d3.getDrawable(0)).getPaint().getAlpha());
   1658             assertEquals(100, ((BitmapDrawable) d3.getDrawable(0)).getPaint().getAlpha());
   1659 
   1660             d2.setAlpha(50);
   1661             assertEquals(200, ((BitmapDrawable) d1.getDrawable(0)).getPaint().getAlpha());
   1662             assertEquals(200, ((BitmapDrawable) d1.getDrawable(0)).getPaint().getAlpha());
   1663             assertEquals(50, ((BitmapDrawable) d2.getDrawable(0)).getPaint().getAlpha());
   1664             assertEquals(50, ((BitmapDrawable) d2.getDrawable(0)).getPaint().getAlpha());
   1665             assertEquals(50, ((BitmapDrawable) d3.getDrawable(0)).getPaint().getAlpha());
   1666             assertEquals(50, ((BitmapDrawable) d3.getDrawable(0)).getPaint().getAlpha());
   1667         } finally {
   1668             // restore externally visible state, since other tests may use the drawable
   1669             mContext.getDrawable(R.drawable.layerdrawable).setAlpha(restoreAlpha);
   1670         }
   1671     }
   1672 
   1673     @Test
   1674     public void testPreloadDensity() throws XmlPullParserException, IOException {
   1675         final Resources res = mContext.getResources();
   1676         final int densityDpi = res.getConfiguration().densityDpi;
   1677         try {
   1678             DrawableTestUtils.setResourcesDensity(res, densityDpi);
   1679             verifyPreloadDensityInner(res, densityDpi);
   1680         } finally {
   1681             DrawableTestUtils.setResourcesDensity(res, densityDpi);
   1682         }
   1683     }
   1684 
   1685     @Test
   1686     public void testPreloadDensity_tvdpi() throws XmlPullParserException, IOException {
   1687         final Resources res = mContext.getResources();
   1688         final int densityDpi = res.getConfiguration().densityDpi;
   1689         try {
   1690             DrawableTestUtils.setResourcesDensity(res, 213);
   1691             verifyPreloadDensityInner(res, 213);
   1692         } finally {
   1693             DrawableTestUtils.setResourcesDensity(res, densityDpi);
   1694         }
   1695     }
   1696 
   1697     private void verifyPreloadDensityInner(Resources res, int densityDpi)
   1698             throws XmlPullParserException, IOException {
   1699         // Capture initial state at default density.
   1700         final XmlResourceParser parser = DrawableTestUtils.getResourceParser(
   1701                 res, R.drawable.layer_drawable_density);
   1702         final LayerDrawable preloadedDrawable = new LayerDrawable(new Drawable[0]);
   1703         preloadedDrawable.inflate(res, parser, Xml.asAttributeSet(parser));
   1704         final ConstantState preloadedConstantState = preloadedDrawable.getConstantState();
   1705         final int initialLeftPadding = preloadedDrawable.getLeftPadding();
   1706         final int initialRightPadding = preloadedDrawable.getRightPadding();
   1707         final int initialContentInsetL = preloadedDrawable.getLayerInsetLeft(0);
   1708         final int initialContentInsetR = preloadedDrawable.getLayerInsetRight(0);
   1709         final int initialContentWidth = preloadedDrawable.getLayerWidth(0);
   1710         final int initialIntrinsicWidth = preloadedDrawable.getIntrinsicWidth();
   1711         final int initialBottomPadding = preloadedDrawable.getBottomPadding();
   1712         final int initialTopPadding = preloadedDrawable.getTopPadding();
   1713         final int initialLayerInsetLeft = preloadedDrawable.getLayerInsetLeft(0);
   1714         final int initialLayerInsetRight = preloadedDrawable.getLayerInsetRight(0);
   1715         final int initialLayerInsetTop = preloadedDrawable.getLayerInsetTop(0);
   1716         final int initialLayerInsetBottom = preloadedDrawable.getLayerInsetBottom(0);
   1717         final int initialLayerWidth = preloadedDrawable.getLayerWidth(0);
   1718         final int initialLayerHeight = preloadedDrawable.getLayerHeight(0);
   1719 
   1720         // Set density to half of original. Padding and insets are
   1721         // truncated, dimensions are rounded to the nearest pixel. Because
   1722         // LayerDrawable's intrinsic width is a combination of padding and
   1723         // dimensions, some computation is necessary.
   1724         DrawableTestUtils.setResourcesDensity(res, densityDpi / 2);
   1725         final LayerDrawable halfDrawable =
   1726                 (LayerDrawable) preloadedConstantState.newDrawable(res);
   1727         // NOTE: densityDpi may not be an even number, so account for *actual* scaling in asserts
   1728         final float approxHalf = (float)(densityDpi / 2) / densityDpi;
   1729         final int halfContentWidth = Math.round(initialContentWidth * approxHalf);
   1730         final int halfLeftPadding = (int) (initialLeftPadding * approxHalf);
   1731         final int halfRightPadding = (int) (initialRightPadding * approxHalf);
   1732         final int halfContentInsetL = (int) (initialContentInsetL * approxHalf);
   1733         final int halfContentInsetR = (int) (initialContentInsetR * approxHalf);
   1734         final int halfIntrinsicWidth = halfContentWidth + halfContentInsetL + halfContentInsetR;
   1735         assertEquals(halfLeftPadding, halfDrawable.getLeftPadding());
   1736         assertEquals(halfRightPadding, halfDrawable.getRightPadding());
   1737         assertEquals(halfContentInsetL, halfDrawable.getLayerInsetRight(0));
   1738         assertEquals(halfContentInsetR, halfDrawable.getLayerInsetLeft(0));
   1739         assertEquals(halfContentWidth, halfDrawable.getLayerWidth(0));
   1740         assertEquals(halfIntrinsicWidth, halfDrawable.getIntrinsicWidth());
   1741         assertEquals((int) (initialBottomPadding * approxHalf), halfDrawable.getBottomPadding());
   1742         assertEquals((int) (initialTopPadding * approxHalf), halfDrawable.getTopPadding());
   1743         assertEquals((int) (initialLayerInsetLeft * approxHalf),
   1744                 halfDrawable.getLayerInsetLeft(0));
   1745         assertEquals((int) (initialLayerInsetRight * approxHalf),
   1746                 halfDrawable.getLayerInsetRight(0));
   1747         assertEquals((int) (initialLayerInsetTop * approxHalf),
   1748                 halfDrawable.getLayerInsetTop(0));
   1749         assertEquals((int) (initialLayerInsetBottom * approxHalf),
   1750                 halfDrawable.getLayerInsetBottom(0));
   1751         assertEquals(Math.round(initialLayerWidth * approxHalf), halfDrawable.getLayerWidth(0));
   1752         assertEquals(Math.round(initialLayerHeight * approxHalf), halfDrawable.getLayerHeight(0));
   1753 
   1754         // Set density to double original.
   1755         DrawableTestUtils.setResourcesDensity(res, densityDpi * 2);
   1756         final LayerDrawable doubleDrawable =
   1757                 (LayerDrawable) preloadedConstantState.newDrawable(res);
   1758         assertEquals(initialLeftPadding * 2, doubleDrawable.getLeftPadding());
   1759         assertEquals(initialRightPadding * 2, doubleDrawable.getRightPadding());
   1760         assertEquals(initialContentInsetL * 2, doubleDrawable.getLayerInsetRight(0));
   1761         assertEquals(initialContentInsetR * 2, doubleDrawable.getLayerInsetLeft(0));
   1762         assertEquals(initialContentWidth * 2, doubleDrawable.getLayerWidth(0));
   1763         assertEquals(initialIntrinsicWidth * 2, doubleDrawable.getIntrinsicWidth());
   1764         assertEquals(initialBottomPadding * 2, doubleDrawable.getBottomPadding());
   1765         assertEquals(initialTopPadding * 2, doubleDrawable.getTopPadding());
   1766         assertEquals(initialLayerInsetLeft * 2, doubleDrawable.getLayerInsetLeft(0));
   1767         assertEquals(initialLayerInsetRight * 2, doubleDrawable.getLayerInsetRight(0));
   1768         assertEquals(initialLayerInsetTop * 2, doubleDrawable.getLayerInsetTop(0));
   1769         assertEquals(initialLayerInsetBottom * 2, doubleDrawable.getLayerInsetBottom(0));
   1770         assertEquals(initialLayerWidth * 2, doubleDrawable.getLayerWidth(0));
   1771         assertEquals(initialLayerHeight * 2, doubleDrawable.getLayerHeight(0));
   1772 
   1773         // Restore original configuration and metrics.
   1774         DrawableTestUtils.setResourcesDensity(res, densityDpi);
   1775         final LayerDrawable origDrawable =
   1776                 (LayerDrawable) preloadedConstantState.newDrawable(res);
   1777         assertEquals(initialLeftPadding, origDrawable.getLeftPadding());
   1778         assertEquals(initialRightPadding, origDrawable.getRightPadding());
   1779         assertEquals(initialContentInsetL, origDrawable.getLayerInsetRight(0));
   1780         assertEquals(initialContentInsetR, origDrawable.getLayerInsetLeft(0));
   1781         assertEquals(initialContentWidth, origDrawable.getLayerWidth(0));
   1782         assertEquals(initialIntrinsicWidth, origDrawable.getIntrinsicWidth());
   1783         assertEquals(initialBottomPadding, origDrawable.getBottomPadding());
   1784         assertEquals(initialTopPadding, origDrawable.getTopPadding());
   1785         assertEquals(initialLayerInsetLeft, origDrawable.getLayerInsetLeft(0));
   1786         assertEquals(initialLayerInsetRight, origDrawable.getLayerInsetRight(0));
   1787         assertEquals(initialLayerInsetTop, origDrawable.getLayerInsetTop(0));
   1788         assertEquals(initialLayerInsetBottom, origDrawable.getLayerInsetBottom(0));
   1789         assertEquals(initialLayerWidth, origDrawable.getLayerWidth(0));
   1790         assertEquals(initialLayerHeight, origDrawable.getLayerHeight(0));
   1791 
   1792         // Ensure theme density is applied correctly.
   1793         final Theme t = res.newTheme();
   1794 
   1795         // The half-density drawable will scale-up all of the values that were
   1796         // previously scaled-down, so we need to capture the rounding errors.
   1797         halfDrawable.applyTheme(t);
   1798 
   1799         // Reproduce imprecise truncated scale down, and back up. Note that we don't round.
   1800         float approxDouble = 1 / approxHalf;
   1801         assertEquals((int) (halfLeftPadding * approxDouble), halfDrawable.getLeftPadding());
   1802         assertEquals((int) (halfRightPadding * approxDouble), halfDrawable.getRightPadding());
   1803         assertEquals((int) (halfContentInsetL * approxDouble), halfDrawable.getLayerInsetRight(0));
   1804         assertEquals((int) (halfContentInsetR * approxDouble), halfDrawable.getLayerInsetLeft(0));
   1805         assertEquals((int) (halfContentWidth * approxDouble), halfDrawable.getLayerWidth(0));
   1806         assertEquals(halfIntrinsicWidth * 2, halfDrawable.getIntrinsicWidth());
   1807         assertEquals((int) ((int) (initialBottomPadding * approxHalf) * approxDouble),
   1808                 halfDrawable.getBottomPadding());
   1809         assertEquals((int) ((int) (initialTopPadding * approxHalf) * approxDouble),
   1810                 halfDrawable.getTopPadding());
   1811         assertEquals((int) ((int) (initialLayerInsetLeft * approxHalf) * approxDouble),
   1812                 halfDrawable.getLayerInsetLeft(0));
   1813         assertEquals((int) ((int) (initialLayerInsetRight * approxHalf) * approxDouble),
   1814                 halfDrawable.getLayerInsetRight(0));
   1815         assertEquals((int) ((int) (initialLayerInsetTop * approxHalf) * approxDouble),
   1816                 halfDrawable.getLayerInsetTop(0));
   1817         assertEquals((int) ((int) (initialLayerInsetBottom * approxHalf) * approxDouble),
   1818                 halfDrawable.getLayerInsetBottom(0));
   1819         assertEquals(Math.round(Math.round(initialLayerWidth * approxHalf) * approxDouble),
   1820                 halfDrawable.getLayerWidth(0));
   1821         assertEquals(Math.round(Math.round(initialLayerHeight * approxHalf) * approxDouble),
   1822                 halfDrawable.getLayerHeight(0));
   1823 
   1824         // The double-density drawable will scale-down all of the values that
   1825         // were previously scaled-up, so we don't need to worry about rounding.
   1826         doubleDrawable.applyTheme(t);
   1827         assertEquals(initialLeftPadding, doubleDrawable.getLeftPadding());
   1828         assertEquals(initialRightPadding, doubleDrawable.getRightPadding());
   1829         assertEquals(initialContentInsetL, doubleDrawable.getLayerInsetRight(0));
   1830         assertEquals(initialContentInsetR, doubleDrawable.getLayerInsetLeft(0));
   1831         assertEquals(initialContentWidth, doubleDrawable.getLayerWidth(0));
   1832         assertEquals(initialIntrinsicWidth, doubleDrawable.getIntrinsicWidth());
   1833         assertEquals(initialBottomPadding, doubleDrawable.getBottomPadding());
   1834         assertEquals(initialTopPadding, doubleDrawable.getTopPadding());
   1835         assertEquals(initialLayerInsetLeft, doubleDrawable.getLayerInsetLeft(0));
   1836         assertEquals(initialLayerInsetRight, doubleDrawable.getLayerInsetRight(0));
   1837         assertEquals(initialLayerInsetTop, doubleDrawable.getLayerInsetTop(0));
   1838         assertEquals(initialLayerInsetBottom, doubleDrawable.getLayerInsetBottom(0));
   1839         assertEquals(initialLayerWidth, doubleDrawable.getLayerWidth(0));
   1840         assertEquals(initialLayerHeight, doubleDrawable.getLayerHeight(0));
   1841     }
   1842 
   1843     @Test
   1844     public void testOpacityChange() {
   1845         ColorDrawable c1 = new ColorDrawable(Color.RED);
   1846         ColorDrawable c2 = new ColorDrawable(Color.BLUE);
   1847         LayerDrawable dr = new LayerDrawable(new ColorDrawable[] { c1, c2 });
   1848         assertEquals(PixelFormat.OPAQUE, dr.getOpacity());
   1849 
   1850         c1.setTint(0x80FF0000);
   1851         c1.setTintMode(PorterDuff.Mode.SRC);
   1852         c2.setTint(0x800000FF);
   1853         c2.setTintMode(PorterDuff.Mode.SRC);
   1854         assertEquals(PixelFormat.TRANSLUCENT, dr.getOpacity());
   1855     }
   1856 
   1857     @Test
   1858     public void testStatefulnessChange() {
   1859         ColorDrawable c1 = new ColorDrawable(Color.RED);
   1860         ColorDrawable c2 = new ColorDrawable(Color.BLUE);
   1861         LayerDrawable dr = new LayerDrawable(new ColorDrawable[] { c1, c2 });
   1862         assertEquals(false, dr.isStateful());
   1863 
   1864         ColorStateList csl = new ColorStateList(
   1865                 new int[][] { { android.R.attr.state_enabled }, { } },
   1866                 new int[] { Color.RED, Color.BLUE });
   1867         c1.setTintList(csl);
   1868         assertEquals(true, dr.isStateful());
   1869     }
   1870 
   1871     @Test
   1872     public void testInvalidateDuringInit() {
   1873         Drawable layer = new RippleDrawable(ColorStateList.valueOf(Color.BLACK), null, null);
   1874 
   1875         LayerDrawable orig = new LayerDrawable(new Drawable[] { layer });
   1876         orig.setBounds(0, 0, 100, 100);
   1877 
   1878         // This will invoke the layer's invalidateSelf() during construction.
   1879         LayerDrawable copy = (LayerDrawable) orig.getConstantState().newDrawable();
   1880         assertNotSame(orig, copy);
   1881     }
   1882 
   1883     private static class IntrinsicSizeDrawable extends Drawable {
   1884         private final int mIntrinsicWidth;
   1885         private final int mIntrinsicHeight;
   1886         private final Rect mPadding;
   1887 
   1888         public IntrinsicSizeDrawable(int intrinsicWidth, int intrinsicHeight, Rect padding) {
   1889             mIntrinsicWidth = intrinsicWidth;
   1890             mIntrinsicHeight = intrinsicHeight;
   1891             mPadding = new Rect(padding);
   1892         }
   1893 
   1894         @Override
   1895         public boolean getPadding(Rect padding) {
   1896             padding.set(mPadding);
   1897             return true;
   1898         }
   1899 
   1900         @Override
   1901         public int getIntrinsicHeight() {
   1902             return mIntrinsicHeight;
   1903         }
   1904 
   1905         @Override
   1906         public int getIntrinsicWidth() {
   1907             return mIntrinsicWidth;
   1908         }
   1909 
   1910         @Override
   1911         public void draw(Canvas canvas) {
   1912         }
   1913 
   1914         @Override
   1915         public void setAlpha(int alpha) {
   1916         }
   1917 
   1918         @Override
   1919         public void setColorFilter(ColorFilter colorFilter) {
   1920         }
   1921 
   1922         @Override
   1923         public int getOpacity() {
   1924             return 0;
   1925         }
   1926     }
   1927 }
   1928