Merge change 5599 into donut

* changes:
  Integrate unsubmitted cupcake change 131116: 	CTS: add test cases for graphics.drawable.BitmapDrawable, LayerDrawable, PaintDrawable, PictureDrawable, RotateDrawable and ScaleDrawable
diff --git a/tests/res/drawable/layerdrawable.xml b/tests/res/drawable/layerdrawable.xml
new file mode 100644
index 0000000..521703b
--- /dev/null
+++ b/tests/res/drawable/layerdrawable.xml
@@ -0,0 +1,21 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+ * Copyright (C) 2009 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ -->
+
+<layer-list xmlns:android="http://schemas.android.com/apk/res/android">
+    <item android:drawable="@drawable/testimage"/>
+    <item android:drawable="@drawable/start"/>
+</layer-list>
diff --git a/tests/res/drawable/paintdrawable_attr.xml b/tests/res/drawable/paintdrawable_attr.xml
new file mode 100644
index 0000000..444e5e2
--- /dev/null
+++ b/tests/res/drawable/paintdrawable_attr.xml
@@ -0,0 +1,42 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+ * Copyright (C) 2008 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+ -->
+<shape  xmlns:android="http://schemas.android.com/apk/res/android"
+        android:shape="rectangle">
+
+        <solid
+            android:color="#00000000"/>
+
+        <stroke
+            android:width="2dp"
+            android:color="#ff000000"/>
+
+        <padding
+            android:paddingLeft="1dp"
+            android:paddingRight="10dp"
+            android:paddingTop="1dp"
+            android:paddingBottom="10dp"/>
+
+        <corners
+            android:radius="9dp"
+            android:bottomRightRadius="8dp"
+            android:bottomLeftRadius="8dp"
+            android:topLeftRadius="0.5dp"
+            android:topRightRadius="0.5dp"/>
+
+</shape>
+
diff --git a/tests/res/drawable/rotatedrawable.xml b/tests/res/drawable/rotatedrawable.xml
new file mode 100644
index 0000000..b9b2cfe
--- /dev/null
+++ b/tests/res/drawable/rotatedrawable.xml
@@ -0,0 +1,22 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+ * Copyright (C) 2009 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ -->
+
+<rotate xmlns:android="http://schemas.android.com/apk/res/android"
+    android:pivotX="50%" android:pivotY="50%"
+    android:fromDegrees="0" android:toDegrees="360"
+    android:drawable="@drawable/testimage"/>
+
diff --git a/tests/res/drawable/scaledrawable.xml b/tests/res/drawable/scaledrawable.xml
new file mode 100644
index 0000000..7e65dce
--- /dev/null
+++ b/tests/res/drawable/scaledrawable.xml
@@ -0,0 +1,23 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+ * Copyright (C) 2009 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ -->
+
+<scale xmlns:android="http://schemas.android.com/apk/res/android"
+    android:fromXScale="1.0"
+    android:toXScale="1.4"
+    android:fromYScale="1.0"
+    android:toYScale="0.6"
+    android:drawable="@drawable/testimage"/>
diff --git a/tests/res/drawable/window_test_drawable.xml b/tests/res/drawable/window_test_drawable.xml
new file mode 100644
index 0000000..4281cd8
--- /dev/null
+++ b/tests/res/drawable/window_test_drawable.xml
@@ -0,0 +1,23 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+ * Copyright (C) 2009 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ -->
+
+<shape xmlns:android="http://schemas.android.com/apk/res/android">
+    <solid android:color="#00000000"/>
+    <stroke android:width="2dp" android:color="#ff000000"/>
+    <padding android:left="1dp" android:top="1dp"
+            android:right="1dp" android:bottom="1dp" />
+</shape>
diff --git a/tests/res/values/ids.xml b/tests/res/values/ids.xml
new file mode 100644
index 0000000..30e081b
--- /dev/null
+++ b/tests/res/values/ids.xml
@@ -0,0 +1,18 @@
+<!-- Copyright (C) 2008 The Android Open Source Project
+
+     Licensed under the Apache License, Version 2.0 (the "License");
+     you may not use this file except in compliance with the License.
+     You may obtain a copy of the License at
+
+          http://www.apache.org/licenses/LICENSE-2.0
+
+     Unless required by applicable law or agreed to in writing, software
+     distributed under the License is distributed on an "AS IS" BASIS,
+     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+     See the License for the specific language governing permissions and
+     limitations under the License.
+-->
+
+<resources>
+  <item type="id" name="background" />
+</resources>
diff --git a/tests/res/xml/bitmapdrawable.xml b/tests/res/xml/bitmapdrawable.xml
new file mode 100644
index 0000000..f9001aa
--- /dev/null
+++ b/tests/res/xml/bitmapdrawable.xml
@@ -0,0 +1,40 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+ * Copyright (C) 2008 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ -->
+<alias xmlns:android="http://schemas.android.com/apk/res/android">
+    <bitmap_allattrs>
+        <bitmap android:src="@drawable/testimage"
+            android:gravity="top|right"
+            android:dither="true"
+            android:antialias="true"
+            android:filter="false"
+            android:tileMode="repeat"/>
+    </bitmap_allattrs>
+
+    <bitmap_partattrs>
+        <bitmap android:src="@drawable/size_48x48"
+            android:gravity="center"
+            android:tileMode="mirror"/>
+    </bitmap_partattrs>
+
+    <bitmap_wrongsrc>
+        <bitmap android:src="@drawable/colorstatelist_test"/>
+    </bitmap_wrongsrc>
+
+    <bitmap_nosrc>
+        <bitmap android:gravity="center"/>
+    </bitmap_nosrc>
+</alias>
diff --git a/tests/res/xml/layerdrawable.xml b/tests/res/xml/layerdrawable.xml
new file mode 100644
index 0000000..9bb1268
--- /dev/null
+++ b/tests/res/xml/layerdrawable.xml
@@ -0,0 +1,48 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+ * Copyright (C) 2008 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ -->
+<alias xmlns:android="http://schemas.android.com/apk/res/android">
+    <layer-list_full>
+        <layer-list>
+            <item><color android:color="#88ffffff">
+                <padding android:left="1px" android:top="2px" android:right="3px"
+                    android:bottom="4px"/>
+            </color></item>
+            <item android:drawable="@drawable/testimage"/>
+            <item>
+                <rotate
+                    android:pivotX="50%" android:pivotY="50%"
+                    android:fromDegrees="0" android:toDegrees="360"
+                    android:drawable="@drawable/testimage"/>
+                <padding android:left="4px" android:top="3px"
+                    android:right="2px" android:bottom="1px" />
+            </item>
+            <bitmap android:src="@drawable/testimage"/>
+            <item android:id="@id/background"
+                android:drawable="@drawable/window_test_drawable" />
+        </layer-list>
+    </layer-list_full>
+    <layer-list_empty>
+        <layer-list>
+            <bitmap android:src="@drawable/testimage"/>
+        </layer-list>
+    </layer-list_empty>
+    <layer-list_exception>
+        <layer-list>
+            <item android:id="@id/background"/>
+        </layer-list>
+    </layer-list_exception>
+</alias>
diff --git a/tests/res/xml/scaledrawable.xml b/tests/res/xml/scaledrawable.xml
new file mode 100644
index 0000000..d8d5f73
--- /dev/null
+++ b/tests/res/xml/scaledrawable.xml
@@ -0,0 +1,35 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+ * Copyright (C) 2008 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ -->
+<alias xmlns:android="http://schemas.android.com/apk/res/android">
+    <scale_allattrs>
+        <scale
+            android:scaleWidth="0.4"
+            android:scaleHeight="0.3"
+            android:scaleGravity="center"
+            android:drawable="@drawable/testimage">
+            <color android:color="#88ffffff"/>
+            <bitmap android:src="@drawable/size_48x48"/>
+        </scale>
+    </scale_allattrs>
+
+    <scale_nodrawable>
+        <scale
+            android:scaleWidth="0.7"
+            android:scaleHeight="0.3"
+            android:scaleGravity="center"/>
+    </scale_nodrawable>
+</alias>
diff --git a/tests/src/android/graphics/drawable/cts/DrawableTestUtils.java b/tests/src/android/graphics/drawable/cts/DrawableTestUtils.java
new file mode 100644
index 0000000..8745bd3
--- /dev/null
+++ b/tests/src/android/graphics/drawable/cts/DrawableTestUtils.java
@@ -0,0 +1,79 @@
+/*
+ * Copyright (C) 2008 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.graphics.drawable.cts;
+
+import android.content.res.XmlResourceParser;
+import android.util.AttributeSet;
+import android.util.Xml;
+
+import java.io.IOException;
+
+import com.android.internal.util.XmlUtils;
+
+import org.xmlpull.v1.XmlPullParser;
+import org.xmlpull.v1.XmlPullParserException;
+
+/**
+ * The useful methods for graphics.drawable test.
+ */
+public class DrawableTestUtils {
+    /**
+     * Retrieve an AttributeSet from a XML.
+     *
+     * @param parser the XmlPullParser to use for the xml parsing.
+     * @param searchedNodeName the name of the target node.
+     * @return the AttributeSet retrieved from specified node.
+     * @throws IOException
+     * @throws XmlPullParserException
+     */
+    public static AttributeSet getAttributeSet(XmlResourceParser parser, String searchedNodeName)
+            throws XmlPullParserException, IOException {
+        AttributeSet attrs = null;
+        int type;
+        while ((type = parser.next()) != XmlPullParser.END_DOCUMENT
+                && type != XmlPullParser.START_TAG) {
+        }
+        String nodeName = parser.getName();
+        if (!"alias".equals(nodeName)) {
+            throw new RuntimeException();
+        }
+        int outerDepth = parser.getDepth();
+        while ((type = parser.next()) != XmlPullParser.END_DOCUMENT
+                && (type != XmlPullParser.END_TAG || parser.getDepth() > outerDepth)) {
+            if (type == XmlPullParser.END_TAG || type == XmlPullParser.TEXT) {
+                continue;
+            }
+            nodeName = parser.getName();
+            if (searchedNodeName.equals(nodeName)) {
+                outerDepth = parser.getDepth();
+                while ((type = parser.next()) != XmlPullParser.END_DOCUMENT
+                        && (type != XmlPullParser.END_TAG || parser.getDepth() > outerDepth)) {
+                    if (type == XmlPullParser.END_TAG || type == XmlPullParser.TEXT) {
+                        continue;
+                    }
+                    nodeName = parser.getName();
+                    attrs = Xml.asAttributeSet(parser);
+                    break;
+                }
+                break;
+            } else {
+                XmlUtils.skipCurrentTag(parser);
+            }
+        }
+        return attrs;
+    }
+}
diff --git a/tests/tests/graphics/src/android/graphics/drawable/cts/BitmapDrawableTest.java b/tests/tests/graphics/src/android/graphics/drawable/cts/BitmapDrawableTest.java
new file mode 100644
index 0000000..2b8df75
--- /dev/null
+++ b/tests/tests/graphics/src/android/graphics/drawable/cts/BitmapDrawableTest.java
@@ -0,0 +1,525 @@
+/*
+ * Copyright (C) 2008 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.graphics.drawable.cts;
+
+import com.android.cts.stub.R;
+
+import dalvik.annotation.TestLevel;
+import dalvik.annotation.TestTargetClass;
+import dalvik.annotation.TestTargetNew;
+import dalvik.annotation.TestTargets;
+import dalvik.annotation.ToBeFixed;
+
+import org.xmlpull.v1.XmlPullParserException;
+
+import android.content.Context;
+import android.content.res.Resources;
+import android.content.res.XmlResourceParser;
+import android.graphics.Bitmap;
+import android.graphics.Canvas;
+import android.graphics.ColorFilter;
+import android.graphics.Paint;
+import android.graphics.PixelFormat;
+import android.graphics.Shader;
+import android.graphics.Bitmap.Config;
+import android.graphics.Shader.TileMode;
+import android.graphics.drawable.BitmapDrawable;
+import android.graphics.drawable.Drawable.ConstantState;
+import android.test.InstrumentationTestCase;
+import android.util.AttributeSet;
+import android.view.Gravity;
+
+import java.io.ByteArrayInputStream;
+import java.io.IOException;
+import java.io.InputStream;
+
+@TestTargetClass(android.graphics.drawable.BitmapDrawable.class)
+public class BitmapDrawableTest extends InstrumentationTestCase {
+    // The target context.
+    private Context mContext;
+
+    @Override
+    protected void setUp() throws Exception {
+        super.setUp();
+        mContext = getInstrumentation().getTargetContext();
+    }
+
+    @TestTargets({
+        @TestTargetNew(
+            level = TestLevel.COMPLETE,
+            method = "BitmapDrawable",
+            args = {}
+        ),
+        @TestTargetNew(
+            level = TestLevel.COMPLETE,
+            method = "BitmapDrawable",
+            args = {android.graphics.Bitmap.class}
+        ),
+        @TestTargetNew(
+            level = TestLevel.COMPLETE,
+            method = "BitmapDrawable",
+            args = {java.lang.String.class}
+        ),
+        @TestTargetNew(
+            level = TestLevel.COMPLETE,
+            method = "BitmapDrawable",
+            args = {java.io.InputStream.class}
+        ),
+        @TestTargetNew(
+            level = TestLevel.COMPLETE,
+            method = "getPaint",
+            args = {}
+        ),
+        @TestTargetNew(
+            level = TestLevel.COMPLETE,
+            method = "getBitmap",
+            args = {}
+        )
+    })
+    public void testConstructor() {
+        BitmapDrawable bitmapDrawable = new BitmapDrawable();
+        assertNotNull(bitmapDrawable.getPaint());
+        assertEquals(Paint.FILTER_BITMAP_FLAG | Paint.DEV_KERN_TEXT_FLAG,
+                bitmapDrawable.getPaint().getFlags());
+        assertNull(bitmapDrawable.getBitmap());
+
+        Bitmap bitmap = Bitmap.createBitmap(200, 300, Config.ARGB_8888);
+        bitmapDrawable = new BitmapDrawable(bitmap);
+        assertNotNull(bitmapDrawable.getPaint());
+        assertEquals(Paint.FILTER_BITMAP_FLAG | Paint.DEV_KERN_TEXT_FLAG,
+                bitmapDrawable.getPaint().getFlags());
+        assertEquals(bitmap, bitmapDrawable.getBitmap());
+
+        new BitmapDrawable(mContext.getFilesDir().getPath());
+
+        new BitmapDrawable(new ByteArrayInputStream("test constructor".getBytes()));
+
+        // exceptional test
+        new BitmapDrawable((Bitmap) null);
+
+        new BitmapDrawable((String) null);
+
+        new BitmapDrawable((InputStream) null);
+    }
+
+    @TestTargets({
+        @TestTargetNew(
+            level = TestLevel.COMPLETE,
+            method = "getGravity",
+            args = {}
+        ),
+        @TestTargetNew(
+            level = TestLevel.COMPLETE,
+            method = "setGravity",
+            args = {int.class}
+        )
+    })
+    public void testAccessGravity() {
+        InputStream source = mContext.getResources().openRawResource(R.raw.testimage);
+        BitmapDrawable bitmapDrawable = new BitmapDrawable(source);
+
+        assertEquals(Gravity.FILL, bitmapDrawable.getGravity());
+
+        bitmapDrawable.setGravity(Gravity.CENTER);
+        assertEquals(Gravity.CENTER, bitmapDrawable.getGravity());
+
+        bitmapDrawable.setGravity(-1);
+        assertEquals(-1, bitmapDrawable.getGravity());
+
+        bitmapDrawable.setGravity(Integer.MAX_VALUE);
+        assertEquals(Integer.MAX_VALUE, bitmapDrawable.getGravity());
+    }
+
+    @TestTargetNew(
+        level = TestLevel.COMPLETE,
+        method = "setAntiAlias",
+        args = {boolean.class}
+    )
+    public void testSetAntiAlias() {
+        InputStream source = mContext.getResources().openRawResource(R.raw.testimage);
+        BitmapDrawable bitmapDrawable = new BitmapDrawable(source);
+
+        assertFalse(bitmapDrawable.getPaint().isAntiAlias());
+
+        bitmapDrawable.setAntiAlias(true);
+        assertTrue(bitmapDrawable.getPaint().isAntiAlias());
+
+        bitmapDrawable.setAntiAlias(false);
+        assertFalse(bitmapDrawable.getPaint().isAntiAlias());
+    }
+
+    @TestTargetNew(
+        level = TestLevel.COMPLETE,
+        method = "setFilterBitmap",
+        args = {boolean.class}
+    )
+    public void testSetFilterBitmap() {
+        InputStream source = mContext.getResources().openRawResource(R.raw.testimage);
+        BitmapDrawable bitmapDrawable = new BitmapDrawable(source);
+
+        assertTrue(bitmapDrawable.getPaint().isFilterBitmap());
+
+        bitmapDrawable.setFilterBitmap(false);
+        assertFalse(bitmapDrawable.getPaint().isFilterBitmap());
+
+        bitmapDrawable.setFilterBitmap(true);
+        assertTrue(bitmapDrawable.getPaint().isFilterBitmap());
+    }
+
+    @TestTargetNew(
+        level = TestLevel.COMPLETE,
+        method = "setDither",
+        args = {boolean.class}
+    )
+    public void testSetDither() {
+        InputStream source = mContext.getResources().openRawResource(R.raw.testimage);
+        BitmapDrawable bitmapDrawable = new BitmapDrawable(source);
+
+        assertFalse(bitmapDrawable.getPaint().isDither());
+
+        bitmapDrawable.setDither(true);
+        assertTrue(bitmapDrawable.getPaint().isDither());
+
+        bitmapDrawable.setDither(false);
+        assertFalse(bitmapDrawable.getPaint().isDither());
+    }
+
+    @TestTargets({
+        @TestTargetNew(
+            level = TestLevel.COMPLETE,
+            method = "getTileModeX",
+            args = {}
+        ),
+        @TestTargetNew(
+            level = TestLevel.COMPLETE,
+            method = "getTileModeY",
+            args = {}
+        ),
+        @TestTargetNew(
+            level = TestLevel.COMPLETE,
+            method = "setTileModeX",
+            args = {android.graphics.Shader.TileMode.class}
+        ),
+        @TestTargetNew(
+            level = TestLevel.COMPLETE,
+            method = "setTileModeY",
+            args = {android.graphics.Shader.TileMode.class}
+        ),
+        @TestTargetNew(
+            level = TestLevel.COMPLETE,
+            method = "setTileModeXY",
+            args = {android.graphics.Shader.TileMode.class, android.graphics.Shader.TileMode.class}
+        )
+    })
+    public void testAccessTileMode() {
+        InputStream source = mContext.getResources().openRawResource(R.raw.testimage);
+        BitmapDrawable bitmapDrawable = new BitmapDrawable(source);
+
+        assertNull(bitmapDrawable.getTileModeX());
+        assertNull(bitmapDrawable.getTileModeY());
+        assertNull(bitmapDrawable.getPaint().getShader());
+
+        bitmapDrawable.setTileModeX(TileMode.CLAMP);
+        assertEquals(TileMode.CLAMP, bitmapDrawable.getTileModeX());
+        assertNull(bitmapDrawable.getTileModeY());
+
+        bitmapDrawable.draw(new Canvas());
+        assertNotNull(bitmapDrawable.getPaint().getShader());
+        Shader oldShader = bitmapDrawable.getPaint().getShader();
+
+        bitmapDrawable.setTileModeY(TileMode.REPEAT);
+        assertEquals(TileMode.CLAMP, bitmapDrawable.getTileModeX());
+        assertEquals(TileMode.REPEAT, bitmapDrawable.getTileModeY());
+
+        bitmapDrawable.draw(new Canvas());
+        assertNotSame(oldShader, bitmapDrawable.getPaint().getShader());
+        oldShader = bitmapDrawable.getPaint().getShader();
+
+        bitmapDrawable.setTileModeXY(TileMode.REPEAT, TileMode.MIRROR);
+        assertEquals(TileMode.REPEAT, bitmapDrawable.getTileModeX());
+        assertEquals(TileMode.MIRROR, bitmapDrawable.getTileModeY());
+
+        bitmapDrawable.draw(new Canvas());
+        assertNotSame(oldShader, bitmapDrawable.getPaint().getShader());
+        oldShader = bitmapDrawable.getPaint().getShader();
+
+        bitmapDrawable.setTileModeX(TileMode.MIRROR);
+        assertEquals(TileMode.MIRROR, bitmapDrawable.getTileModeX());
+        assertEquals(TileMode.MIRROR, bitmapDrawable.getTileModeY());
+
+        bitmapDrawable.draw(new Canvas());
+        assertNotSame(oldShader, bitmapDrawable.getPaint().getShader());
+    }
+
+    @TestTargetNew(
+        level = TestLevel.COMPLETE,
+        method = "getChangingConfigurations",
+        args = {}
+    )
+    public void testGetChangingConfigurations() {
+        InputStream source = mContext.getResources().openRawResource(R.raw.testimage);
+        BitmapDrawable bitmapDrawable = new BitmapDrawable(source);
+
+        assertEquals(0, bitmapDrawable.getChangingConfigurations());
+
+        bitmapDrawable.setChangingConfigurations(1);
+        assertEquals(1, bitmapDrawable.getChangingConfigurations());
+
+        bitmapDrawable.setChangingConfigurations(2);
+        assertEquals(2, bitmapDrawable.getChangingConfigurations());
+    }
+
+    @TestTargetNew(
+        level = TestLevel.NOT_NECESSARY,
+        method = "onBoundsChange",
+        args = {android.graphics.Rect.class}
+    )
+    public void testOnBoundsChange() {
+        // Do not test this API. it is callbacks which:
+        // 1. The callback machanism has been tested in super class
+        // 2. The functionality is implmentation details, no need to test
+    }
+
+    @TestTargetNew(
+        level = TestLevel.COMPLETE,
+        method = "setAlpha",
+        args = {int.class}
+    )
+    public void testSetAlpha() {
+        InputStream source = mContext.getResources().openRawResource(R.raw.testimage);
+        BitmapDrawable bitmapDrawable = new BitmapDrawable(source);
+
+        assertEquals(255, bitmapDrawable.getPaint().getAlpha());
+
+        bitmapDrawable.setAlpha(0);
+        assertEquals(0, bitmapDrawable.getPaint().getAlpha());
+
+        bitmapDrawable.setAlpha(100);
+        assertEquals(100, bitmapDrawable.getPaint().getAlpha());
+
+        // exceptional test
+        bitmapDrawable.setAlpha(-1);
+        assertEquals(255, bitmapDrawable.getPaint().getAlpha());
+
+        bitmapDrawable.setAlpha(256);
+        assertEquals(0, bitmapDrawable.getPaint().getAlpha());
+    }
+
+    @TestTargetNew(
+        level = TestLevel.COMPLETE,
+        method = "setColorFilter",
+        args = {android.graphics.ColorFilter.class}
+    )
+    public void testSetColorFilter() {
+        InputStream source = mContext.getResources().openRawResource(R.raw.testimage);
+        BitmapDrawable bitmapDrawable = new BitmapDrawable(source);
+
+        assertNull(bitmapDrawable.getPaint().getColorFilter());
+
+        ColorFilter colorFilter = new ColorFilter();
+        bitmapDrawable.setColorFilter(colorFilter);
+        assertSame(colorFilter, bitmapDrawable.getPaint().getColorFilter());
+
+        bitmapDrawable.setColorFilter(null);
+        assertNull(bitmapDrawable.getPaint().getColorFilter());
+    }
+
+    @TestTargetNew(
+        level = TestLevel.COMPLETE,
+        method = "getOpacity",
+        args = {}
+    )
+    public void testGetOpacity() {
+        BitmapDrawable bitmapDrawable = new BitmapDrawable();
+        assertEquals(Gravity.FILL, bitmapDrawable.getGravity());
+        assertEquals(PixelFormat.TRANSLUCENT, bitmapDrawable.getOpacity());
+
+        InputStream source = mContext.getResources().openRawResource(R.raw.testimage);
+        bitmapDrawable = new BitmapDrawable(source);
+        assertEquals(Gravity.FILL, bitmapDrawable.getGravity());
+        assertEquals(PixelFormat.OPAQUE, bitmapDrawable.getOpacity());
+        bitmapDrawable.setGravity(Gravity.BOTTOM);
+        assertEquals(PixelFormat.TRANSLUCENT, bitmapDrawable.getOpacity());
+
+        bitmapDrawable = new BitmapDrawable(source);
+        assertEquals(Gravity.FILL, bitmapDrawable.getGravity());
+        assertEquals(PixelFormat.OPAQUE, bitmapDrawable.getOpacity());
+        bitmapDrawable.setAlpha(120);
+        assertEquals(PixelFormat.TRANSLUCENT, bitmapDrawable.getOpacity());
+    }
+
+    @TestTargetNew(
+        level = TestLevel.COMPLETE,
+        method = "getConstantState",
+        args = {}
+    )
+    public void testGetConstantState() {
+        InputStream source = mContext.getResources().openRawResource(R.raw.testimage);
+        BitmapDrawable bitmapDrawable = new BitmapDrawable(source);
+        ConstantState constantState = bitmapDrawable.getConstantState();
+        assertNotNull(constantState);
+        assertEquals(0, constantState.getChangingConfigurations());
+
+        bitmapDrawable.setChangingConfigurations(1);
+        constantState = bitmapDrawable.getConstantState();
+        assertNotNull(constantState);
+        assertEquals(1, constantState.getChangingConfigurations());
+    }
+
+    @TestTargets({
+        @TestTargetNew(
+            level = TestLevel.COMPLETE,
+            method = "getIntrinsicWidth",
+            args = {}
+        ),
+        @TestTargetNew(
+            level = TestLevel.COMPLETE,
+            method = "getIntrinsicHeight",
+            args = {}
+        )
+    })
+    public void testGetIntrinsicSize() {
+        BitmapDrawable bitmapDrawable = new BitmapDrawable();
+        assertEquals(0, bitmapDrawable.getIntrinsicWidth());
+        assertEquals(0, bitmapDrawable.getIntrinsicHeight());
+
+        Bitmap bitmap = Bitmap.createBitmap(200, 300, Config.RGB_565);
+        bitmapDrawable = new BitmapDrawable(bitmap);
+        assertEquals(200, bitmapDrawable.getIntrinsicWidth());
+        assertEquals(300, bitmapDrawable.getIntrinsicHeight());
+
+        InputStream source = mContext.getResources().openRawResource(R.drawable.size_48x48);
+        bitmapDrawable = new BitmapDrawable(source);
+        assertEquals(48, bitmapDrawable.getIntrinsicWidth());
+        assertEquals(48, bitmapDrawable.getIntrinsicHeight());
+    }
+
+    @TestTargetNew(
+        level = TestLevel.COMPLETE,
+        method = "inflate",
+        args = {android.content.res.Resources.class, org.xmlpull.v1.XmlPullParser.class,
+                android.util.AttributeSet.class}
+    )
+    @ToBeFixed(bug = "1695243", explanation = "the javadoc for draw() is incomplete." +
+            "1. not clear what is supposed to happen if the Resource is null.")
+    public void testInflate() throws IOException, XmlPullParserException {
+        BitmapDrawable bitmapDrawable = new BitmapDrawable();
+
+        XmlResourceParser parser = mContext.getResources().getXml(R.xml.bitmapdrawable);
+        AttributeSet attrs = DrawableTestUtils.getAttributeSet(
+                mContext.getResources().getXml(R.xml.bitmapdrawable), "bitmap_allattrs");
+        bitmapDrawable.inflate(mContext.getResources(), parser, attrs);
+        assertEquals(Gravity.TOP | Gravity.RIGHT, bitmapDrawable.getGravity());
+        assertTrue(bitmapDrawable.getPaint().isDither());
+        assertTrue(bitmapDrawable.getPaint().isAntiAlias());
+        assertFalse(bitmapDrawable.getPaint().isFilterBitmap());
+        assertEquals(TileMode.REPEAT, bitmapDrawable.getTileModeX());
+        assertEquals(TileMode.REPEAT, bitmapDrawable.getTileModeY());
+
+        bitmapDrawable = new BitmapDrawable();
+        attrs = DrawableTestUtils.getAttributeSet(
+                mContext.getResources().getXml(R.xml.bitmapdrawable), "bitmap_partattrs");
+        // when parser is null
+        bitmapDrawable.inflate(mContext.getResources(), null, attrs);
+        assertEquals(Gravity.CENTER, bitmapDrawable.getGravity());
+        assertEquals(TileMode.MIRROR, bitmapDrawable.getTileModeX());
+        assertEquals(TileMode.MIRROR, bitmapDrawable.getTileModeY());
+        // default value
+        assertFalse(bitmapDrawable.getPaint().isDither());
+        assertFalse(bitmapDrawable.getPaint().isAntiAlias());
+        assertTrue(bitmapDrawable.getPaint().isFilterBitmap());
+
+        attrs = DrawableTestUtils.getAttributeSet(
+                mContext.getResources().getXml(R.xml.bitmapdrawable), "bitmap_wrongsrc");
+        try {
+            bitmapDrawable.inflate(mContext.getResources(), parser, attrs);
+            fail("Should throw XmlPullParserException if the bitmap source can't be decoded.");
+        } catch (XmlPullParserException e) {
+        }
+
+        attrs = DrawableTestUtils.getAttributeSet(
+                mContext.getResources().getXml(R.xml.bitmapdrawable), "bitmap_nosrc");
+        try {
+            bitmapDrawable.inflate(mContext.getResources(), parser, attrs);
+            fail("Should throw XmlPullParserException if the bitmap src doesn't be defined.");
+        } catch (XmlPullParserException e) {
+        }
+
+        attrs = DrawableTestUtils.getAttributeSet(
+                mContext.getResources().getXml(R.xml.bitmapdrawable), "bitmap_allattrs");
+        try {
+            bitmapDrawable.inflate(null, parser, attrs);
+            fail("Should throw NullPointerException if resource is null");
+        } catch (NullPointerException e) {
+        }
+
+        try {
+            bitmapDrawable.inflate(mContext.getResources(), parser, null);
+            fail("Should throw NullPointerException if attribute set is null");
+        } catch (NullPointerException e) {
+        }
+    }
+
+    @TestTargetNew(
+        level = TestLevel.COMPLETE,
+        method = "draw",
+        args = {android.graphics.Canvas.class}
+    )
+    @ToBeFixed(bug = "1695243", explanation = "the javadoc for draw() is incomplete." +
+            "1. not clear what is supposed to happen if canvas is null.")
+    public void testDraw() {
+        InputStream source = mContext.getResources().openRawResource(R.raw.testimage);
+        BitmapDrawable bitmapDrawable = new BitmapDrawable(source);
+
+        // if the function draw() does not throw any exception, we think it is right.
+        bitmapDrawable.draw(new Canvas());
+
+        // input null as param
+        try {
+            bitmapDrawable.draw(null);
+            fail("Should throw NullPointerException.");
+        } catch (NullPointerException e) {
+        }
+    }
+
+    @TestTargetNew(
+        level = TestLevel.COMPLETE,
+        method = "mutate",
+        args = {}
+    )
+    public void testMutate() {
+        Resources resources = mContext.getResources();
+        BitmapDrawable d1 = (BitmapDrawable) resources.getDrawable(R.drawable.testimage);
+        BitmapDrawable d2 = (BitmapDrawable) resources.getDrawable(R.drawable.testimage);
+        BitmapDrawable d3 = (BitmapDrawable) resources.getDrawable(R.drawable.testimage);
+
+        d1.setAlpha(100);
+        assertEquals(100, d1.getPaint().getAlpha());
+        assertEquals(100, d2.getPaint().getAlpha());
+        assertEquals(100, d3.getPaint().getAlpha());
+
+        d1.mutate();
+        d1.setAlpha(200);
+        assertEquals(200, d1.getPaint().getAlpha());
+        assertEquals(100, d2.getPaint().getAlpha());
+        assertEquals(100, d3.getPaint().getAlpha());
+        d2.setAlpha(50);
+        assertEquals(200, d1.getPaint().getAlpha());
+        assertEquals(50, d2.getPaint().getAlpha());
+        assertEquals(50, d3.getPaint().getAlpha());
+    }
+}
diff --git a/tests/tests/graphics/src/android/graphics/drawable/cts/LayerDrawableTest.java b/tests/tests/graphics/src/android/graphics/drawable/cts/LayerDrawableTest.java
new file mode 100644
index 0000000..184d90f
--- /dev/null
+++ b/tests/tests/graphics/src/android/graphics/drawable/cts/LayerDrawableTest.java
@@ -0,0 +1,1067 @@
+/*
+ * Copyright (C) 2008 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.graphics.drawable.cts;
+
+import com.android.cts.stub.R;
+
+import dalvik.annotation.TestLevel;
+import dalvik.annotation.TestTargetClass;
+import dalvik.annotation.TestTargetNew;
+import dalvik.annotation.TestTargets;
+import dalvik.annotation.ToBeFixed;
+
+import org.xmlpull.v1.XmlPullParserException;
+
+import android.R.attr;
+import android.content.res.Resources;
+import android.content.res.XmlResourceParser;
+import android.graphics.Canvas;
+import android.graphics.Color;
+import android.graphics.ColorFilter;
+import android.graphics.PixelFormat;
+import android.graphics.Rect;
+import android.graphics.drawable.BitmapDrawable;
+import android.graphics.drawable.ColorDrawable;
+import android.graphics.drawable.Drawable;
+import android.graphics.drawable.GradientDrawable;
+import android.graphics.drawable.LayerDrawable;
+import android.graphics.drawable.RotateDrawable;
+import android.graphics.drawable.ShapeDrawable;
+import android.graphics.drawable.StateListDrawable;
+import android.graphics.drawable.Drawable.Callback;
+import android.graphics.drawable.Drawable.ConstantState;
+import android.test.AndroidTestCase;
+import android.util.AttributeSet;
+import android.util.StateSet;
+import android.view.View;
+
+import java.io.IOException;
+
+@TestTargetClass(android.graphics.drawable.LayerDrawable.class)
+public class LayerDrawableTest extends AndroidTestCase {
+    @TestTargetNew(
+        level = TestLevel.COMPLETE,
+        method = "LayerDrawable",
+        args = {android.graphics.drawable.Drawable[].class}
+    )
+    @ToBeFixed(bug = "1695243", explanation = "the javadoc for constructor is incomplete." +
+            "1. not clear what is supposed to happen if layers is null.")
+    public void testConstructor() {
+        Drawable bitmapDrawable = new BitmapDrawable();
+        Drawable colorDrawable  = new ColorDrawable(Color.BLUE);
+        Drawable[] array = new Drawable[] { bitmapDrawable, colorDrawable };
+        LayerDrawable layerDrawable = new LayerDrawable(array);
+        assertEquals(array.length, layerDrawable.getNumberOfLayers());
+        assertSame(bitmapDrawable, layerDrawable.getDrawable(0));
+        assertSame(colorDrawable, layerDrawable.getDrawable(1));
+
+        array = new Drawable[0];
+        layerDrawable = new LayerDrawable(array);
+        assertEquals(0, layerDrawable.getNumberOfLayers());
+
+        try {
+            new LayerDrawable((Drawable[]) null);
+            fail("Should throw NullPointerException");
+        } catch (NullPointerException e) {
+        }
+    }
+
+    @TestTargetNew(
+        level = TestLevel.COMPLETE,
+        method = "inflate",
+        args = {android.content.res.Resources.class, org.xmlpull.v1.XmlPullParser.class,
+                android.util.AttributeSet.class}
+    )
+    @ToBeFixed(bug = "1695243", explanation = "the javadoc for inflate is incomplete." +
+            "1. not clear what is supposed to happen if any parameter is null.")
+    public void testInflate() throws XmlPullParserException, IOException {
+        Drawable[] array = new Drawable[0];
+        LayerDrawable layerDrawable = new LayerDrawable(array);
+
+        XmlResourceParser parser = mContext.getResources().getXml(R.xml.layerdrawable);
+        AttributeSet attrs = DrawableTestUtils.getAttributeSet(parser, "layer-list_full");
+
+        layerDrawable.inflate(mContext.getResources(), parser, attrs);
+
+        assertEquals(4, layerDrawable.getNumberOfLayers());
+        assertEquals(ColorDrawable.class, layerDrawable.getDrawable(0).getClass());
+        assertEquals(0x88, (((ColorDrawable) layerDrawable.getDrawable(0)).getAlpha()));
+        assertEquals(View.NO_ID, layerDrawable.getId(0));
+        assertEquals(BitmapDrawable.class, layerDrawable.getDrawable(1).getClass());
+        assertEquals(View.NO_ID, layerDrawable.getId(1));
+        assertEquals(212, layerDrawable.getDrawable(1).getIntrinsicWidth());
+        assertEquals(142, layerDrawable.getDrawable(1).getIntrinsicHeight());
+        assertEquals(RotateDrawable.class, layerDrawable.getDrawable(2).getClass());
+        assertEquals(View.NO_ID, layerDrawable.getId(2));
+        assertEquals(GradientDrawable.class, layerDrawable.getDrawable(3).getClass());
+        assertEquals(R.id.background, layerDrawable.getId(3));
+
+        layerDrawable = new LayerDrawable(array);
+        parser = mContext.getResources().getXml(R.xml.layerdrawable);
+        attrs = DrawableTestUtils.getAttributeSet(parser, "layer-list_empty");
+        layerDrawable.inflate(mContext.getResources(), parser, attrs);
+        assertEquals(0, layerDrawable.getNumberOfLayers());
+
+        parser = mContext.getResources().getXml(R.xml.layerdrawable);
+        attrs = DrawableTestUtils.getAttributeSet(parser, "layer-list_exception");
+        try {
+            layerDrawable.inflate(mContext.getResources(), parser, attrs);
+            fail("Should throw XmlPullParserException if neither 'drawable' attribute" +
+                    " nor child tag defining a drawable in <item> tag.");
+        } catch (XmlPullParserException e) {
+        }
+
+        try {
+            layerDrawable.inflate(null, parser, attrs);
+            fail("Should throw NullPointerException if resource is null");
+        } catch (NullPointerException e) {
+        }
+
+        try {
+            layerDrawable.inflate(mContext.getResources(), null, attrs);
+            fail("Should throw NullPointerException if parser is null");
+        } catch (NullPointerException e) {
+        }
+
+        try {
+            layerDrawable.inflate(mContext.getResources(), parser, null);
+            fail("Should throw NullPointerException if attribute set is null");
+        } catch (NullPointerException e) {
+        }
+    }
+
+    @TestTargetNew(
+        level = TestLevel.COMPLETE,
+        method = "findDrawableByLayerId",
+        args = {int.class}
+    )
+    public void testFindDrawableByLayerId() {
+        Drawable bitmapDrawable = new BitmapDrawable();
+        Drawable colorDrawable  = new ColorDrawable(Color.BLUE);
+        Drawable[] array = new Drawable[] { bitmapDrawable, colorDrawable };
+        LayerDrawable layerDrawable = new LayerDrawable(array);
+
+        layerDrawable.setId(0, 10);
+        layerDrawable.setId(1, 20);
+        assertSame(bitmapDrawable, layerDrawable.findDrawableByLayerId(10));
+        assertSame(colorDrawable, layerDrawable.findDrawableByLayerId(20));
+        assertNull(layerDrawable.findDrawableByLayerId(30));
+
+        layerDrawable.setId(0, Integer.MIN_VALUE);
+        layerDrawable.setId(1, Integer.MAX_VALUE);
+        assertSame(bitmapDrawable, layerDrawable.findDrawableByLayerId(Integer.MIN_VALUE));
+        assertSame(colorDrawable, layerDrawable.findDrawableByLayerId(Integer.MAX_VALUE));
+
+        layerDrawable.setId(0, 10);
+        layerDrawable.setId(1, 10);
+        assertSame(colorDrawable, layerDrawable.findDrawableByLayerId(10));
+        assertNull(layerDrawable.findDrawableByLayerId(30));
+    }
+
+    @TestTargets({
+        @TestTargetNew(
+            level = TestLevel.COMPLETE,
+            method = "setId",
+            args = {int.class, int.class}
+        ),
+        @TestTargetNew(
+            level = TestLevel.COMPLETE,
+            method = "getId",
+            args = {int.class}
+        )
+    })
+    @ToBeFixed(bug = "1695243", explanation = "the javadoc for setId and getId are incomplete." +
+            "1. not clear what is supposed to happen if index is exceptional.")
+    public void testAccessId() {
+        Drawable[] array = new Drawable[] { new BitmapDrawable(), new ColorDrawable(Color.BLUE) };
+        LayerDrawable layerDrawable = new LayerDrawable(array);
+
+        layerDrawable.setId(0, 10);
+        layerDrawable.setId(1, 20);
+        assertEquals(10, layerDrawable.getId(0));
+        assertEquals(20, layerDrawable.getId(1));
+
+        layerDrawable.setId(0, Integer.MIN_VALUE);
+        layerDrawable.setId(1, Integer.MAX_VALUE);
+        assertEquals(Integer.MIN_VALUE, layerDrawable.getId(0));
+        assertEquals(Integer.MAX_VALUE, layerDrawable.getId(1));
+
+        try {
+            layerDrawable.setId(-1, 20);
+            fail("Should throw IndexOutOfBoundsException");
+        } catch (IndexOutOfBoundsException e) {
+        }
+
+        try {
+            layerDrawable.setId(layerDrawable.getNumberOfLayers(), 20);
+            fail("Should throw IndexOutOfBoundsException");
+        } catch (IndexOutOfBoundsException e) {
+        }
+
+        try {
+            layerDrawable.getId(-1);
+            fail("Should throw IndexOutOfBoundsException");
+        } catch (IndexOutOfBoundsException e) {
+        }
+
+        try {
+            layerDrawable.getId(layerDrawable.getNumberOfLayers());
+            fail("Should throw IndexOutOfBoundsException");
+        } catch (IndexOutOfBoundsException e) {
+        }
+    }
+
+    @TestTargetNew(
+        level = TestLevel.COMPLETE,
+        method = "getNumberOfLayers",
+        args = {}
+    )
+    public void testGetNumberOfLayers() {
+        Drawable[] array = new Drawable[] { new BitmapDrawable(), new ColorDrawable(Color.BLUE) };
+        LayerDrawable layerDrawable = new LayerDrawable(array);
+        assertEquals(2, layerDrawable.getNumberOfLayers());
+
+        array = new Drawable[5];
+        for (int i = 0; i < 5; i++) {
+            array[i] = new BitmapDrawable();
+        }
+        layerDrawable = new LayerDrawable(array);
+        assertEquals(5, layerDrawable.getNumberOfLayers());
+
+        array = new Drawable[0];
+        layerDrawable = new LayerDrawable(array);
+        assertEquals(0, layerDrawable.getNumberOfLayers());
+    }
+
+    @TestTargets({
+        @TestTargetNew(
+            level = TestLevel.COMPLETE,
+            method = "getDrawable",
+            args = {int.class}
+        ),
+        @TestTargetNew(
+            level = TestLevel.COMPLETE,
+            method = "setDrawableByLayerId",
+            args = {int.class, android.graphics.drawable.Drawable.class}
+        )
+    })
+    @ToBeFixed(bug = "1695243", explanation = "the javadoc for getDrawable is incomplete." +
+            "1. not clear what is supposed to happen if index is exceptional.")
+    public void testAccessDrawable() {
+        Drawable bitmapDrawable = new BitmapDrawable();
+        Drawable colorDrawable  = new ColorDrawable(Color.BLUE);
+        Drawable[] array = new Drawable[] { bitmapDrawable, colorDrawable };
+        LayerDrawable layerDrawable = new LayerDrawable(array);
+        assertSame(bitmapDrawable, layerDrawable.getDrawable(0));
+        assertSame(colorDrawable, layerDrawable.getDrawable(1));
+
+        layerDrawable.setId(0, 10);
+        layerDrawable.setId(1, 20);
+        Drawable d1 = new ColorDrawable(Color.GREEN);
+        Drawable d2 = new BitmapDrawable();
+        layerDrawable.setDrawableByLayerId(10, d1);
+        layerDrawable.setDrawableByLayerId(20, d2);
+        assertEquals(d1, layerDrawable.getDrawable(0));
+        assertEquals(d2, layerDrawable.getDrawable(1));
+
+        assertFalse(layerDrawable.setDrawableByLayerId(30, d1));
+
+        layerDrawable.setDrawableByLayerId(20, null);
+        assertEquals(null, layerDrawable.getDrawable(1));
+
+        try {
+            layerDrawable.getDrawable(layerDrawable.getNumberOfLayers());
+            fail("Should throw IndexOutOfBoundsException");
+        } catch (IndexOutOfBoundsException e) {
+        }
+
+        try {
+            layerDrawable.getDrawable(-1);
+            fail("Should throw IndexOutOfBoundsException");
+        } catch (IndexOutOfBoundsException e) {
+        }
+    }
+
+    @TestTargetNew(
+        level = TestLevel.COMPLETE,
+        method = "setLayerInset",
+        args = {int.class, int.class, int.class, int.class, int.class}
+    )
+    @ToBeFixed(bug = "1695243", explanation = "the javadoc for setLayerInset is incomplete." +
+            "1. not clear what is supposed to happen if index is exceptional.")
+    public void testSetLayerInset() {
+        Drawable[] array = new Drawable[] { new BitmapDrawable(), new ColorDrawable(Color.BLUE) };
+        LayerDrawable layerDrawable = new LayerDrawable(array);
+
+        // set inset for layer 0
+        int left = 10;
+        int top = 20;
+        int right = 30;
+        int bottom = 40;
+        layerDrawable.setLayerInset(0, left, top, right, bottom);
+        assertEquals(layerDrawable.getDrawable(0).getIntrinsicWidth() + left + right,
+                layerDrawable.getIntrinsicWidth());
+        assertEquals(layerDrawable.getDrawable(0).getIntrinsicHeight() + top + bottom,
+                layerDrawable.getIntrinsicHeight());
+
+        // set bigger inset for layer 1
+        left += 10;
+        top += 10;
+        right += 10;
+        bottom += 10;
+        layerDrawable.setLayerInset(1, left, top, right, bottom);
+        assertEquals(layerDrawable.getDrawable(1).getIntrinsicWidth() + left + right,
+                layerDrawable.getIntrinsicWidth());
+        assertEquals(layerDrawable.getDrawable(1).getIntrinsicHeight() + top + bottom,
+                layerDrawable.getIntrinsicHeight());
+
+        try {
+            layerDrawable.setLayerInset(-1, left, top, right, bottom);
+            fail("Should throw IndexOutOfBoundsException");
+        } catch (IndexOutOfBoundsException e) {
+        }
+    }
+
+    @TestTargetNew(
+        level = TestLevel.COMPLETE,
+        method = "invalidateDrawable",
+        args = {android.graphics.drawable.Drawable.class}
+    )
+    public void testInvalidateDrawable() {
+        Drawable[] array = new Drawable[0];
+        LayerDrawable layerDrawable = new LayerDrawable(array);
+
+        MockCallback cb = new MockCallback();
+        layerDrawable.setCallback(cb);
+        layerDrawable.invalidateDrawable(null);
+        assertTrue(cb.hasCalledInvalidate());
+
+        cb.reset();
+        layerDrawable.invalidateDrawable(new BitmapDrawable());
+        assertTrue(cb.hasCalledInvalidate());
+
+        cb.reset();
+        layerDrawable.setCallback(null);
+        layerDrawable.invalidateDrawable(null);
+        assertFalse(cb.hasCalledInvalidate());
+    }
+
+    @TestTargetNew(
+        level = TestLevel.COMPLETE,
+        method = "scheduleDrawable",
+        args = {android.graphics.drawable.Drawable.class, java.lang.Runnable.class, long.class}
+    )
+    public void testScheduleDrawable() {
+        Drawable[] array = new Drawable[0];
+        LayerDrawable layerDrawable = new LayerDrawable(array);
+
+        MockCallback cb = new MockCallback();
+        layerDrawable.setCallback(cb);
+        layerDrawable.scheduleDrawable(null, null, 0);
+        assertTrue(cb.hasCalledSchedule());
+
+        cb.reset();
+        layerDrawable.scheduleDrawable(new BitmapDrawable(), new Runnable() {
+            public void run() {
+            }
+        }, 1000L);
+        assertTrue(cb.hasCalledSchedule());
+
+        cb.reset();
+        layerDrawable.setCallback(null);
+        layerDrawable.scheduleDrawable(null, null, 0);
+        assertFalse(cb.hasCalledSchedule());
+    }
+
+    @TestTargetNew(
+        level = TestLevel.COMPLETE,
+        method = "unscheduleDrawable",
+        args = {android.graphics.drawable.Drawable.class, java.lang.Runnable.class}
+    )
+    public void testUnscheduleDrawable() {
+        Drawable[] array = new Drawable[0];
+        LayerDrawable layerDrawable = new LayerDrawable(array);
+
+        MockCallback cb = new MockCallback();
+        layerDrawable.setCallback(cb);
+        layerDrawable.unscheduleDrawable(null, null);
+        assertTrue(cb.hasCalledUnschedule());
+
+        cb.reset();
+        layerDrawable.unscheduleDrawable(new BitmapDrawable(), new Runnable() {
+            public void run() {
+            }
+        });
+        assertTrue(cb.hasCalledUnschedule());
+
+        cb.reset();
+        layerDrawable.setCallback(null);
+        layerDrawable.unscheduleDrawable(null, null);
+        assertFalse(cb.hasCalledUnschedule());
+    }
+
+    private static class MockCallback implements Callback {
+        private boolean mCalledInvalidate;
+        private boolean mCalledSchedule;
+        private boolean mCalledUnschedule;
+
+        public void invalidateDrawable(Drawable who) {
+            mCalledInvalidate = true;
+        }
+
+        public void scheduleDrawable(Drawable who, Runnable what, long when) {
+            mCalledSchedule = true;
+        }
+
+        public void unscheduleDrawable(Drawable who, Runnable what) {
+            mCalledUnschedule = true;
+        }
+
+        public boolean hasCalledInvalidate() {
+            return mCalledInvalidate;
+        }
+
+        public boolean hasCalledSchedule() {
+            return mCalledSchedule;
+        }
+
+        public boolean hasCalledUnschedule() {
+            return mCalledUnschedule;
+        }
+
+        public void reset() {
+            mCalledInvalidate = false;
+            mCalledSchedule = false;
+            mCalledUnschedule = false;
+        }
+    }
+
+    @TestTargetNew(
+        level = TestLevel.COMPLETE,
+        method = "draw",
+        args = {android.graphics.Canvas.class}
+    )
+    public void testDraw() {
+        MockDrawable mockDrawable1 = new MockDrawable();
+        MockDrawable mockDrawable2 = new MockDrawable();
+        Drawable[] array = new Drawable[] { mockDrawable1, mockDrawable2 };
+        LayerDrawable layerDrawable = new LayerDrawable(array);
+
+        // this method will call each child's draw().
+        layerDrawable.draw(new Canvas());
+        assertTrue(mockDrawable1.hasCalledDraw());
+        assertTrue(mockDrawable2.hasCalledDraw());
+
+        mockDrawable1.reset();
+        mockDrawable2.reset();
+        layerDrawable.draw(null);
+        assertTrue(mockDrawable1.hasCalledDraw());
+        assertTrue(mockDrawable2.hasCalledDraw());
+    }
+
+    @TestTargetNew(
+        level = TestLevel.COMPLETE,
+        method = "getChangingConfigurations",
+        args = {}
+    )
+    public void testGetChangingConfigurations() {
+        final int superConfig = 1;
+        final int bitmapDrawableConfig = 2;
+        final int colorDrawableConfig = 4;
+        final int childConfig = bitmapDrawableConfig | colorDrawableConfig;
+
+        BitmapDrawable bitmapDrawable = new BitmapDrawable();
+        bitmapDrawable.setChangingConfigurations(bitmapDrawableConfig);
+        ColorDrawable colorDrawable = new ColorDrawable(Color.BLUE);
+        colorDrawable.setChangingConfigurations(colorDrawableConfig);
+        Drawable[] array = new Drawable[] { bitmapDrawable, colorDrawable };
+        LayerDrawable layerDrawable = new LayerDrawable(array);
+
+        assertEquals(childConfig, layerDrawable.getChangingConfigurations());
+
+        layerDrawable.setChangingConfigurations(superConfig);
+        assertEquals(superConfig | childConfig, layerDrawable.getChangingConfigurations());
+    }
+
+    @TestTargetNew(
+        level = TestLevel.COMPLETE,
+        method = "getPadding",
+        args = {android.graphics.Rect.class}
+    )
+    public void testGetPadding() {
+        Drawable[] array = new Drawable[] { new ShapeDrawable(), new ShapeDrawable() };
+        LayerDrawable layerDrawable = new LayerDrawable(array);
+
+        Rect rc = new Rect();
+        layerDrawable.getPadding(rc);
+        assertEquals(0, rc.left);
+        assertEquals(0, rc.top);
+        assertEquals(0, rc.right);
+        assertEquals(0, rc.bottom);
+
+        Rect padding0 = new Rect(10, 20, 30, 40);
+        ((ShapeDrawable) layerDrawable.getDrawable(0)).setPadding(padding0);
+        layerDrawable.getPadding(rc);
+        assertEquals(padding0.left, rc.left);
+        assertEquals(padding0.top, rc.top);
+        assertEquals(padding0.right, rc.right);
+        assertEquals(padding0.bottom, rc.bottom);
+
+        Rect padding1 = new Rect(20, 30, 40, 50);
+        ((ShapeDrawable) layerDrawable.getDrawable(1)).setPadding(padding1);
+        layerDrawable.getPadding(rc);
+        assertEquals(padding0.left + padding1.left, rc.left);
+        assertEquals(padding0.top + padding1.top, rc.top);
+        assertEquals(padding0.right + padding1.right, rc.right);
+        assertEquals(padding0.bottom + padding1.bottom, rc.bottom);
+    }
+
+    @TestTargetNew(
+        level = TestLevel.COMPLETE,
+        method = "setVisible",
+        args = {boolean.class, boolean.class}
+    )
+    public void testSetVisible() {
+        Drawable[] array = new Drawable[] { new BitmapDrawable(), new ColorDrawable(Color.BLUE) };
+        LayerDrawable layerDrawable = new LayerDrawable(array);
+
+        assertTrue(layerDrawable.setVisible(false, true));
+        assertFalse(layerDrawable.isVisible());
+        assertFalse(layerDrawable.getDrawable(0).isVisible());
+        assertFalse(layerDrawable.getDrawable(1).isVisible());
+
+        assertFalse(layerDrawable.setVisible(false, false));
+
+        assertTrue(layerDrawable.setVisible(true, false));
+        assertTrue(layerDrawable.isVisible());
+        assertTrue(layerDrawable.getDrawable(0).isVisible());
+        assertTrue(layerDrawable.getDrawable(1).isVisible());
+    }
+
+    @TestTargetNew(
+        level = TestLevel.COMPLETE,
+        method = "setDither",
+        args = {boolean.class}
+    )
+    public void testSetDither() {
+        MockDrawable mockDrawable1 = new MockDrawable();
+        MockDrawable mockDrawable2 = new MockDrawable();
+        Drawable[] array = new Drawable[] { mockDrawable1, mockDrawable2 };
+        LayerDrawable layerDrawable = new LayerDrawable(array);
+
+        layerDrawable.setDither(true);
+        assertTrue(mockDrawable1.hasCalledSetDither());
+        assertTrue(mockDrawable2.hasCalledSetDither());
+
+        mockDrawable1.reset();
+        mockDrawable2.reset();
+        layerDrawable.setDither(false);
+        assertTrue(mockDrawable1.hasCalledSetDither());
+        assertTrue(mockDrawable2.hasCalledSetDither());
+    }
+
+    @TestTargetNew(
+        level = TestLevel.COMPLETE,
+        method = "setAlpha",
+        args = {int.class}
+    )
+    public void testSetAlpha() {
+        MockDrawable mockDrawable1 = new MockDrawable();
+        MockDrawable mockDrawable2 = new MockDrawable();
+        Drawable[] array = new Drawable[] { mockDrawable1, mockDrawable2 };
+        LayerDrawable layerDrawable = new LayerDrawable(array);
+
+        layerDrawable.setAlpha(0);
+        assertTrue(mockDrawable1.hasCalledSetAlpha());
+        assertTrue(mockDrawable2.hasCalledSetAlpha());
+
+        mockDrawable1.reset();
+        mockDrawable2.reset();
+        layerDrawable.setAlpha(Integer.MAX_VALUE);
+        assertTrue(mockDrawable1.hasCalledSetAlpha());
+        assertTrue(mockDrawable2.hasCalledSetAlpha());
+    }
+
+    @TestTargetNew(
+        level = TestLevel.COMPLETE,
+        method = "setColorFilter",
+        args = {android.graphics.ColorFilter.class}
+    )
+    public void testSetColorFilter() {
+        MockDrawable mockDrawable1 = new MockDrawable();
+        MockDrawable mockDrawable2 = new MockDrawable();
+        Drawable[] array = new Drawable[] { mockDrawable1, mockDrawable2 };
+        LayerDrawable layerDrawable = new LayerDrawable(array);
+
+        layerDrawable.setColorFilter(new ColorFilter());
+        assertTrue(mockDrawable1.hasCalledColorFilter());
+        assertTrue(mockDrawable2.hasCalledColorFilter());
+
+        mockDrawable1.reset();
+        mockDrawable2.reset();
+        layerDrawable.setColorFilter(null);
+        assertTrue(mockDrawable1.hasCalledColorFilter());
+        assertTrue(mockDrawable2.hasCalledColorFilter());
+    }
+
+    @TestTargetNew(
+        level = TestLevel.COMPLETE,
+        method = "getOpacity",
+        args = {}
+    )
+    public void testGetOpacity() {
+        Drawable[] array = new Drawable[0];
+        LayerDrawable layerDrawable = new LayerDrawable(array);
+        assertEquals(PixelFormat.TRANSPARENT, layerDrawable.getOpacity());
+
+        MockDrawable mockDrawable1 = new MockDrawable();
+        MockDrawable mockDrawable2 = new MockDrawable();
+        array = new Drawable[] { mockDrawable1, mockDrawable2 };
+        layerDrawable = new LayerDrawable(array);
+        assertEquals(PixelFormat.OPAQUE, layerDrawable.getOpacity());
+
+        layerDrawable = new LayerDrawable(array);
+        mockDrawable2.setOpacity(PixelFormat.TRANSPARENT);
+        assertEquals(PixelFormat.TRANSPARENT, layerDrawable.getOpacity());
+
+        layerDrawable = new LayerDrawable(array);
+        mockDrawable2.setOpacity(PixelFormat.TRANSPARENT);
+        mockDrawable1.setOpacity(PixelFormat.TRANSLUCENT);
+        assertEquals(PixelFormat.TRANSLUCENT, layerDrawable.getOpacity());
+
+        layerDrawable = new LayerDrawable(array);
+        mockDrawable1.setOpacity(PixelFormat.TRANSLUCENT);
+        mockDrawable2.setOpacity(PixelFormat.UNKNOWN);
+        assertEquals(PixelFormat.UNKNOWN, layerDrawable.getOpacity());
+    }
+
+    @TestTargetNew(
+        level = TestLevel.COMPLETE,
+        method = "isStateful",
+        args = {}
+    )
+    public void testIsStateful() {
+        Drawable[] array = new Drawable[0];
+        LayerDrawable layerDrawable = new LayerDrawable(array);
+        assertFalse(layerDrawable.isStateful());
+
+        array = new Drawable[] { new BitmapDrawable(), new MockDrawable() };
+        layerDrawable = new LayerDrawable(array);
+        assertFalse(layerDrawable.isStateful());
+
+        array = new Drawable[] { new BitmapDrawable(), new StateListDrawable() };
+        layerDrawable = new LayerDrawable(array);
+        assertTrue(layerDrawable.isStateful());
+    }
+
+    @TestTargetNew(
+        level = TestLevel.COMPLETE,
+        method = "onStateChange",
+        args = {int[].class}
+    )
+    public void testOnStateChange() {
+        MockDrawable mockDrawable1 = new MockDrawable();
+        MockDrawable mockDrawable2 = new MockDrawable();
+        Drawable[] array = new Drawable[] { mockDrawable1, mockDrawable2 };
+        MockLayerDrawable layerDrawable = new MockLayerDrawable(array);
+
+        // this method will call each child's setState().
+        assertFalse(layerDrawable.onStateChange(StateSet.WILD_CARD));
+        assertTrue(mockDrawable1.hasCalledSetState());
+        assertTrue(mockDrawable2.hasCalledSetState());
+        assertTrue(layerDrawable.hasCalledOnBoundsChange());
+
+        mockDrawable1.reset();
+        mockDrawable2.reset();
+        layerDrawable.reset();
+        assertTrue(layerDrawable.onStateChange(null));
+        assertTrue(mockDrawable1.hasCalledSetState());
+        assertTrue(mockDrawable2.hasCalledSetState());
+        assertTrue(layerDrawable.hasCalledOnBoundsChange());
+
+        mockDrawable1.reset();
+        mockDrawable2.reset();
+        layerDrawable.reset();
+        assertTrue(layerDrawable.onStateChange(new int[] { attr.state_checked, attr.state_empty }));
+        assertTrue(mockDrawable1.hasCalledSetState());
+        assertTrue(mockDrawable2.hasCalledSetState());
+        assertTrue(layerDrawable.hasCalledOnBoundsChange());
+    }
+
+    @TestTargetNew(
+        level = TestLevel.COMPLETE,
+        method = "onLevelChange",
+        args = {int.class}
+    )
+    public void testOnLevelChange() {
+        MockDrawable mockDrawable1 = new MockDrawable();
+        MockDrawable mockDrawable2 = new MockDrawable();
+        Drawable[] array = new Drawable[] { mockDrawable1, mockDrawable2 };
+        MockLayerDrawable layerDrawable = new MockLayerDrawable(array);
+
+        // this method will call each child's setLevel(),
+        // but just when set a different level the child's onLevelChange will be called.
+        assertFalse(layerDrawable.onLevelChange(0));
+        assertFalse(mockDrawable1.hasCalledOnLevelChange());
+        assertFalse(mockDrawable2.hasCalledOnLevelChange());
+        assertFalse(layerDrawable.hasCalledOnBoundsChange());
+
+        mockDrawable1.reset();
+        mockDrawable2.reset();
+        layerDrawable.reset();
+        assertTrue(layerDrawable.onLevelChange(Integer.MAX_VALUE));
+        assertTrue(mockDrawable1.hasCalledOnLevelChange());
+        assertTrue(mockDrawable2.hasCalledOnLevelChange());
+        assertTrue(layerDrawable.hasCalledOnBoundsChange());
+
+        mockDrawable1.reset();
+        mockDrawable2.reset();
+        layerDrawable.reset();
+        assertTrue(layerDrawable.onLevelChange(Integer.MIN_VALUE));
+        assertTrue(mockDrawable1.hasCalledOnLevelChange());
+        assertTrue(mockDrawable2.hasCalledOnLevelChange());
+        assertTrue(layerDrawable.hasCalledOnBoundsChange());
+    }
+
+    @TestTargetNew(
+        level = TestLevel.COMPLETE,
+        method = "onBoundsChange",
+        args = {android.graphics.Rect.class}
+    )
+    public void testOnBoundsChange() {
+        MockDrawable mockDrawable1 = new MockDrawable();
+        MockDrawable mockDrawable2 = new MockDrawable();
+        Drawable[] array = new Drawable[] { mockDrawable1, mockDrawable2 };
+        MockLayerDrawable layerDrawable = new MockLayerDrawable(array);
+
+        Rect inset1 = new Rect(1, 2, 3, 4);
+        Rect inset2 = new Rect(2, 4, 6, 7);
+        Rect padding1 = new Rect(11, 22, 33, 44);
+        Rect padding2 = new Rect(21, 32, 43, 54);
+        layerDrawable.setLayerInset(0, inset1.left, inset1.top, inset1.right, inset1.bottom);
+        layerDrawable.setLayerInset(1, inset2.left, inset2.top, inset2.right, inset2.bottom);
+        mockDrawable1.setPadding(padding1);
+        mockDrawable2.setPadding(padding2);
+        layerDrawable.getPadding(new Rect());
+
+        // the children's bounds before call onBoundsChange
+        assertEquals(0, mockDrawable1.getBounds().left);
+        assertEquals(0, mockDrawable1.getBounds().top);
+        assertEquals(0, mockDrawable1.getBounds().right);
+        assertEquals(0, mockDrawable1.getBounds().bottom);
+        assertEquals(0, mockDrawable2.getBounds().left);
+        assertEquals(0, mockDrawable2.getBounds().top);
+        assertEquals(0, mockDrawable2.getBounds().right);
+        assertEquals(0, mockDrawable2.getBounds().bottom);
+
+        Rect bounds = new Rect(10, 20, 30, 40);
+        layerDrawable.onBoundsChange(bounds);
+
+        // all children's bounds will be changed after call onBoundsChange
+        assertEquals(bounds.left + inset1.left, mockDrawable1.getBounds().left);
+        assertEquals(bounds.top + inset1.top, mockDrawable1.getBounds().top);
+        assertEquals(bounds.right - inset1.right, mockDrawable1.getBounds().right);
+        assertEquals(bounds.bottom - inset1.bottom, mockDrawable1.getBounds().bottom);
+        assertEquals(bounds.left + inset2.left + padding1.left, mockDrawable2.getBounds().left);
+        assertEquals(bounds.top + inset2.top + padding1.top, mockDrawable2.getBounds().top);
+        assertEquals(bounds.right - inset2.right - padding1.right,
+                mockDrawable2.getBounds().right);
+        assertEquals(bounds.bottom - inset2.bottom - padding1.bottom,
+                mockDrawable2.getBounds().bottom);
+    }
+
+    @TestTargetNew(
+        level = TestLevel.COMPLETE,
+        method = "getIntrinsicWidth",
+        args = {}
+    )
+    public void testGetIntrinsicWidth() {
+        MockDrawable mockDrawable1 = new MockDrawable();
+        MockDrawable mockDrawable2 = new MockDrawable();
+        Drawable[] array = new Drawable[] { mockDrawable1, mockDrawable2 };
+        MockLayerDrawable layerDrawable = new MockLayerDrawable(array);
+        assertEquals(mockDrawable1.getIntrinsicWidth(), layerDrawable.getIntrinsicWidth());
+
+        Rect inset1 = new Rect(1, 2, 3, 4);
+        Rect inset2 = new Rect(2, 4, 6, 7);
+        Rect padding1 = new Rect(11, 22, 33, 44);
+        Rect padding2 = new Rect(21, 32, 43, 54);
+        layerDrawable.setLayerInset(0, inset1.left, inset1.top, inset1.right, inset1.bottom);
+        layerDrawable.setLayerInset(1, inset2.left, inset2.top, inset2.right, inset2.bottom);
+        mockDrawable1.setPadding(padding1);
+        mockDrawable2.setPadding(padding2);
+        layerDrawable.getPadding(new Rect());
+        assertEquals(mockDrawable2.getIntrinsicWidth() + inset2.left
+                + inset2.right + padding1.left + padding1.right,
+                layerDrawable.getIntrinsicWidth());
+
+        inset1 = new Rect(inset2.left + padding1.left + 1, inset2.top + padding1.top + 1,
+                inset2.right + padding1.right + 1, inset2.bottom + padding1.bottom + 1);
+        layerDrawable.setLayerInset(0, inset1.left, inset1.top, inset1.right, inset1.bottom);
+        assertEquals(mockDrawable1.getIntrinsicWidth() + inset1.left + inset1.right,
+                layerDrawable.getIntrinsicWidth());
+    }
+
+    @TestTargetNew(
+        level = TestLevel.COMPLETE,
+        method = "getIntrinsicHeight",
+        args = {}
+    )
+    public void testGetIntrinsicHeight() {
+        MockDrawable mockDrawable1 = new MockDrawable();
+        MockDrawable mockDrawable2 = new MockDrawable();
+        Drawable[] array = new Drawable[] { mockDrawable1, mockDrawable2 };
+        MockLayerDrawable layerDrawable = new MockLayerDrawable(array);
+        assertEquals(mockDrawable1.getIntrinsicHeight(), layerDrawable.getIntrinsicHeight());
+
+        Rect inset1 = new Rect(1, 2, 3, 4);
+        Rect inset2 = new Rect(2, 4, 6, 7);
+        Rect padding1 = new Rect(11, 22, 33, 44);
+        Rect padding2 = new Rect(21, 32, 43, 54);
+        layerDrawable.setLayerInset(0, inset1.left, inset1.top, inset1.right, inset1.bottom);
+        layerDrawable.setLayerInset(1, inset2.left, inset2.top, inset2.right, inset2.bottom);
+        mockDrawable1.setPadding(padding1);
+        mockDrawable2.setPadding(padding2);
+        layerDrawable.getPadding(new Rect());
+        assertEquals(mockDrawable2.getIntrinsicHeight() + inset2.top
+                + inset2.bottom + padding1.top + padding1.bottom,
+                layerDrawable.getIntrinsicHeight());
+
+        inset1 = new Rect(inset2.left + padding1.left + 1, inset2.top + padding1.top + 1,
+                inset2.right + padding1.right + 1, inset2.bottom + padding1.bottom + 1);
+        layerDrawable.setLayerInset(0, inset1.left, inset1.top, inset1.right, inset1.bottom);
+        assertEquals(mockDrawable1.getIntrinsicHeight() + inset1.top + inset1.bottom,
+                layerDrawable.getIntrinsicHeight());
+    }
+
+    @TestTargetNew(
+        level = TestLevel.COMPLETE,
+        method = "getConstantState",
+        args = {}
+    )
+    public void testGetConstantState() {
+        Drawable[] array = new Drawable[] { new BitmapDrawable(), new ColorDrawable(Color.BLUE) };
+        LayerDrawable layerDrawable = new LayerDrawable(array);
+        ConstantState constantState = layerDrawable.getConstantState();
+        assertNotNull(constantState);
+        assertEquals(0, constantState.getChangingConfigurations());
+
+        layerDrawable.setChangingConfigurations(1);
+        constantState = layerDrawable.getConstantState();
+        assertNotNull(constantState);
+        assertEquals(1, constantState.getChangingConfigurations());
+    }
+
+    private static class MockDrawable extends Drawable {
+        private boolean mCalledSetDither = false;
+        private boolean mCalledSetAlpha = false;
+        private boolean mCalledColorFilter = false;
+
+        private boolean mCalledSetState = false;
+        private boolean mCalledOnLevelChange = false;
+
+        private boolean mCalledDraw = false;
+
+        private int mOpacity = PixelFormat.OPAQUE;
+
+        Rect mPadding = null;
+
+        @Override
+        public void draw(Canvas canvas) {
+            mCalledDraw = true;
+        }
+
+        public boolean hasCalledDraw() {
+            return mCalledDraw;
+        }
+
+        @Override
+        public int getOpacity() {
+            return mOpacity;
+        }
+
+        public void setOpacity(int opacity) {
+            mOpacity = opacity;
+        }
+
+        @Override
+        public void setAlpha(int alpha) {
+            mCalledSetAlpha = true;
+        }
+
+        @Override
+        public void setColorFilter(ColorFilter cf) {
+            mCalledColorFilter = true;
+        }
+
+        @Override
+        public void setDither(boolean dither) {
+            mCalledSetDither = true;
+        }
+
+        public boolean hasCalledSetDither() {
+            return mCalledSetDither;
+        }
+
+        public boolean hasCalledSetAlpha() {
+            return mCalledSetAlpha;
+        }
+
+        public boolean hasCalledColorFilter() {
+            return mCalledColorFilter;
+        }
+
+        public void reset() {
+            mCalledSetDither = false;
+            mCalledSetAlpha = false;
+            mCalledColorFilter = false;
+
+            mCalledSetState = false;
+            mCalledOnLevelChange = false;
+
+            mCalledDraw = false;
+        }
+
+        @Override
+        protected boolean onStateChange(int[] state) {
+            return true;
+        }
+
+        private void increasePadding() {
+            Rect padding = new Rect();
+            getPadding(padding);
+            padding.left++;
+            padding.top++;
+            padding.right++;
+            padding.bottom++;
+
+            setPadding(padding);
+        }
+
+        @Override
+        protected boolean onLevelChange(int level) {
+            increasePadding();
+            mCalledOnLevelChange = true;
+            return true;
+        }
+
+        public boolean hasCalledSetState() {
+            return mCalledSetState;
+        }
+
+        public boolean setState(final int[] stateSet) {
+            increasePadding();
+            mCalledSetState = true;
+            return super.setState(stateSet);
+        }
+
+        public boolean hasCalledOnLevelChange() {
+            return mCalledOnLevelChange;
+        }
+
+        public void setPadding(Rect padding) {
+            if (padding == null) {
+                mPadding = null;
+            } else {
+                if (mPadding == null) {
+                    mPadding = new Rect();
+                }
+                mPadding.set(padding);
+            }
+        }
+
+        @Override
+        public boolean getPadding(Rect padding) {
+            if (mPadding != null) {
+                padding.set(mPadding);
+                return true;
+            } else {
+                return super.getPadding(padding);
+            }
+        }
+    }
+
+    private static class MockLayerDrawable extends LayerDrawable {
+        private boolean mCalledOnBoundsChange = false;
+
+        public MockLayerDrawable(Drawable[] array) {
+            super(array);
+        }
+
+        // override protected methods
+        @Override
+        protected boolean onStateChange(int[] state) {
+            return super.onStateChange(state);
+        }
+
+        @Override
+        protected boolean onLevelChange(int level) {
+            return super.onLevelChange(level);
+        }
+
+        @Override
+        protected void onBoundsChange(Rect bounds) {
+            mCalledOnBoundsChange = true;
+            super.onBoundsChange(bounds);
+        }
+
+        public boolean hasCalledOnBoundsChange() {
+            return mCalledOnBoundsChange;
+        }
+
+        public void reset() {
+            mCalledOnBoundsChange = false;
+        }
+    }
+
+    @TestTargetNew(
+        level = TestLevel.COMPLETE,
+        method = "mutate",
+        args = {}
+    )
+    public void testMutate() {
+        Resources resources = mContext.getResources();
+        LayerDrawable d1 = (LayerDrawable) resources.getDrawable(R.drawable.layerdrawable);
+        LayerDrawable d2 = (LayerDrawable) resources.getDrawable(R.drawable.layerdrawable);
+        LayerDrawable d3 = (LayerDrawable) resources.getDrawable(R.drawable.layerdrawable);
+
+        d1.setAlpha(100);
+        assertEquals(100, ((BitmapDrawable) d1.getDrawable(0)).getPaint().getAlpha());
+        assertEquals(100, ((BitmapDrawable) d1.getDrawable(0)).getPaint().getAlpha());
+        assertEquals(100, ((BitmapDrawable) d2.getDrawable(0)).getPaint().getAlpha());
+        assertEquals(100, ((BitmapDrawable) d2.getDrawable(0)).getPaint().getAlpha());
+        assertEquals(100, ((BitmapDrawable) d3.getDrawable(0)).getPaint().getAlpha());
+        assertEquals(100, ((BitmapDrawable) d2.getDrawable(0)).getPaint().getAlpha());
+
+        d1.mutate();
+        d1.setAlpha(200);
+        assertEquals(200, ((BitmapDrawable) d1.getDrawable(0)).getPaint().getAlpha());
+        assertEquals(200, ((BitmapDrawable) d1.getDrawable(0)).getPaint().getAlpha());
+        assertEquals(100, ((BitmapDrawable) d2.getDrawable(0)).getPaint().getAlpha());
+        assertEquals(100, ((BitmapDrawable) d2.getDrawable(0)).getPaint().getAlpha());
+        assertEquals(100, ((BitmapDrawable) d3.getDrawable(0)).getPaint().getAlpha());
+        assertEquals(100, ((BitmapDrawable) d3.getDrawable(0)).getPaint().getAlpha());
+
+        d2.setAlpha(50);
+        assertEquals(200, ((BitmapDrawable) d1.getDrawable(0)).getPaint().getAlpha());
+        assertEquals(200, ((BitmapDrawable) d1.getDrawable(0)).getPaint().getAlpha());
+        assertEquals(50, ((BitmapDrawable) d2.getDrawable(0)).getPaint().getAlpha());
+        assertEquals(50, ((BitmapDrawable) d2.getDrawable(0)).getPaint().getAlpha());
+        assertEquals(50, ((BitmapDrawable) d3.getDrawable(0)).getPaint().getAlpha());
+        assertEquals(50, ((BitmapDrawable) d3.getDrawable(0)).getPaint().getAlpha());
+    }
+}
diff --git a/tests/tests/graphics/src/android/graphics/drawable/cts/PaintDrawableTest.java b/tests/tests/graphics/src/android/graphics/drawable/cts/PaintDrawableTest.java
new file mode 100644
index 0000000..05472b2
--- /dev/null
+++ b/tests/tests/graphics/src/android/graphics/drawable/cts/PaintDrawableTest.java
@@ -0,0 +1,258 @@
+/*
+ * Copyright (C) 2008 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.graphics.drawable.cts;
+
+import com.android.cts.stub.R;
+
+import dalvik.annotation.TestLevel;
+import dalvik.annotation.TestTargetClass;
+import dalvik.annotation.TestTargetNew;
+import dalvik.annotation.TestTargets;
+import dalvik.annotation.ToBeFixed;
+
+import org.xmlpull.v1.XmlPullParser;
+import org.xmlpull.v1.XmlPullParserException;
+
+import android.content.res.Resources;
+import android.content.res.XmlResourceParser;
+import android.graphics.Rect;
+import android.graphics.drawable.PaintDrawable;
+import android.graphics.drawable.shapes.RoundRectShape;
+import android.test.AndroidTestCase;
+import android.util.AttributeSet;
+import android.util.Xml;
+
+import java.io.IOException;
+
+@TestTargetClass(android.graphics.drawable.PaintDrawable.class)
+public class PaintDrawableTest extends AndroidTestCase {
+    @TestTargets({
+        @TestTargetNew(
+            level = TestLevel.COMPLETE,
+            method = "PaintDrawable",
+            args = {}
+        ),
+        @TestTargetNew(
+            level = TestLevel.COMPLETE,
+            method = "PaintDrawable",
+            args = {int.class}
+        )
+    })
+    @ToBeFixed(bug = "1695243", explanation = "Android API javadocs are incomplete")
+    public void testConstructor() {
+        new PaintDrawable();
+        new PaintDrawable(0x0);
+        new PaintDrawable(0xffffffff);
+    }
+
+    @TestTargetNew(
+        level = TestLevel.COMPLETE,
+        method = "setCornerRadius",
+        args = {float.class}
+    )
+    public void testSetCornerRadius() {
+        PaintDrawable paintDrawable;
+
+        // Test input value with a positive float
+        // First, create a new PaintDrawable, which has no Shape
+        paintDrawable = getPaintDrawable(false);
+        assertNull(paintDrawable.getShape());
+        paintDrawable.setCornerRadius(1.5f);
+        assertNotNull(paintDrawable.getShape());
+        assertTrue(paintDrawable.getShape() instanceof RoundRectShape);
+
+        // Test input value as 0, this function will set its Shape as null
+        paintDrawable = getPaintDrawable(true);
+        assertNotNull(paintDrawable.getShape());
+        paintDrawable.setCornerRadius(0);
+        assertNull(paintDrawable.getShape());
+
+        // Test input value as negative, this function will set its Shape as null
+        paintDrawable = getPaintDrawable(true);
+        assertNotNull(paintDrawable.getShape());
+        paintDrawable.setCornerRadius(-2.5f);
+        assertNull(paintDrawable.getShape());
+    }
+
+    @TestTargetNew(
+        level = TestLevel.COMPLETE,
+        method = "setCornerRadii",
+        args = {float[].class}
+    )
+    @ToBeFixed(bug = "1695243", explanation = "Android API javadocs are incomplete")
+    public void testSetCornerRadii() {
+        PaintDrawable paintDrawable;
+
+        // Test with null
+        paintDrawable = getPaintDrawable(false);
+        assertNull(paintDrawable.getShape());
+        paintDrawable.setCornerRadii(null);
+        assertNull(paintDrawable.getShape());
+
+        // Test with a Shape
+        paintDrawable = getPaintDrawable(true);
+        assertNotNull(paintDrawable.getShape());
+        paintDrawable.setCornerRadii(null);
+        assertNull(paintDrawable.getShape());
+
+        float[] radii = {
+                4.5f, 6.0f, 4.5f, 6.0f, 4.5f, 6.0f, 4.5f, 6.0f
+        };
+        float[] fakeRadii = new float[7];
+
+        // Test the array which is shorter than 8
+        try {
+            paintDrawable.setCornerRadii(fakeRadii);
+            fail("setCornerRadii should throw a ArrayIndexOutOfBoundsException if array is"
+                    + " shorter than 8.");
+        } catch (ArrayIndexOutOfBoundsException e) {
+            // expected
+        }
+
+        // Test the function with correct input float array
+        assertNull(paintDrawable.getShape());
+        paintDrawable.setCornerRadii(radii);
+        assertNotNull(paintDrawable.getShape());
+        assertTrue(paintDrawable.getShape() instanceof RoundRectShape);
+    }
+
+    @TestTargetNew(
+        level = TestLevel.COMPLETE,
+        method = "inflateTag",
+        args = {java.lang.String.class, android.content.res.Resources.class,
+                org.xmlpull.v1.XmlPullParser.class, android.util.AttributeSet.class}
+    )
+    public void testInflateTag() throws XmlPullParserException, IOException {
+        // Test name is not 'corners', and default executing path will load super's method.
+        XmlResourceParser parser = getParser();
+        AttributeSet attr = getAtrributeSet(parser);
+        assertNotNull(attr);
+        gotoTag(parser, "padding");
+        Rect padding = new Rect(0, 0, 10, 10);
+        MyPaintDrawable paintDrawable = new MyPaintDrawable();
+        // set mPadding not null
+        paintDrawable.setPadding(padding);
+        assertTrue(paintDrawable.getPadding(padding));
+        //If the Tagname is not 'corners',inflateTag will invoke its super's version. and the super
+        // version is a operation on mPadding, in this case, it will set mPadding to null, and
+        // return false by getPadding.
+        assertTrue(paintDrawable.inflateTag("padding", getContext().getResources(), parser, attr));
+        assertFalse(paintDrawable.getPadding(padding));
+
+        // Test tag-name with ''
+        parser = getParser();
+        attr = getAtrributeSet(parser);
+        assertNotNull(attr);
+        assertFalse(new MyPaintDrawable().inflateTag("", getContext().getResources(), parser,
+                attr));
+
+        // Exceptional input Tests
+        try {
+            // null tag name
+            new MyPaintDrawable().inflateTag(null, getContext().getResources(), parser, attr);
+            fail("Normally the function would throw a NullPointerException here.");
+        } catch (NullPointerException e) {
+            // expected
+        }
+
+        try {
+            // null Resources
+            gotoTag(parser, "padding");
+            new MyPaintDrawable().inflateTag("padding", null, parser, attr);
+            fail("Normally the function would throw a NullPointerException here.");
+        } catch (NullPointerException e) {
+            // expected
+        }
+
+        // null XmlPullParser
+        parser = getParser();
+        attr = getAtrributeSet(parser);
+        assertNotNull(attr);
+        gotoTag(parser, "padding");
+        paintDrawable = new MyPaintDrawable();
+        assertTrue(paintDrawable.inflateTag("padding", getContext().getResources(), null, attr));
+
+        try {
+            // null AttributeSet
+            new MyPaintDrawable().inflateTag("padding", getContext().getResources(), parser, null);
+            fail("Normally the function would throw a NullPointerException here.");
+        } catch (NullPointerException e) {
+            // expected
+        }
+
+        assertNull(paintDrawable.getShape());
+
+        parser = getParser();
+        attr = getAtrributeSet(parser);
+        assertNotNull(attr);
+        gotoTag(parser, "corners");
+        assertTrue(paintDrawable.inflateTag("corners", getContext().getResources(), parser, attr));
+        assertNotNull(paintDrawable.getShape());
+    }
+
+    private XmlResourceParser getParser() {
+        return getContext().getResources().getXml(R.drawable.paintdrawable_attr);
+    }
+
+    private AttributeSet getAtrributeSet(XmlResourceParser parser) throws XmlPullParserException,
+            IOException {
+        int type;
+        // FIXME: this come from
+        // com.android.internal.util.XmlUtils.beginDocument. It's better put
+        // it up as a utility method of CTS test cases.
+        type = parser.next();
+        while (type != XmlPullParser.START_TAG && type != XmlPullParser.END_DOCUMENT) {
+            type = parser.next();
+        }
+        if (type != XmlPullParser.START_TAG) {
+            return null;
+        }
+
+        return Xml.asAttributeSet(parser);
+    }
+
+    private void gotoTag(XmlResourceParser parser, String tagName) throws XmlPullParserException,
+            IOException {
+        if (parser == null) {
+            return;
+        }
+
+        while (parser.nextTag() != XmlPullParser.END_TAG) {
+            String name = parser.getName();
+            if (name.equals(tagName)) {
+                break;
+            }
+            parser.nextText();
+        }
+    }
+
+    private static class MyPaintDrawable extends PaintDrawable {
+        @Override
+        protected boolean inflateTag(String name, Resources r, XmlPullParser parser,
+                AttributeSet attrs) {
+            return super.inflateTag(name, r, parser, attrs);
+        }
+    }
+
+    private PaintDrawable getPaintDrawable(boolean hasShape) {
+        PaintDrawable paintDrawable = new PaintDrawable();
+        if (hasShape) {
+            paintDrawable.setCornerRadius(1.5f);
+        }
+        return paintDrawable;
+    }
+}
diff --git a/tests/tests/graphics/src/android/graphics/drawable/cts/PictureDrawableTest.java b/tests/tests/graphics/src/android/graphics/drawable/cts/PictureDrawableTest.java
new file mode 100644
index 0000000..9c261b3
--- /dev/null
+++ b/tests/tests/graphics/src/android/graphics/drawable/cts/PictureDrawableTest.java
@@ -0,0 +1,179 @@
+/*
+ * Copyright (C) 2008 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.graphics.drawable.cts;
+
+import dalvik.annotation.TestLevel;
+import dalvik.annotation.TestTargetClass;
+import dalvik.annotation.TestTargetNew;
+import dalvik.annotation.TestTargets;
+
+import android.graphics.Bitmap;
+import android.graphics.Canvas;
+import android.graphics.ColorFilter;
+import android.graphics.Picture;
+import android.graphics.PixelFormat;
+import android.graphics.drawable.PictureDrawable;
+import android.test.AndroidTestCase;
+
+@TestTargetClass(android.graphics.drawable.PictureDrawable.class)
+public class PictureDrawableTest extends AndroidTestCase {
+    @TestTargetNew(
+        level = TestLevel.COMPLETE,
+        method = "PictureDrawable",
+        args = {android.graphics.Picture.class}
+    )
+    public void testConstructor() {
+        assertNull((new PictureDrawable(null)).getPicture());
+        assertNotNull((new PictureDrawable(new Picture())).getPicture());
+    }
+
+    @TestTargetNew(
+        level = TestLevel.COMPLETE,
+        method = "draw",
+        args = {android.graphics.Canvas.class}
+    )
+    public void testDraw() {
+        PictureDrawable pictureDrawable = new PictureDrawable(null);
+
+        // Create Picture for drawing
+        Picture picture = new Picture();
+        Canvas recodingCanvas = picture.beginRecording(100, 200);
+        recodingCanvas.drawARGB(255, 0xa, 0xc, 0xb);
+        picture.endRecording();
+        pictureDrawable.setPicture(picture);
+        pictureDrawable.setBounds(0, 0, 100, 200);
+
+        // Create drawable bitmap for rendering into
+        Bitmap destBitmap = Bitmap.createBitmap(100, 200, Bitmap.Config.ARGB_8888);
+        // Set of drawing routines
+        Canvas canvas = new Canvas(destBitmap);
+        assertEquals(100, canvas.getClipBounds().width());
+        assertEquals(200, canvas.getClipBounds().height());
+        canvas.drawARGB(255, 0x0f, 0x0b, 0x0c);
+
+        // Check the color has been set.
+        assertEquals(0xff0f0b0c, destBitmap.getPixel(10, 10));
+        pictureDrawable.draw(canvas);
+        // Check the target pixle's color, ensure it has been changed.
+        assertEquals(0xff0a0c0b, destBitmap.getPixel(10, 10));
+    }
+
+    @TestTargets({
+        @TestTargetNew(
+            level = TestLevel.COMPLETE,
+            method = "getIntrinsicWidth",
+            args = {}
+        ),
+        @TestTargetNew(
+            level = TestLevel.COMPLETE,
+            method = "getIntrinsicHeight",
+            args = {}
+        )
+    })
+    public void testGetIntrinsicSize() {
+        PictureDrawable pictureDrawable = new PictureDrawable(null);
+        // Test with null Picture object
+        assertEquals(-1, pictureDrawable.getIntrinsicWidth());
+        assertEquals(-1, pictureDrawable.getIntrinsicHeight());
+
+        Picture picture = new Picture();
+        picture.beginRecording(99, 101);
+        // Test with Picture object
+        pictureDrawable.setPicture(picture);
+        assertEquals(99, pictureDrawable.getIntrinsicWidth());
+        assertEquals(101, pictureDrawable.getIntrinsicHeight());
+    }
+
+    @TestTargetNew(
+        level = TestLevel.COMPLETE,
+        method = "getOpacity",
+        args = {}
+    )
+    public void testGetOpacity() {
+        PictureDrawable pictureDrawable = new PictureDrawable(null);
+        assertEquals(PixelFormat.TRANSLUCENT, pictureDrawable.getOpacity());
+    }
+
+    @TestTargetNew(
+        level = TestLevel.COMPLETE,
+        method = "setAlpha",
+        args = {int.class}
+    )
+    public void testSetAlpha() {
+        PictureDrawable pictureDrawable = new PictureDrawable(null);
+        pictureDrawable.setAlpha(0);
+    }
+
+    @TestTargetNew(
+        level = TestLevel.COMPLETE,
+        method = "setColorFilter",
+        args = {android.graphics.ColorFilter.class}
+    )
+    public void testSetColorFilter() {
+        PictureDrawable pictureDrawable = new PictureDrawable(null);
+
+        ColorFilter colorFilter = new ColorFilter();
+        pictureDrawable.setColorFilter(colorFilter);
+    }
+
+    @TestTargetNew(
+        level = TestLevel.COMPLETE,
+        method = "setDither",
+        args = {boolean.class}
+    )
+    public void testSetDither() {
+        PictureDrawable pictureDrawable = new PictureDrawable(null);
+        pictureDrawable.setDither(true);
+    }
+
+    @TestTargetNew(
+        level = TestLevel.COMPLETE,
+        method = "setFilterBitmap",
+        args = {boolean.class}
+    )
+    public void testSetFilterBitmap() {
+        PictureDrawable pictureDrawable = new PictureDrawable(null);
+        pictureDrawable.setFilterBitmap(true);
+    }
+
+    @TestTargets({
+        @TestTargetNew(
+            level = TestLevel.COMPLETE,
+            method = "getPicture",
+            args = {}
+        ),
+        @TestTargetNew(
+            level = TestLevel.COMPLETE,
+            method = "setPicture",
+            args = {android.graphics.Picture.class}
+        )
+    })
+    public void testAccessPicture() {
+        PictureDrawable pictureDrawable = new PictureDrawable(null);
+        assertNull(pictureDrawable.getPicture());
+
+        // Test with real picture object.
+        Picture picture = new Picture();
+        pictureDrawable.setPicture(picture);
+        assertNotNull(pictureDrawable.getPicture());
+        assertEquals(picture, pictureDrawable.getPicture());
+
+        // Test with null input.
+        pictureDrawable.setPicture(null);
+        assertNull(pictureDrawable.getPicture());
+    }
+}
diff --git a/tests/tests/graphics/src/android/graphics/drawable/cts/RotateDrawableTest.java b/tests/tests/graphics/src/android/graphics/drawable/cts/RotateDrawableTest.java
new file mode 100644
index 0000000..97bc210
--- /dev/null
+++ b/tests/tests/graphics/src/android/graphics/drawable/cts/RotateDrawableTest.java
@@ -0,0 +1,390 @@
+/*
+ * Copyright (C) 2008 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.graphics.drawable.cts;
+
+import com.android.cts.stub.R;
+
+import dalvik.annotation.TestLevel;
+import dalvik.annotation.TestTargetClass;
+import dalvik.annotation.TestTargetNew;
+import dalvik.annotation.TestTargets;
+import dalvik.annotation.ToBeFixed;
+
+import org.xmlpull.v1.XmlPullParser;
+import org.xmlpull.v1.XmlPullParserException;
+
+import android.content.res.Configuration;
+import android.content.res.Resources;
+import android.graphics.Canvas;
+import android.graphics.ColorFilter;
+import android.graphics.PixelFormat;
+import android.graphics.Rect;
+import android.graphics.drawable.BitmapDrawable;
+import android.graphics.drawable.Drawable;
+import android.graphics.drawable.RotateDrawable;
+import android.graphics.drawable.Drawable.Callback;
+import android.graphics.drawable.Drawable.ConstantState;
+import android.test.AndroidTestCase;
+import android.util.AttributeSet;
+import android.util.Xml;
+
+import java.io.IOException;
+
+@TestTargetClass(android.graphics.drawable.RotateDrawable.class)
+public class RotateDrawableTest extends AndroidTestCase {
+    private RotateDrawable mRotateDrawable;
+
+    @Override
+    protected void setUp() throws Exception {
+        super.setUp();
+
+        Resources resources = mContext.getResources();
+        mRotateDrawable = (RotateDrawable) resources.getDrawable(R.drawable.rotatedrawable);
+    }
+
+    @TestTargetNew(
+        level = TestLevel.COMPLETE,
+        method = "RotateDrawable",
+        args = {}
+    )
+    public void testConstructor() {
+        new RotateDrawable();
+    }
+
+    @TestTargetNew(
+        level = TestLevel.SUFFICIENT,
+        method = "draw",
+        args = {android.graphics.Canvas.class}
+    )
+    public void testDraw() {
+        Canvas canvas = new Canvas();
+        mRotateDrawable.draw(canvas);
+    }
+
+    @TestTargetNew(
+        level = TestLevel.COMPLETE,
+        method = "getChangingConfigurations",
+        args = {}
+    )
+    public void testGetChangingConfigurations() {
+        assertEquals(0, mRotateDrawable.getChangingConfigurations());
+
+        mRotateDrawable.setChangingConfigurations(Configuration.KEYBOARD_NOKEYS);
+        assertEquals(Configuration.KEYBOARD_NOKEYS, mRotateDrawable.getChangingConfigurations());
+
+        mRotateDrawable.setChangingConfigurations(Configuration.KEYBOARD_12KEY);
+        assertEquals(Configuration.KEYBOARD_12KEY, mRotateDrawable.getChangingConfigurations());
+    }
+
+    @TestTargetNew(
+        level = TestLevel.COMPLETE,
+        method = "setAlpha",
+        args = {int.class}
+    )
+    public void testSetAlpha() {
+        mRotateDrawable.setAlpha(100);
+        assertEquals(100, ((BitmapDrawable) mRotateDrawable.getDrawable()).getPaint().getAlpha());
+
+        mRotateDrawable.setAlpha(255);
+        assertEquals(255, ((BitmapDrawable) mRotateDrawable.getDrawable()).getPaint().getAlpha());
+    }
+
+    @TestTargetNew(
+        level = TestLevel.COMPLETE,
+        method = "setColorFilter",
+        args = {android.graphics.ColorFilter.class}
+    )
+    public void testSetColorFilter() {
+        ColorFilter filter = new ColorFilter();
+        mRotateDrawable.setColorFilter(filter);
+        assertSame(filter,
+                ((BitmapDrawable) mRotateDrawable.getDrawable()).getPaint().getColorFilter());
+
+        mRotateDrawable.setColorFilter(null);
+        assertNull(((BitmapDrawable) mRotateDrawable.getDrawable()).getPaint().getColorFilter());
+    }
+
+    @TestTargetNew(
+        level = TestLevel.COMPLETE,
+        method = "getOpacity",
+        args = {}
+    )
+    public void testGetOpacity() {
+        assertEquals(PixelFormat.OPAQUE, mRotateDrawable.getOpacity());
+    }
+
+    @TestTargetNew(
+        level = TestLevel.COMPLETE,
+        method = "invalidateDrawable",
+        args = {android.graphics.drawable.Drawable.class}
+    )
+    public void testInvalidateDrawable() {
+        Drawable drawable = mContext.getResources().getDrawable(R.drawable.pass);
+        MockCallback callback = new MockCallback();
+
+        mRotateDrawable.setCallback(callback);
+        mRotateDrawable.invalidateDrawable(null);
+        assertTrue(callback.hasCalledInvalidate());
+
+        callback.reset();
+        mRotateDrawable.invalidateDrawable(drawable);
+        assertTrue(callback.hasCalledInvalidate());
+
+        callback.reset();
+        mRotateDrawable.setCallback(null);
+        mRotateDrawable.invalidateDrawable(drawable);
+        assertFalse(callback.hasCalledInvalidate());
+    }
+
+    @TestTargetNew(
+        level = TestLevel.COMPLETE,
+        method = "scheduleDrawable",
+        args = {android.graphics.drawable.Drawable.class, java.lang.Runnable.class, long.class}
+    )
+    public void testScheduleDrawable() {
+        MockCallback callback = new MockCallback();
+
+        mRotateDrawable.setCallback(callback);
+        mRotateDrawable.scheduleDrawable(null, null, 0);
+        assertTrue(callback.hasCalledSchedule());
+
+        callback.reset();
+        mRotateDrawable.scheduleDrawable(new BitmapDrawable(), new Runnable() {
+            public void run() {
+            }
+        }, 1000L);
+        assertTrue(callback.hasCalledSchedule());
+
+        callback.reset();
+        mRotateDrawable.setCallback(null);
+        mRotateDrawable.scheduleDrawable(null, null, 0);
+        assertFalse(callback.hasCalledSchedule());
+    }
+
+    @TestTargetNew(
+        level = TestLevel.COMPLETE,
+        method = "unscheduleDrawable",
+        args = {android.graphics.drawable.Drawable.class, java.lang.Runnable.class}
+    )
+    public void testUnscheduleDrawable() {
+        MockCallback callback = new MockCallback();
+
+        mRotateDrawable.setCallback(callback);
+        mRotateDrawable.unscheduleDrawable(null, null);
+        assertTrue(callback.hasCalledUnschedule());
+
+        callback.reset();
+        mRotateDrawable.unscheduleDrawable(new BitmapDrawable(), new Runnable() {
+            public void run() {
+            }
+        });
+        assertTrue(callback.hasCalledUnschedule());
+
+        callback.reset();
+        mRotateDrawable.setCallback(null);
+        mRotateDrawable.unscheduleDrawable(null, null);
+        assertFalse(callback.hasCalledUnschedule());
+    }
+
+    @TestTargetNew(
+        level = TestLevel.COMPLETE,
+        method = "getPadding",
+        args = {android.graphics.Rect.class}
+    )
+    public void testGetPadding() {
+        Rect rect = new Rect();
+        assertFalse(mRotateDrawable.getPadding(rect));
+        assertEquals(0, rect.left);
+        assertEquals(0, rect.top);
+        assertEquals(0, rect.right);
+        assertEquals(0, rect.bottom);
+    }
+
+    @TestTargetNew(
+        level = TestLevel.COMPLETE,
+        method = "setVisible",
+        args = {boolean.class, boolean.class}
+    )
+    public void testSetVisible() {
+        assertTrue(mRotateDrawable.isVisible());
+
+        assertTrue(mRotateDrawable.setVisible(false, false));
+        assertFalse(mRotateDrawable.isVisible());
+
+        assertFalse(mRotateDrawable.setVisible(false, true));
+        assertFalse(mRotateDrawable.isVisible());
+
+        assertTrue(mRotateDrawable.setVisible(true, false));
+        assertTrue(mRotateDrawable.isVisible());
+    }
+
+    @TestTargetNew(
+        level = TestLevel.COMPLETE,
+        method = "isStateful",
+        args = {}
+    )
+    public void testIsStateful() {
+        assertFalse(mRotateDrawable.isStateful());
+    }
+
+    @TestTargets({
+        @TestTargetNew(
+            level = TestLevel.NOT_FEASIBLE,
+            method = "onStateChange",
+            args = {int[].class}
+        ),
+        @TestTargetNew(
+            level = TestLevel.NOT_FEASIBLE,
+            method = "onLevelChange",
+            args = {int.class}
+        ),
+        @TestTargetNew(
+            level = TestLevel.NOT_FEASIBLE,
+            method = "onBoundsChange",
+            args = {android.graphics.Rect.class}
+        )
+    })
+    public void testMethods() {
+        // implementation details, do not test.
+    }
+
+    @TestTargets({
+        @TestTargetNew(
+            level = TestLevel.COMPLETE,
+            method = "getIntrinsicWidth",
+            args = {}
+        ),
+        @TestTargetNew(
+            level = TestLevel.COMPLETE,
+            method = "getIntrinsicHeight",
+            args = {}
+        ),
+        @TestTargetNew(
+            level = TestLevel.COMPLETE,
+            method = "inflate",
+            args = {android.content.res.Resources.class, org.xmlpull.v1.XmlPullParser.class,
+                    android.util.AttributeSet.class}
+        )
+    })
+    public void testGetIntrinsicWidthAndHeight() throws XmlPullParserException, IOException {
+        // testimage is set in res/drawable/rotatedrawable.xml
+        Drawable drawable = mContext.getResources().getDrawable(R.drawable.testimage);
+        assertEquals(drawable.getIntrinsicWidth(), mRotateDrawable.getIntrinsicWidth());
+        assertEquals(drawable.getIntrinsicHeight(), mRotateDrawable.getIntrinsicHeight());
+
+        RotateDrawable rotateDrawable = new RotateDrawable();
+        Resources r = mContext.getResources();
+        XmlPullParser parser = r.getXml(R.drawable.rotatedrawable);
+        while (parser.next() != XmlPullParser.START_TAG) {
+            // ignore event, just seek to first tag
+        }
+        AttributeSet attrs = Xml.asAttributeSet(parser);
+        rotateDrawable.inflate(r, parser, attrs);
+        assertEquals(drawable.getIntrinsicWidth(), rotateDrawable.getIntrinsicWidth());
+        assertEquals(drawable.getIntrinsicHeight(), rotateDrawable.getIntrinsicHeight());
+
+        try {
+            mRotateDrawable.inflate(null, null, null);
+            fail("did not throw NullPointerException when parameters are null.");
+        } catch (NullPointerException e) {
+            // expected, test success
+        }
+    }
+
+    @TestTargetNew(
+        level = TestLevel.COMPLETE,
+        method = "getConstantState",
+        args = {}
+    )
+    @ToBeFixed(bug = "1695243", explanation = "Android API javadocs are incomplete")
+    public void testGetConstantState() {
+        ConstantState state = mRotateDrawable.getConstantState();
+        assertNotNull(state);
+    }
+
+    @TestTargets({
+        @TestTargetNew(
+            level = TestLevel.COMPLETE,
+            method = "mutate",
+            args = {}
+        ),
+        @TestTargetNew(
+            level = TestLevel.COMPLETE,
+            method = "getDrawable",
+            args = {}
+        )
+    })
+    public void testMutate() {
+        Resources resources = mContext.getResources();
+
+        RotateDrawable d1 = (RotateDrawable) resources.getDrawable(R.drawable.rotatedrawable);
+        RotateDrawable d2 = (RotateDrawable) resources.getDrawable(R.drawable.rotatedrawable);
+        RotateDrawable d3 = (RotateDrawable) resources.getDrawable(R.drawable.rotatedrawable);
+
+        d1.setAlpha(100);
+        assertEquals(100, ((BitmapDrawable) d1.getDrawable()).getPaint().getAlpha());
+        assertEquals(100, ((BitmapDrawable) d2.getDrawable()).getPaint().getAlpha());
+        assertEquals(100, ((BitmapDrawable) d3.getDrawable()).getPaint().getAlpha());
+
+        d1.mutate();
+        d1.setAlpha(200);
+        assertEquals(200, ((BitmapDrawable) d1.getDrawable()).getPaint().getAlpha());
+        assertEquals(100, ((BitmapDrawable) d2.getDrawable()).getPaint().getAlpha());
+        assertEquals(100, ((BitmapDrawable) d3.getDrawable()).getPaint().getAlpha());
+
+        d2.setAlpha(50);
+        assertEquals(200, ((BitmapDrawable) d1.getDrawable()).getPaint().getAlpha());
+        assertEquals(50, ((BitmapDrawable) d2.getDrawable()).getPaint().getAlpha());
+        assertEquals(50, ((BitmapDrawable) d3.getDrawable()).getPaint().getAlpha());
+    }
+
+    private static class MockCallback implements Callback {
+        private boolean mCalledInvalidate;
+        private boolean mCalledSchedule;
+        private boolean mCalledUnschedule;
+
+        public void invalidateDrawable(Drawable who) {
+            mCalledInvalidate = true;
+        }
+
+        public void scheduleDrawable(Drawable who, Runnable what, long when) {
+            mCalledSchedule = true;
+        }
+
+        public void unscheduleDrawable(Drawable who, Runnable what) {
+            mCalledUnschedule = true;
+        }
+
+        public boolean hasCalledInvalidate() {
+            return mCalledInvalidate;
+        }
+
+        public boolean hasCalledSchedule() {
+            return mCalledSchedule;
+        }
+
+        public boolean hasCalledUnschedule() {
+            return mCalledUnschedule;
+        }
+
+        public void reset() {
+            mCalledInvalidate = false;
+            mCalledSchedule = false;
+            mCalledUnschedule = false;
+        }
+    }
+}
diff --git a/tests/tests/graphics/src/android/graphics/drawable/cts/ScaleDrawableTest.java b/tests/tests/graphics/src/android/graphics/drawable/cts/ScaleDrawableTest.java
new file mode 100644
index 0000000..1aa5f13
--- /dev/null
+++ b/tests/tests/graphics/src/android/graphics/drawable/cts/ScaleDrawableTest.java
@@ -0,0 +1,740 @@
+/*
+ * Copyright (C) 2008 The Android Open Source Project.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.graphics.drawable.cts;
+
+import com.android.cts.stub.R;
+
+import dalvik.annotation.TestLevel;
+import dalvik.annotation.TestTargetClass;
+import dalvik.annotation.TestTargetNew;
+import dalvik.annotation.TestTargets;
+import dalvik.annotation.ToBeFixed;
+
+import org.xmlpull.v1.XmlPullParserException;
+
+import android.content.res.Resources;
+import android.content.res.XmlResourceParser;
+import android.graphics.Canvas;
+import android.graphics.ColorFilter;
+import android.graphics.Rect;
+import android.graphics.drawable.BitmapDrawable;
+import android.graphics.drawable.Drawable;
+import android.graphics.drawable.ScaleDrawable;
+import android.graphics.drawable.Drawable.Callback;
+import android.graphics.drawable.Drawable.ConstantState;
+import android.test.AndroidTestCase;
+import android.util.AttributeSet;
+import android.util.StateSet;
+import android.view.Gravity;
+
+import java.io.IOException;
+
+@TestTargetClass(android.graphics.drawable.ScaleDrawable.class)
+public class ScaleDrawableTest extends AndroidTestCase {
+
+    @TestTargets({
+        @TestTargetNew(
+            level = TestLevel.COMPLETE,
+            method = "ScaleDrawable",
+            args = {android.graphics.drawable.Drawable.class, int.class, float.class, float.class}
+        ),
+        @TestTargetNew(
+            level = TestLevel.COMPLETE,
+            method = "getDrawable",
+            args = {}
+        )
+    })
+    public void testConstructor() {
+        Drawable d = new BitmapDrawable();
+        ScaleDrawable scaleDrawable = new ScaleDrawable(d, Gravity.CENTER, 100, 200);
+        assertSame(d, scaleDrawable.getDrawable());
+
+        new ScaleDrawable(null, -1, Float.MAX_VALUE, Float.MIN_VALUE);
+    }
+
+    @TestTargetNew(
+        level = TestLevel.COMPLETE,
+        method = "invalidateDrawable",
+        args = {android.graphics.drawable.Drawable.class}
+    )
+    public void testInvalidateDrawable() {
+        ScaleDrawable scaleDrawable = new ScaleDrawable(new BitmapDrawable(),
+                Gravity.CENTER, 100, 200);
+
+        MockCallback cb = new MockCallback();
+        scaleDrawable.setCallback(cb);
+        scaleDrawable.invalidateDrawable(null);
+        assertTrue(cb.hasCalledInvalidate());
+
+        cb.reset();
+        scaleDrawable.invalidateDrawable(new BitmapDrawable());
+        assertTrue(cb.hasCalledInvalidate());
+
+        cb.reset();
+        scaleDrawable.setCallback(null);
+        scaleDrawable.invalidateDrawable(null);
+        assertFalse(cb.hasCalledInvalidate());
+    }
+
+    @TestTargetNew(
+        level = TestLevel.COMPLETE,
+        method = "scheduleDrawable",
+        args = {android.graphics.drawable.Drawable.class, java.lang.Runnable.class, long.class}
+    )
+    public void testScheduleDrawable() {
+        ScaleDrawable scaleDrawable = new ScaleDrawable(new BitmapDrawable(),
+                Gravity.CENTER, 100, 200);
+
+        MockCallback cb = new MockCallback();
+        scaleDrawable.setCallback(cb);
+        scaleDrawable.scheduleDrawable(null, null, 0);
+        assertTrue(cb.hasCalledSchedule());
+
+        cb.reset();
+        scaleDrawable.scheduleDrawable(new BitmapDrawable(), new Runnable() {
+            public void run() {
+            }
+        }, 1000L);
+        assertTrue(cb.hasCalledSchedule());
+
+        cb.reset();
+        scaleDrawable.setCallback(null);
+        scaleDrawable.scheduleDrawable(null, null, 0);
+        assertFalse(cb.hasCalledSchedule());
+    }
+
+    @TestTargetNew(
+        level = TestLevel.COMPLETE,
+        method = "unscheduleDrawable",
+        args = {android.graphics.drawable.Drawable.class, java.lang.Runnable.class}
+    )
+    public void testUnscheduleDrawable() {
+        ScaleDrawable scaleDrawable = new ScaleDrawable(new BitmapDrawable(),
+                Gravity.CENTER, 100, 200);
+
+        MockCallback cb = new MockCallback();
+        scaleDrawable.setCallback(cb);
+        scaleDrawable.unscheduleDrawable(null, null);
+        assertTrue(cb.hasCalledUnschedule());
+
+        cb.reset();
+        scaleDrawable.unscheduleDrawable(new BitmapDrawable(), new Runnable() {
+            public void run() {
+            }
+        });
+        assertTrue(cb.hasCalledUnschedule());
+
+        cb.reset();
+        scaleDrawable.setCallback(null);
+        scaleDrawable.unscheduleDrawable(null, null);
+        assertFalse(cb.hasCalledUnschedule());
+    }
+
+    private static class MockCallback implements Callback {
+        private boolean mCalledInvalidate;
+        private boolean mCalledSchedule;
+        private boolean mCalledUnschedule;
+
+        public void invalidateDrawable(Drawable who) {
+            mCalledInvalidate = true;
+        }
+
+        public void scheduleDrawable(Drawable who, Runnable what, long when) {
+            mCalledSchedule = true;
+        }
+
+        public void unscheduleDrawable(Drawable who, Runnable what) {
+            mCalledUnschedule = true;
+        }
+
+        public boolean hasCalledInvalidate() {
+            return mCalledInvalidate;
+        }
+
+        public boolean hasCalledSchedule() {
+            return mCalledSchedule;
+        }
+
+        public boolean hasCalledUnschedule() {
+            return mCalledUnschedule;
+        }
+
+        public void reset() {
+            mCalledInvalidate = false;
+            mCalledSchedule = false;
+            mCalledUnschedule = false;
+        }
+    }
+
+    @TestTargetNew(
+        level = TestLevel.COMPLETE,
+        method = "draw",
+        args = {android.graphics.Canvas.class}
+    )
+    public void testDraw() {
+        MockDrawable mockDrawable = new MockDrawable();
+        ScaleDrawable scaleDrawable = new ScaleDrawable(mockDrawable, Gravity.CENTER, 100, 200);
+
+        scaleDrawable.draw(new Canvas());
+        assertFalse(mockDrawable.hasCalledDraw());
+
+        // this method will call the contained drawable's draw method
+        // if the contained drawable's level doesn't equal 0.
+        mockDrawable.setLevel(1);
+        scaleDrawable.draw(new Canvas());
+        assertTrue(mockDrawable.hasCalledDraw());
+
+        mockDrawable.reset();
+        scaleDrawable.draw(null);
+        assertTrue(mockDrawable.hasCalledDraw());
+    }
+
+    @TestTargetNew(
+        level = TestLevel.COMPLETE,
+        method = "getChangingConfigurations",
+        args = {}
+    )
+    public void testGetChangingConfigurations() {
+        final int SUPER_CONFIG = 1;
+        final int CONTAINED_DRAWABLE_CONFIG = 2;
+
+        MockDrawable mockDrawable = new MockDrawable();
+        ScaleDrawable scaleDrawable = new ScaleDrawable(mockDrawable, Gravity.CENTER, 100, 200);
+
+        assertEquals(0, scaleDrawable.getChangingConfigurations());
+
+        mockDrawable.setChangingConfigurations(CONTAINED_DRAWABLE_CONFIG);
+        assertEquals(CONTAINED_DRAWABLE_CONFIG, scaleDrawable.getChangingConfigurations());
+
+        scaleDrawable.setChangingConfigurations(SUPER_CONFIG);
+        assertEquals(SUPER_CONFIG | CONTAINED_DRAWABLE_CONFIG,
+                scaleDrawable.getChangingConfigurations());
+    }
+
+    @TestTargetNew(
+        level = TestLevel.COMPLETE,
+        method = "getPadding",
+        args = {android.graphics.Rect.class}
+    )
+    @ToBeFixed(bug = "1695243", explanation = "the javadoc for getPadding is incomplete." +
+            "1. not clear what is supposed to happen if padding is null.")
+    public void testGetPadding() {
+        MockDrawable mockDrawable = new MockDrawable();
+        ScaleDrawable scaleDrawable = new ScaleDrawable(mockDrawable, Gravity.CENTER, 100, 200);
+
+        // this method will call contained drawable's getPadding method.
+        scaleDrawable.getPadding(new Rect());
+        assertTrue(mockDrawable.hasCalledGetPadding());
+
+        // input null as param
+        try {
+            scaleDrawable.getPadding(null);
+            fail("Should throw NullPointerException");
+        } catch (NullPointerException e) {
+        }
+    }
+
+    @TestTargetNew(
+        level = TestLevel.COMPLETE,
+        method = "setVisible",
+        args = {boolean.class, boolean.class}
+    )
+    public void testSetVisible() {
+        MockDrawable mockDrawable = new MockDrawable();
+        ScaleDrawable scaleDrawable = new ScaleDrawable(mockDrawable, Gravity.CENTER, 100, 200);
+        assertTrue(scaleDrawable.isVisible());
+
+        assertTrue(scaleDrawable.setVisible(false, false));
+        assertFalse(scaleDrawable.isVisible());
+        assertTrue(mockDrawable.hasCalledSetVisible());
+
+        mockDrawable.reset();
+        assertFalse(scaleDrawable.setVisible(false, false));
+        assertFalse(scaleDrawable.isVisible());
+        assertTrue(mockDrawable.hasCalledSetVisible());
+
+        mockDrawable.reset();
+        assertTrue(scaleDrawable.setVisible(true, false));
+        assertTrue(scaleDrawable.isVisible());
+        assertTrue(mockDrawable.hasCalledSetVisible());
+    }
+
+    @TestTargetNew(
+        level = TestLevel.COMPLETE,
+        method = "setAlpha",
+        args = {int.class}
+    )
+    public void testSetAlpha() {
+        MockDrawable mockDrawable = new MockDrawable();
+        ScaleDrawable scaleDrawable = new ScaleDrawable(mockDrawable, Gravity.CENTER, 100, 200);
+
+        // this method will call contained drawable's setAlpha method.
+        scaleDrawable.setAlpha(100);
+        assertTrue(mockDrawable.hasCalledSetAlpha());
+
+        mockDrawable.reset();
+        scaleDrawable.setAlpha(Integer.MAX_VALUE);
+        assertTrue(mockDrawable.hasCalledSetAlpha());
+
+        mockDrawable.reset();
+        scaleDrawable.setAlpha(-1);
+        assertTrue(mockDrawable.hasCalledSetAlpha());
+    }
+
+    @TestTargetNew(
+        level = TestLevel.COMPLETE,
+        method = "setColorFilter",
+        args = {android.graphics.ColorFilter.class}
+    )
+    public void testSetColorFilter() {
+        MockDrawable mockDrawable = new MockDrawable();
+        ScaleDrawable scaleDrawable = new ScaleDrawable(mockDrawable, Gravity.CENTER, 100, 200);
+
+        // this method will call contained drawable's setColorFilter method.
+        scaleDrawable.setColorFilter(new ColorFilter());
+        assertTrue(mockDrawable.hasCalledSetColorFilter());
+
+        mockDrawable.reset();
+        scaleDrawable.setColorFilter(null);
+        assertTrue(mockDrawable.hasCalledSetColorFilter());
+    }
+
+    @TestTargetNew(
+        level = TestLevel.COMPLETE,
+        method = "getOpacity",
+        args = {}
+    )
+    public void testGetOpacity() {
+        MockDrawable mockDrawable = new MockDrawable();
+        ScaleDrawable scaleDrawable = new ScaleDrawable(mockDrawable, Gravity.CENTER, 100, 200);
+
+        // this method will call contained drawable's getOpacity method.
+        scaleDrawable.getOpacity();
+        assertTrue(mockDrawable.hasCalledGetOpacity());
+    }
+
+    @TestTargetNew(
+        level = TestLevel.COMPLETE,
+        method = "isStateful",
+        args = {}
+    )
+    public void testIsStateful() {
+        MockDrawable mockDrawable = new MockDrawable();
+        ScaleDrawable scaleDrawable = new ScaleDrawable(mockDrawable, Gravity.CENTER, 100, 200);
+
+        // this method will call contained drawable's isStateful method.
+        scaleDrawable.isStateful();
+        assertTrue(mockDrawable.hasCalledIsStateful());
+    }
+
+    @TestTargetNew(
+        level = TestLevel.COMPLETE,
+        method = "onStateChange",
+        args = {int[].class}
+    )
+    public void testOnStateChange() {
+        MockDrawable mockDrawable = new MockDrawable();
+        MockScaleDrawable mockScaleDrawable = new MockScaleDrawable(
+                mockDrawable, Gravity.CENTER, 100, 200);
+
+        assertFalse(mockScaleDrawable.onStateChange(StateSet.WILD_CARD));
+        assertTrue(mockDrawable.hasCalledSetState());
+        assertTrue(mockScaleDrawable.hasCalledOnBoundsChange());
+
+        mockDrawable.reset();
+        mockScaleDrawable.reset();
+        assertFalse(mockScaleDrawable.onStateChange(null));
+        assertTrue(mockDrawable.hasCalledSetState());
+        assertTrue(mockScaleDrawable.hasCalledOnBoundsChange());
+    }
+
+    @TestTargetNew(
+        level = TestLevel.COMPLETE,
+        method = "onLevelChange",
+        args = {int.class}
+    )
+    public void testOnLevelChange() {
+        MockDrawable mockDrawable = new MockDrawable();
+        MockScaleDrawable mockScaleDrawable = new MockScaleDrawable(
+                mockDrawable, Gravity.CENTER, 100, 200);
+
+        assertTrue(mockScaleDrawable.onLevelChange(0));
+        assertFalse(mockDrawable.hasCalledOnLevelChange());
+        assertTrue(mockScaleDrawable.hasCalledOnBoundsChange());
+
+        mockDrawable.reset();
+        mockScaleDrawable.reset();
+        assertTrue(mockScaleDrawable.onLevelChange(Integer.MIN_VALUE));
+        assertTrue(mockDrawable.hasCalledOnLevelChange());
+        assertTrue(mockScaleDrawable.hasCalledOnBoundsChange());
+    }
+
+    @TestTargetNew(
+        level = TestLevel.COMPLETE,
+        method = "onBoundsChange",
+        args = {android.graphics.Rect.class}
+    )
+    public void testOnBoundsChange() {
+        MockDrawable mockDrawable = new MockDrawable();
+        float scaleWidth = 0.3f;
+        float scaleHeight = 0.3f;
+        MockScaleDrawable mockScaleDrawable = new MockScaleDrawable(
+                mockDrawable, Gravity.LEFT, scaleWidth, scaleHeight);
+        Rect bounds = new Rect(2, 2, 26, 32);
+        mockDrawable.setBounds(bounds);
+        mockScaleDrawable.onBoundsChange(bounds);
+        Rect expected = new Rect();
+        Gravity.apply(Gravity.LEFT, bounds.width() - (int) (bounds.width() * scaleWidth),
+                bounds.height() - (int) (bounds.height() * scaleHeight), bounds, expected);
+        assertEquals(expected.left, mockDrawable.getBounds().left);
+        assertEquals(expected.top, mockDrawable.getBounds().top);
+        assertEquals(expected.right, mockDrawable.getBounds().right);
+        assertEquals(expected.bottom, mockDrawable.getBounds().bottom);
+
+        scaleWidth = 0.6f;
+        scaleHeight = 0.7f;
+        int level = 4000;
+        mockScaleDrawable = new MockScaleDrawable(
+                mockDrawable, Gravity.BOTTOM | Gravity.RIGHT, scaleWidth, scaleHeight);
+        mockDrawable.setBounds(bounds);
+        mockScaleDrawable.setLevel(level);
+        mockScaleDrawable.onBoundsChange(bounds);
+        Gravity.apply(Gravity.BOTTOM | Gravity.RIGHT,
+                bounds.width() - (int) (bounds.width() * scaleWidth * (10000 - level) / 10000),
+                bounds.height() - (int) (bounds.height() * scaleHeight * (10000 - level) / 10000),
+                bounds, expected);
+        assertEquals(expected.left, mockDrawable.getBounds().left);
+        assertEquals(expected.top, mockDrawable.getBounds().top);
+        assertEquals(expected.right, mockDrawable.getBounds().right);
+        assertEquals(expected.bottom, mockDrawable.getBounds().bottom);
+
+        scaleWidth = 0f;
+        scaleHeight = -0.3f;
+        mockScaleDrawable = new MockScaleDrawable(
+                mockDrawable, Gravity.BOTTOM | Gravity.RIGHT, scaleWidth, scaleHeight);
+        mockDrawable.setBounds(bounds);
+        mockScaleDrawable.onBoundsChange(bounds);
+        assertEquals(bounds.left, mockDrawable.getBounds().left);
+        assertEquals(bounds.top, mockDrawable.getBounds().top);
+        assertEquals(bounds.right, mockDrawable.getBounds().right);
+        assertEquals(bounds.bottom, mockDrawable.getBounds().bottom);
+
+        scaleWidth = 1f;
+        scaleHeight = 1.7f;
+        mockScaleDrawable = new MockScaleDrawable(
+                mockDrawable, Gravity.BOTTOM | Gravity.RIGHT, scaleWidth, scaleHeight);
+        mockDrawable.setBounds(bounds);
+        mockScaleDrawable.onBoundsChange(bounds);
+        assertEquals(bounds.left, mockDrawable.getBounds().left);
+        assertEquals(bounds.top, mockDrawable.getBounds().top);
+        assertEquals(bounds.right, mockDrawable.getBounds().right);
+        assertEquals(bounds.bottom, mockDrawable.getBounds().bottom);
+    }
+
+    @TestTargetNew(
+        level = TestLevel.COMPLETE,
+        method = "getIntrinsicWidth",
+        args = {}
+    )
+    public void testGetIntrinsicWidth() {
+        MockDrawable mockDrawable = new MockDrawable();
+        ScaleDrawable scaleDrawable = new ScaleDrawable(mockDrawable, Gravity.CENTER, 100, 200);
+
+        // this method will call contained drawable's getIntrinsicWidth method.
+        scaleDrawable.getIntrinsicWidth();
+        assertTrue(mockDrawable.hasCalledGetIntrinsicWidth());
+    }
+
+    @TestTargetNew(
+        level = TestLevel.COMPLETE,
+        method = "getIntrinsicHeight",
+        args = {}
+    )
+    public void testGetIntrinsicHeight() {
+        MockDrawable mockDrawable = new MockDrawable();
+        ScaleDrawable scaleDrawable = new ScaleDrawable(mockDrawable, Gravity.CENTER, 100, 200);
+
+        // this method will call contained drawable's getIntrinsicHeight method.
+        scaleDrawable.getIntrinsicHeight();
+        assertTrue(mockDrawable.hasCalledGetIntrinsicHeight());
+    }
+
+    @TestTargetNew(
+        level = TestLevel.COMPLETE,
+        method = "getConstantState",
+        args = {}
+    )
+    public void testGetConstantState() {
+        ScaleDrawable scaleDrawable = new ScaleDrawable(new BitmapDrawable(),
+                Gravity.CENTER, 100, 200);
+
+        ConstantState constantState = scaleDrawable.getConstantState();
+        assertNotNull(constantState);
+        assertEquals(0, constantState.getChangingConfigurations());
+
+        scaleDrawable.setChangingConfigurations(1);
+        constantState = scaleDrawable.getConstantState();
+        assertNotNull(constantState);
+        assertEquals(1, constantState.getChangingConfigurations());
+    }
+
+    @TestTargetNew(
+        level = TestLevel.COMPLETE,
+        method = "inflate",
+        args = {android.content.res.Resources.class, org.xmlpull.v1.XmlPullParser.class,
+                android.util.AttributeSet.class}
+    )
+    @ToBeFixed(bug = "1695243", explanation = "the javadoc for inflate is incomplete." +
+            "1. not clear what is supposed to happen if any parameter is null.")
+    public void testInflate() throws XmlPullParserException, IOException {
+        ScaleDrawable scaleDrawable = new ScaleDrawable(new BitmapDrawable(),
+                Gravity.RIGHT, 100, 200);
+
+        XmlResourceParser parser = mContext.getResources().getXml(R.xml.scaledrawable);
+        AttributeSet attrs = DrawableTestUtils.getAttributeSet(parser, "scale_allattrs");
+        scaleDrawable.inflate(mContext.getResources(), parser, attrs);
+        assertEquals(48, scaleDrawable.getIntrinsicWidth());
+        assertEquals(48, scaleDrawable.getIntrinsicHeight());
+
+        parser = mContext.getResources().getXml(R.xml.scaledrawable);
+        attrs = DrawableTestUtils.getAttributeSet(parser, "scale_nodrawable");
+        try {
+            scaleDrawable.inflate(mContext.getResources(), parser, attrs);
+            fail("Should throw IllegalArgumentException");
+        } catch (IllegalArgumentException e) {
+        }
+
+        try {
+            scaleDrawable.inflate(null, parser, attrs);
+            fail("Should throw NullPointerException if resource is null");
+        } catch (NullPointerException e) {
+        }
+
+        try {
+            scaleDrawable.inflate(mContext.getResources(), null, attrs);
+            fail("Should throw NullPointerException if parser is null");
+        } catch (NullPointerException e) {
+        }
+
+        try {
+            scaleDrawable.inflate(mContext.getResources(), parser, null);
+            fail("Should throw NullPointerException if attribute set is null");
+        } catch (NullPointerException e) {
+        }
+    }
+
+    @TestTargetNew(
+        level = TestLevel.COMPLETE,
+        method = "mutate",
+        args = {}
+    )
+    public void testMutate() {
+        Resources resources = mContext.getResources();
+        ScaleDrawable d1 = (ScaleDrawable) resources.getDrawable(R.drawable.scaledrawable);
+        ScaleDrawable d2 = (ScaleDrawable) resources.getDrawable(R.drawable.scaledrawable);
+        ScaleDrawable d3 = (ScaleDrawable) resources.getDrawable(R.drawable.scaledrawable);
+
+        d1.setAlpha(100);
+        assertEquals(100, ((BitmapDrawable) d1.getDrawable()).getPaint().getAlpha());
+        assertEquals(100, ((BitmapDrawable) d2.getDrawable()).getPaint().getAlpha());
+        assertEquals(100, ((BitmapDrawable) d3.getDrawable()).getPaint().getAlpha());
+
+        d1.mutate();
+        d1.setAlpha(200);
+        assertEquals(200, ((BitmapDrawable) d1.getDrawable()).getPaint().getAlpha());
+        assertEquals(100, ((BitmapDrawable) d2.getDrawable()).getPaint().getAlpha());
+        assertEquals(100, ((BitmapDrawable) d3.getDrawable()).getPaint().getAlpha());
+
+        d2.setAlpha(50);
+        assertEquals(200, ((BitmapDrawable) d1.getDrawable()).getPaint().getAlpha());
+        assertEquals(50, ((BitmapDrawable) d2.getDrawable()).getPaint().getAlpha());
+        assertEquals(50, ((BitmapDrawable) d3.getDrawable()).getPaint().getAlpha());
+    }
+
+    private static class MockDrawable extends Drawable {
+        private boolean mCalledDraw = false;
+        private boolean mCalledGetPadding = false;
+        private boolean mCalledSetVisible = false;
+        private boolean mCalledSetAlpha = false;
+        private boolean mCalledGetOpacity = false;
+        private boolean mCalledSetColorFilter = false;
+        private boolean mCalledIsStateful = false;
+        private boolean mCalledGetIntrinsicWidth = false;
+        private boolean mCalledGetIntrinsicHeight = false;
+        private boolean mCalledSetState = false;
+        private boolean mCalledOnLevelChange = false;
+
+        @Override
+        public void draw(Canvas canvas) {
+            mCalledDraw = true;
+        }
+
+        @Override
+        public int getOpacity() {
+            mCalledGetOpacity = true;
+            return 0;
+        }
+
+        @Override
+        public void setAlpha(int alpha) {
+            mCalledSetAlpha = true;
+        }
+
+        @Override
+        public void setColorFilter(ColorFilter cf) {
+            mCalledSetColorFilter = true;
+        }
+
+        @Override
+        public boolean getPadding(Rect padding) {
+            mCalledGetPadding = true;
+            return super.getPadding(padding);
+        }
+
+        @Override
+        public boolean setVisible(boolean visible, boolean restart) {
+            mCalledSetVisible = true;
+            return super.setVisible(visible, restart);
+        }
+
+        @Override
+        public boolean isStateful() {
+            mCalledIsStateful = true;
+            return super.isStateful();
+        }
+
+        @Override
+        public int getIntrinsicWidth() {
+            mCalledGetIntrinsicWidth = true;
+            return super.getIntrinsicWidth();
+        }
+
+        @Override
+        public int getIntrinsicHeight() {
+            mCalledGetIntrinsicHeight = true;
+            return super.getIntrinsicHeight();
+
+        }
+
+        @Override
+        public boolean setState(final int[] stateSet) {
+            mCalledSetState = true;
+            return super.setState(stateSet);
+        }
+
+        @Override
+        protected boolean onLevelChange(int level) {
+            mCalledOnLevelChange = true;
+            return super.onLevelChange(level);
+        }
+
+        public boolean hasCalledDraw() {
+            return mCalledDraw;
+        }
+
+        public boolean hasCalledGetPadding() {
+            return mCalledGetPadding;
+        }
+
+        public boolean hasCalledSetVisible() {
+            return mCalledSetVisible;
+        }
+
+        public boolean hasCalledSetAlpha() {
+            return mCalledSetAlpha;
+        }
+
+        public boolean hasCalledGetOpacity() {
+            return mCalledGetOpacity;
+        }
+
+        public boolean hasCalledSetColorFilter() {
+            return mCalledSetColorFilter;
+        }
+
+        public boolean hasCalledIsStateful() {
+            return mCalledIsStateful;
+        }
+
+        public boolean hasCalledGetIntrinsicWidth() {
+            return mCalledGetIntrinsicWidth;
+        }
+
+        public boolean hasCalledGetIntrinsicHeight() {
+            return mCalledGetIntrinsicHeight;
+        }
+
+        public boolean hasCalledSetState() {
+            return mCalledSetState;
+        }
+
+        public boolean hasCalledOnLevelChange() {
+            return mCalledOnLevelChange;
+        }
+
+        public void reset() {
+            mCalledDraw = false;
+            mCalledGetPadding = false;
+            mCalledSetVisible = false;
+            mCalledSetAlpha = false;
+            mCalledGetOpacity = false;
+            mCalledSetColorFilter = false;
+            mCalledIsStateful = false;
+            mCalledGetIntrinsicWidth = false;
+            mCalledGetIntrinsicHeight = false;
+            mCalledSetState = false;
+            mCalledOnLevelChange = false;
+        }
+    }
+
+    private static class MockScaleDrawable extends ScaleDrawable {
+        private boolean mCalledOnBoundsChange = false;
+
+        MockScaleDrawable() {
+            super(null, Gravity.CENTER, 100, 200);
+        }
+
+        public MockScaleDrawable(Drawable drawable, int gravity,
+                float scaleWidth, float scaleHeight) {
+            super(drawable, gravity, scaleWidth, scaleHeight);
+        }
+
+        @Override
+        protected boolean onStateChange(int[] state) {
+            return super.onStateChange(state);
+        }
+
+        @Override
+        protected boolean onLevelChange(int level) {
+            return super.onLevelChange(level);
+        }
+
+        @Override
+        protected void onBoundsChange(Rect bounds) {
+            mCalledOnBoundsChange = true;
+            super.onBoundsChange(bounds);
+        }
+
+        public boolean hasCalledOnBoundsChange() {
+            return mCalledOnBoundsChange;
+        }
+
+        public void reset() {
+            mCalledOnBoundsChange = false;
+        }
+    }
+}