Merge change 7169 into donut
* changes:
Add new donut packages to CTS test progress tracker.
diff --git a/tests/res/drawable/animationdrawable.xml b/tests/res/drawable/animationdrawable.xml
new file mode 100644
index 0000000..6756966
--- /dev/null
+++ b/tests/res/drawable/animationdrawable.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.
+ -->
+
+<animation-list xmlns:android="http://schemas.android.com/apk/res/android" android:oneshot="false">
+ <item android:drawable="@drawable/testimage" android:duration="3000"/>
+ <item android:drawable="@drawable/pass" android:duration="2000"/>
+ <item android:drawable="@drawable/scenery" android:duration="1000"/>
+</animation-list>
diff --git a/tests/res/drawable/opaque.9.png b/tests/res/drawable/opaque.9.png
new file mode 100644
index 0000000..a60f6d8
--- /dev/null
+++ b/tests/res/drawable/opaque.9.png
Binary files differ
diff --git a/tests/res/drawable/scaled1.png b/tests/res/drawable/scaled1.png
new file mode 100644
index 0000000..2dad421
--- /dev/null
+++ b/tests/res/drawable/scaled1.png
Binary files differ
diff --git a/tests/res/drawable/scaled2.png b/tests/res/drawable/scaled2.png
new file mode 100644
index 0000000..6d6a94f
--- /dev/null
+++ b/tests/res/drawable/scaled2.png
Binary files differ
diff --git a/tests/res/drawable/transparent_border.9.png b/tests/res/drawable/transparent_border.9.png
new file mode 100644
index 0000000..2614c06
--- /dev/null
+++ b/tests/res/drawable/transparent_border.9.png
Binary files differ
diff --git a/tests/res/drawable/transparent_right.9.png b/tests/res/drawable/transparent_right.9.png
new file mode 100644
index 0000000..a438312
--- /dev/null
+++ b/tests/res/drawable/transparent_right.9.png
Binary files differ
diff --git a/tests/res/xml/anim_list_correct.xml b/tests/res/xml/anim_list_correct.xml
new file mode 100644
index 0000000..660aa96
--- /dev/null
+++ b/tests/res/xml/anim_list_correct.xml
@@ -0,0 +1,32 @@
+<?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.
+ */
+-->
+
+<animation-list xmlns:android="http://schemas.android.com/apk/res/android"
+ android:visible="false"
+ android:variablePadding="true"
+ android:oneshot="true" >
+
+ <item android:drawable="@drawable/testimage"
+ android:duration="2000" />
+
+ <item android:duration="1000" >
+ <color android:color="#77ffffff" />
+ </item>
+</animation-list>
+
diff --git a/tests/res/xml/anim_list_missing_item_drawable.xml b/tests/res/xml/anim_list_missing_item_drawable.xml
new file mode 100644
index 0000000..99052f4
--- /dev/null
+++ b/tests/res/xml/anim_list_missing_item_drawable.xml
@@ -0,0 +1,23 @@
+<?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.
+ */
+-->
+
+<animation-list xmlns:android="http://schemas.android.com/apk/res/android" >
+ <item android:duration="2000" />
+</animation-list>
+
diff --git a/tests/res/xml/anim_list_missing_item_duration.xml b/tests/res/xml/anim_list_missing_item_duration.xml
new file mode 100644
index 0000000..e3986c2
--- /dev/null
+++ b/tests/res/xml/anim_list_missing_item_duration.xml
@@ -0,0 +1,23 @@
+<?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.
+ */
+-->
+
+<animation-list xmlns:android="http://schemas.android.com/apk/res/android" >
+ <item android:drawable="@drawable/testimage" />
+</animation-list>
+
diff --git a/tests/res/xml/anim_list_missing_list_attrs.xml b/tests/res/xml/anim_list_missing_list_attrs.xml
new file mode 100644
index 0000000..25d2dfe
--- /dev/null
+++ b/tests/res/xml/anim_list_missing_list_attrs.xml
@@ -0,0 +1,24 @@
+<?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.
+ */
+-->
+
+<animation-list xmlns:android="http://schemas.android.com/apk/res/android" >
+ <item android:drawable="@drawable/testimage"
+ android:duration="2000" />
+</animation-list>
+
diff --git a/tests/tests/graphics/src/android/graphics/cts/NinePatchTest.java b/tests/tests/graphics/src/android/graphics/cts/NinePatchTest.java
new file mode 100644
index 0000000..67223ab
--- /dev/null
+++ b/tests/tests/graphics/src/android/graphics/cts/NinePatchTest.java
@@ -0,0 +1,257 @@
+/*
+ * 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.cts;
+
+import com.android.cts.stub.R;
+import android.graphics.Bitmap;
+import android.graphics.BitmapFactory;
+import android.graphics.Canvas;
+import android.graphics.Color;
+import android.graphics.NinePatch;
+import android.graphics.Paint;
+import android.graphics.Rect;
+import android.graphics.RectF;
+import android.graphics.Region;
+import android.test.AndroidTestCase;
+import dalvik.annotation.TestLevel;
+import dalvik.annotation.TestTargetClass;
+import dalvik.annotation.TestTargetNew;
+import dalvik.annotation.TestTargets;
+
+@TestTargetClass(NinePatch.class)
+public class NinePatchTest extends AndroidTestCase {
+ private static int ALPHA_OPAQUE = 0xFF;
+
+ private NinePatch mNinePatch;
+ private Bitmap mBitmap;
+ private final String NAME = "TESTNAME";
+ private final int WIDTH = 80;
+ private final int HEIGTH = 120;
+ private final int[] COLOR = new int[WIDTH * HEIGTH];
+ private byte[] mChunk;
+
+ @Override
+ protected void setUp() throws Exception {
+ super.setUp();
+ mBitmap = BitmapFactory.decodeResource(getContext().getResources(),
+ R.drawable.opaque);
+ mChunk = mBitmap.getNinePatchChunk();
+ assertNotNull(mChunk);
+ mNinePatch = new NinePatch(mBitmap, mChunk, NAME);
+ }
+
+ @TestTargetNew(
+ level = TestLevel.COMPLETE,
+ method = "NinePatch",
+ args = {android.graphics.Bitmap.class, byte[].class, java.lang.String.class}
+ )
+ public void testConstructor() {
+ mNinePatch = null;
+ try {
+ mNinePatch = new NinePatch(mBitmap, new byte[2], NAME);
+ fail("should throw exception");
+ } catch (Exception e) {
+ }
+ mNinePatch = new NinePatch(mBitmap, mChunk, NAME);
+ }
+
+ @TestTargetNew(
+ level = TestLevel.COMPLETE,
+ method = "isNinePatchChunk",
+ args = {byte[].class}
+ )
+ public void testIsNinePatchChunk() {
+ assertTrue(NinePatch.isNinePatchChunk(mChunk));
+ Bitmap bitmap = Bitmap.createBitmap(COLOR, 10, 10, Bitmap.Config.ARGB_4444);
+ assertFalse(NinePatch.isNinePatchChunk(bitmap.getNinePatchChunk()));
+ assertFalse(NinePatch.isNinePatchChunk(null));
+
+ }
+
+ @TestTargets(value = {
+ @TestTargetNew(
+ level = TestLevel.COMPLETE,
+ method = "draw",
+ args = {android.graphics.Canvas.class, android.graphics.RectF.class}
+ ),
+ @TestTargetNew(
+ level = TestLevel.COMPLETE,
+ method = "draw",
+ args = {android.graphics.Canvas.class, android.graphics.Rect.class}
+ ),
+ @TestTargetNew(
+ level = TestLevel.COMPLETE,
+ method = "draw",
+ args = {android.graphics.Canvas.class, android.graphics.Rect.class}
+ ),
+ @TestTargetNew(
+ level = TestLevel.COMPLETE,
+ method = "setPaint",
+ args = {android.graphics.Paint.class}
+ )
+ })
+ public void testDraw() {
+ Bitmap expected =
+ BitmapFactory.decodeResource(getContext().getResources(), R.drawable.scaled1);
+
+ Bitmap bitmap = Bitmap.createBitmap(expected.getWidth(), expected.getHeight(),
+ Bitmap.Config.ARGB_8888);
+ Canvas c = new Canvas(bitmap);
+ RectF rectf = new RectF(0, 0, c.getWidth(), c.getHeight());
+ mNinePatch.draw(c, rectf);
+ checkBitmapWithAlpha(expected, bitmap, ALPHA_OPAQUE);
+
+ expected = BitmapFactory.decodeResource(getContext().getResources(), R.drawable.scaled2);
+ bitmap = Bitmap.createBitmap(expected.getWidth(), expected.getHeight(),
+ Bitmap.Config.ARGB_8888);
+ c = new Canvas(bitmap);
+ Rect rect = new Rect(0, 0, c.getWidth(), c.getHeight());
+ mNinePatch.draw(c, rect);
+ checkBitmapWithAlpha(expected, bitmap, ALPHA_OPAQUE);
+
+ bitmap = Bitmap.createBitmap(expected.getWidth(), expected.getHeight(),
+ Bitmap.Config.ARGB_8888);
+ c = new Canvas(bitmap);
+ rect = new Rect(0, 0, c.getWidth(), c.getHeight());
+ final int alpha = 128;
+ Paint p = new Paint();
+ p.setAlpha(alpha);
+ mNinePatch.draw(c, rect, p);
+ checkBitmapWithAlpha(expected, bitmap, alpha);
+
+ bitmap = Bitmap.createBitmap(expected.getWidth(), expected.getHeight(),
+ Bitmap.Config.ARGB_8888);
+ c = new Canvas(bitmap);
+ rectf = new RectF(0, 0, c.getWidth(), c.getHeight());
+ mNinePatch.setPaint(p);
+ mNinePatch.draw(c, rectf);
+ checkBitmapWithAlpha(expected, bitmap, alpha);
+ }
+
+ private void checkBitmapWithAlpha(Bitmap expected, Bitmap bitmap, int alpha) {
+ assertEquals(expected.getWidth(), bitmap.getWidth());
+ assertEquals(expected.getHeight(), bitmap.getHeight());
+ int width = expected.getWidth();
+ int height = expected.getHeight();
+
+ for (int i = 0; i < width; i++) {
+ for (int j = 0; j < height; j++) {
+ int expectedPixel = expected.getPixel(i, j);
+ int actualPixel = bitmap.getPixel(i, j);
+ int expectedAlpha = Color.alpha(expectedPixel);
+ int actualAlpha = Color.alpha(actualPixel);
+ expectedPixel &= 0xFFFFFF;
+ actualPixel &= 0xFFFFFF;
+ assertEquals(expectedPixel, actualPixel);
+ assertEquals(expectedAlpha * alpha / ALPHA_OPAQUE, actualAlpha, 1);
+ }
+ }
+ }
+
+ @TestTargetNew(
+ level = TestLevel.COMPLETE,
+ method = "hasAlpha",
+ args = {}
+ )
+ public void testHasAlpha() {
+ assertFalse(mNinePatch.hasAlpha());
+ assertEquals(mNinePatch.hasAlpha(), mBitmap.hasAlpha());
+
+ Bitmap bitmap = BitmapFactory.decodeResource(getContext().getResources(),
+ R.drawable.transparent_border);
+ byte[] chunk = bitmap.getNinePatchChunk();
+ NinePatch ninePatch = new NinePatch(bitmap, chunk, NAME);
+ assertTrue(ninePatch.hasAlpha());
+ assertEquals(ninePatch.hasAlpha(), bitmap.hasAlpha());
+ }
+
+ @TestTargetNew(
+ level = TestLevel.COMPLETE,
+ method = "getHeight",
+ args = {}
+ )
+ public void testGetHeight() {
+ assertEquals(5, mNinePatch.getHeight());
+ assertEquals(mNinePatch.getHeight(), mBitmap.getHeight());
+ }
+
+ @TestTargetNew(
+ level = TestLevel.COMPLETE,
+ method = "getWidth",
+ args = {}
+ )
+ public void testGetWidth() {
+ assertEquals(5, mNinePatch.getHeight());
+ assertEquals(mNinePatch.getWidth(), mBitmap.getWidth());
+ }
+
+ @TestTargetNew(
+ level = TestLevel.COMPLETE,
+ method = "getTransparentRegion",
+ args = {android.graphics.Rect.class}
+ )
+ public void testGetTransparentRegion() {
+ // no transparency in opaque bitmap
+ Rect location = new Rect(0, 0, mBitmap.getWidth(), mBitmap.getHeight());
+ Region region = mNinePatch.getTransparentRegion(location);
+ assertNull(region);
+
+ // transparent border of 1px
+ mBitmap = BitmapFactory.decodeResource(getContext().getResources(),
+ R.drawable.transparent_border);
+ mChunk = mBitmap.getNinePatchChunk();
+ assertNotNull(mChunk);
+ mNinePatch = new NinePatch(mBitmap, mChunk, NAME);
+
+ location = new Rect(0, 0, mBitmap.getWidth(), mBitmap.getHeight());
+ region = mNinePatch.getTransparentRegion(location);
+ assertNotNull(region);
+ Rect regionBounds = region.getBounds();
+ assertBounds(regionBounds, 0, 0, 5, 5);
+
+ location = new Rect(0, 0, mBitmap.getWidth() * 2, mBitmap.getHeight() * 2);
+ region = mNinePatch.getTransparentRegion(location);
+ assertNotNull(region);
+ regionBounds = region.getBounds();
+ assertBounds(regionBounds, 0, 0, 10, 10);
+
+ // transparent padding of 1px on the right side
+ mBitmap = BitmapFactory.decodeResource(getContext().getResources(),
+ R.drawable.transparent_right);
+ mChunk = mBitmap.getNinePatchChunk();
+ assertNotNull(mChunk);
+ mNinePatch = new NinePatch(mBitmap, mChunk, NAME);
+
+ location = new Rect(0, 0, mBitmap.getWidth(), mBitmap.getHeight());
+ region = mNinePatch.getTransparentRegion(location);
+ assertNotNull(region);
+ regionBounds = region.getBounds();
+ assertBounds(regionBounds, 4, 0, 5, 5);
+
+ location = new Rect(0, 0, mBitmap.getWidth() * 2, mBitmap.getHeight() * 2);
+ region = mNinePatch.getTransparentRegion(location);
+ regionBounds = region.getBounds();
+ assertBounds(regionBounds, 9, 0, 10, 10);
+ }
+
+ private void assertBounds(Rect regionBounds, int left, int top, int right, int bottom) {
+ assertEquals(left, regionBounds.left);
+ assertEquals(top, regionBounds.top);
+ assertEquals(right, regionBounds.right);
+ assertEquals(bottom, regionBounds.bottom);
+ }
+}
diff --git a/tests/tests/graphics/src/android/graphics/cts/PictureTest.java b/tests/tests/graphics/src/android/graphics/cts/PictureTest.java
new file mode 100644
index 0000000..9954b10
--- /dev/null
+++ b/tests/tests/graphics/src/android/graphics/cts/PictureTest.java
@@ -0,0 +1,155 @@
+/*
+ * 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.cts;
+
+import java.io.ByteArrayInputStream;
+import java.io.ByteArrayOutputStream;
+
+import junit.framework.TestCase;
+
+import android.graphics.Bitmap;
+import android.graphics.Canvas;
+import android.graphics.Color;
+import android.graphics.Paint;
+import android.graphics.Picture;
+import android.graphics.Paint.Style;
+
+import dalvik.annotation.TestLevel;
+import dalvik.annotation.TestTargetClass;
+import dalvik.annotation.TestTargetNew;
+import dalvik.annotation.TestTargets;
+
+@TestTargetClass(Picture.class)
+public class PictureTest extends TestCase {
+
+ private static final int TEST_WIDTH = 4; // must be >= 2
+ private static final int TEST_HEIGHT = 3; // must >= 2
+
+ @TestTargets({
+ @TestTargetNew(
+ level = TestLevel.COMPLETE,
+ method = "Picture",
+ args = {}
+ ),
+ @TestTargetNew(
+ level = TestLevel.COMPLETE,
+ method = "Picture",
+ args = {android.graphics.Picture.class}
+ ),
+ @TestTargetNew(
+ level = TestLevel.COMPLETE,
+ method = "beginRecording",
+ args = {int.class, int.class}
+ ),
+ @TestTargetNew(
+ level = TestLevel.COMPLETE,
+ method = "endRecording",
+ args = {}
+ ),
+ @TestTargetNew(
+ level = TestLevel.COMPLETE,
+ method = "getHeight",
+ args = {}
+ ),
+ @TestTargetNew(
+ level = TestLevel.COMPLETE,
+ method = "getWidth",
+ args = {}
+ ),
+ @TestTargetNew(
+ level = TestLevel.COMPLETE,
+ method = "writeToStream",
+ args = {java.io.OutputStream.class}
+ ),
+ @TestTargetNew(
+ level = TestLevel.COMPLETE,
+ method = "createFromStream",
+ args = {java.io.InputStream.class}
+ ),
+ @TestTargetNew(
+ level = TestLevel.COMPLETE,
+ method = "draw",
+ args = {android.graphics.Canvas.class}
+ )
+ })
+ public void testPicture() throws Exception {
+
+ Picture picture = new Picture();
+ ByteArrayOutputStream bout = new ByteArrayOutputStream();
+
+ Canvas canvas = picture.beginRecording(TEST_WIDTH, TEST_HEIGHT);
+ assertNotNull(canvas);
+ drawPicture(canvas);
+ picture.endRecording();
+
+ Bitmap bitmap = Bitmap.createBitmap(TEST_WIDTH, TEST_HEIGHT, Bitmap.Config.ARGB_8888);
+ canvas = new Canvas(bitmap);
+ picture.draw(canvas);
+ checkSize(picture);
+ checkBitmap(bitmap);
+
+ picture.writeToStream(bout);
+ picture = Picture.createFromStream(new ByteArrayInputStream(bout.toByteArray()));
+
+ // create a new Canvas with a new bitmap
+ bitmap = Bitmap.createBitmap(TEST_WIDTH, TEST_HEIGHT, Bitmap.Config.ARGB_8888);
+ canvas = new Canvas(bitmap);
+ picture.draw(canvas);
+ checkSize(picture);
+ checkBitmap(bitmap);
+
+ Picture pic = new Picture(picture);
+ bitmap = Bitmap.createBitmap(TEST_WIDTH, TEST_HEIGHT, Bitmap.Config.ARGB_8888);
+ canvas = new Canvas(bitmap);
+ pic.draw(canvas);
+ checkSize(pic);
+ checkBitmap(bitmap);
+ }
+
+ private void checkSize(Picture picture) {
+ assertEquals(TEST_WIDTH, picture.getWidth());
+ assertEquals(TEST_HEIGHT, picture.getHeight());
+ }
+
+ private void drawPicture(Canvas canvas) {
+ Paint paint = new Paint();
+ // GREEN rectangle covering the entire canvas
+ paint.setColor(Color.GREEN);
+ paint.setStyle(Style.FILL);
+ canvas.drawRect(0, 0, TEST_WIDTH, TEST_HEIGHT, paint);
+ // horizontal red line starting from (0,0); overwrites first line of the rectangle
+ paint.setColor(Color.RED);
+ canvas.drawLine(0, 0, TEST_WIDTH, 0, paint);
+ // overwrite (0,0) with a blue dot
+ paint.setColor(Color.BLUE);
+ canvas.drawPoint(0, 0, paint);
+ }
+
+ private void checkBitmap(Bitmap bitmap) {
+ // first pixel is BLUE, rest of the line is RED
+ assertEquals(Color.BLUE, bitmap.getPixel(0, 0));
+ for (int x = 1; x < TEST_WIDTH; x++) {
+ assertEquals(Color.RED, bitmap.getPixel(x, 0));
+ }
+ // remaining lines are all green
+ for (int y = 1; y < TEST_HEIGHT; y++) {
+ for (int x = 0; x < TEST_WIDTH; x++) {
+ assertEquals(Color.GREEN, bitmap.getPixel(x, y));
+ }
+ }
+ }
+}
diff --git a/tests/tests/graphics/src/android/graphics/drawable/cts/AnimationDrawableTest.java b/tests/tests/graphics/src/android/graphics/drawable/cts/AnimationDrawableTest.java
new file mode 100644
index 0000000..e86f051
--- /dev/null
+++ b/tests/tests/graphics/src/android/graphics/drawable/cts/AnimationDrawableTest.java
@@ -0,0 +1,496 @@
+/*
+ * 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.
+ */
+
+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.app.Activity;
+import android.content.res.Resources;
+import android.content.res.XmlResourceParser;
+import android.graphics.drawable.AnimationDrawable;
+import android.graphics.drawable.Drawable;
+import android.graphics.drawable.DrawableContainer.DrawableContainerState;
+import android.test.ActivityInstrumentationTestCase2;
+import android.util.Xml;
+import android.view.animation.cts.DelayedCheck;
+import android.widget.ImageView;
+import android.widget.cts.ImageViewStubActivity;
+
+import java.io.IOException;
+
+@TestTargetClass(AnimationDrawable.class)
+public class AnimationDrawableTest extends ActivityInstrumentationTestCase2<ImageViewStubActivity> {
+ private static final int FRAMES_COUNT = 3;
+ private static final int FIRST_FRAME_INDEX = 0;
+ private static final int SECOND_FRAME_INDEX = 1;
+ private static final int THIRD_FRAME_INDEX = 2;
+ private static final long TOLERANCE = 500;
+ private static final long FIRST_FRAME_DURATION = 3000;
+ private static final long SECOND_FRAME_DURATION = 2000;
+ private static final long THIRD_FRAME_DURATION = 1000;
+
+ private AnimationDrawable mAnimationDrawable;
+ private Resources mResources;
+
+ public AnimationDrawableTest() {
+ super("com.android.cts.stub", ImageViewStubActivity.class);
+ }
+
+ @Override
+ protected void setUp() throws Exception {
+ super.setUp();
+ final Activity activity = getActivity();
+ mResources = activity.getResources();
+ try {
+ runTestOnUiThread(new Runnable() {
+ public void run() {
+ ImageView imageView = (ImageView) activity.findViewById(R.id.imageview);
+ imageView.setBackgroundResource(R.drawable.animationdrawable);
+ mAnimationDrawable = (AnimationDrawable) imageView.getBackground();
+ }
+ });
+ } catch (Throwable t) {
+ throw new Exception(t);
+ }
+ }
+
+ @TestTargetNew(
+ level = TestLevel.COMPLETE,
+ method = "AnimationDrawable",
+ args = {}
+ )
+ @ToBeFixed(bug = "1695243", explanation = "Android API javadocs are incomplete")
+ public void testConstructor() {
+ mAnimationDrawable = new AnimationDrawable();
+ // Check the values set in the constructor
+ assertNotNull(mAnimationDrawable.getConstantState());
+ assertFalse(mAnimationDrawable.isRunning());
+ assertTrue(mAnimationDrawable.isOneShot());
+ }
+
+ @TestTargetNew(
+ level = TestLevel.COMPLETE,
+ method = "setVisible",
+ args = {boolean.class, boolean.class}
+ )
+ public void testSetVisible() throws Throwable {
+ assertTrue(mAnimationDrawable.isVisible());
+ runTestOnUiThread(new Runnable() {
+ public void run() {
+ mAnimationDrawable.start();
+ }
+ });
+ assertTrue(mAnimationDrawable.isRunning());
+ assertSame(mAnimationDrawable.getFrame(FIRST_FRAME_INDEX),
+ mAnimationDrawable.getCurrent());
+
+ delayedCheckDrawable(SECOND_FRAME_INDEX, FIRST_FRAME_DURATION);
+
+ runTestOnUiThread(new Runnable() {
+ public void run() {
+ assertTrue(mAnimationDrawable.setVisible(false, false));
+ }
+ });
+ assertFalse(mAnimationDrawable.isVisible());
+ assertFalse(mAnimationDrawable.isRunning());
+ assertStoppedAnimation(SECOND_FRAME_INDEX, SECOND_FRAME_DURATION);
+
+ // restart animation
+ runTestOnUiThread(new Runnable() {
+ public void run() {
+ assertTrue(mAnimationDrawable.setVisible(true, true));
+ }
+ });
+ assertTrue(mAnimationDrawable.isVisible());
+ assertFalse(mAnimationDrawable.isRunning());
+ assertStoppedAnimation(FIRST_FRAME_INDEX, FIRST_FRAME_DURATION);
+ }
+
+ @TestTargets({
+ @TestTargetNew(
+ level = TestLevel.COMPLETE,
+ method = "start",
+ args = {}
+ ),
+ @TestTargetNew(
+ level = TestLevel.COMPLETE,
+ method = "stop",
+ args = {}
+ ),
+ @TestTargetNew(
+ level = TestLevel.COMPLETE,
+ method = "isRunning",
+ args = {}
+ )
+ })
+ public void testStart() throws Throwable {
+ // animation should play repeat if do not stop it.
+ assertFalse(mAnimationDrawable.isOneShot());
+ assertFalse(mAnimationDrawable.isRunning());
+ runTestOnUiThread(new Runnable() {
+ public void run() {
+ mAnimationDrawable.start();
+ }
+ });
+
+ assertTrue(mAnimationDrawable.isRunning());
+ assertSame(mAnimationDrawable.getFrame(FIRST_FRAME_INDEX),
+ mAnimationDrawable.getCurrent());
+ delayedCheckDrawable(SECOND_FRAME_INDEX, FIRST_FRAME_DURATION);
+
+ runTestOnUiThread(new Runnable() {
+ public void run() {
+ // This method has no effect if the animation is running.
+ mAnimationDrawable.start();
+ }
+ });
+ delayedCheckDrawable(THIRD_FRAME_INDEX, SECOND_FRAME_DURATION);
+
+ runTestOnUiThread(new Runnable() {
+ public void run() {
+ mAnimationDrawable.stop();
+ }
+ });
+ assertFalse(mAnimationDrawable.isRunning());
+ assertStoppedAnimation(THIRD_FRAME_INDEX, THIRD_FRAME_DURATION);
+
+ runTestOnUiThread(new Runnable() {
+ public void run() {
+ // This method has no effect if the animation is not running.
+ mAnimationDrawable.stop();
+ }
+ });
+ assertFalse(mAnimationDrawable.isRunning());
+ assertStoppedAnimation(THIRD_FRAME_INDEX, THIRD_FRAME_DURATION);
+ }
+
+ @TestTargetNew(
+ level = TestLevel.NOT_NECESSARY,
+ method = "run",
+ args = {}
+ )
+ public void testRun() {
+ // This method should not be called directly.
+ }
+
+ @TestTargetNew(
+ level = TestLevel.COMPLETE,
+ method = "unscheduleSelf",
+ args = {java.lang.Runnable.class}
+ )
+ public void testUnscheduleSelf() throws Throwable {
+ assertFalse(mAnimationDrawable.isRunning());
+ runTestOnUiThread(new Runnable() {
+ public void run() {
+ mAnimationDrawable.start();
+ }
+ });
+
+ assertTrue(mAnimationDrawable.isRunning());
+ delayedCheckDrawable(SECOND_FRAME_INDEX, FIRST_FRAME_DURATION);
+
+ runTestOnUiThread(new Runnable() {
+ public void run() {
+ mAnimationDrawable.unscheduleSelf(mAnimationDrawable);
+ }
+ });
+ assertFalse(mAnimationDrawable.isRunning());
+ assertStoppedAnimation(SECOND_FRAME_INDEX, SECOND_FRAME_DURATION);
+ }
+
+ @TestTargets({
+ @TestTargetNew(
+ level = TestLevel.COMPLETE,
+ method = "getNumberOfFrames",
+ args = {}
+ ),
+ @TestTargetNew(
+ level = TestLevel.COMPLETE,
+ method = "addFrame",
+ args = {android.graphics.drawable.Drawable.class, int.class}
+ )
+ })
+ @ToBeFixed(bug = "1695243", explanation = "should add @throws clause into javadoc of "
+ + "AnimationDrawable#addFrame(Drawable, int) when param frame is null")
+ public void testGetNumberOfFrames() {
+ assertEquals(FRAMES_COUNT, mAnimationDrawable.getNumberOfFrames());
+
+ Drawable frame = mResources.getDrawable(R.drawable.failed);
+ mAnimationDrawable.addFrame(frame, 2000);
+ assertEquals(FRAMES_COUNT + 1, mAnimationDrawable.getNumberOfFrames());
+
+ // add same frame with same duration
+ mAnimationDrawable.addFrame(frame, 2000);
+ assertEquals(FRAMES_COUNT + 2, mAnimationDrawable.getNumberOfFrames());
+
+ try {
+ mAnimationDrawable.addFrame(null, 1000);
+ fail("Should throw NullPointerException if param frame is null.");
+ } catch (NullPointerException e) {
+ // expected
+ }
+ }
+
+ @TestTargetNew(
+ level = TestLevel.COMPLETE,
+ method = "getFrame",
+ args = {int.class}
+ )
+ @ToBeFixed(bug = "1695243", explanation = "should add @throws clause into javadoc of "
+ + "AnimationDrawable#getFrame(int) when param index is out of bounds")
+ public void testGetFrame() {
+ Drawable frame = mAnimationDrawable.getFrame(FIRST_FRAME_INDEX);
+ Drawable drawable = mResources.getDrawable(R.drawable.testimage);
+ assertEquals(drawable.getIntrinsicWidth(), frame.getIntrinsicWidth());
+ assertEquals(drawable.getIntrinsicHeight(), frame.getIntrinsicHeight());
+
+ frame = mAnimationDrawable.getFrame(SECOND_FRAME_INDEX);
+ drawable = mResources.getDrawable(R.drawable.pass);
+ assertEquals(drawable.getIntrinsicWidth(), frame.getIntrinsicWidth());
+ assertEquals(drawable.getIntrinsicHeight(), frame.getIntrinsicHeight());
+
+ frame = mAnimationDrawable.getFrame(THIRD_FRAME_INDEX);
+ drawable = mResources.getDrawable(R.drawable.scenery);
+ assertEquals(drawable.getIntrinsicWidth(), frame.getIntrinsicWidth());
+ assertEquals(drawable.getIntrinsicHeight(), frame.getIntrinsicHeight());
+
+ assertNull(mAnimationDrawable.getFrame(THIRD_FRAME_INDEX + 1));
+
+ try {
+ mAnimationDrawable.getFrame(-1);
+ fail("Should throw ArrayIndexOutOfBoundsException.");
+ } catch (ArrayIndexOutOfBoundsException e) {
+ // expected
+ }
+
+ try {
+ mAnimationDrawable.getFrame(10);
+ fail("Should throw ArrayIndexOutOfBoundsException.");
+ } catch (ArrayIndexOutOfBoundsException e) {
+ // expected
+ }
+ }
+
+ @TestTargetNew(
+ level = TestLevel.COMPLETE,
+ method = "getDuration",
+ args = {int.class}
+ )
+ @ToBeFixed(bug = "1695243", explanation = "should add @throws clause into javadoc of "
+ + "AnimationDrawable#getDuration(int) when param index is out of bounds")
+ public void testGetDuration() {
+ assertEquals(FIRST_FRAME_DURATION, mAnimationDrawable.getDuration(FIRST_FRAME_INDEX));
+ assertEquals(SECOND_FRAME_DURATION, mAnimationDrawable.getDuration(SECOND_FRAME_INDEX));
+ assertEquals(THIRD_FRAME_DURATION, mAnimationDrawable.getDuration(THIRD_FRAME_INDEX));
+ assertEquals(0, mAnimationDrawable.getDuration(THIRD_FRAME_INDEX + 1));
+
+ try {
+ mAnimationDrawable.getDuration(-1);
+ fail("Should throw ArrayIndexOutOfBoundsException.");
+ } catch (ArrayIndexOutOfBoundsException e) {
+ // expected
+ }
+
+ try {
+ mAnimationDrawable.getDuration(10);
+ fail("Should throw ArrayIndexOutOfBoundsException.");
+ } catch (ArrayIndexOutOfBoundsException e) {
+ // expected
+ }
+ }
+
+ @TestTargets({
+ @TestTargetNew(
+ level = TestLevel.COMPLETE,
+ method = "isOneShot",
+ args = {}
+ ),
+ @TestTargetNew(
+ level = TestLevel.COMPLETE,
+ method = "setOneShot",
+ args = {boolean.class}
+ )
+ })
+ public void testAccessOneShot() throws Throwable {
+ // animation should play repeat if do not stop it.
+ assertFalse(mAnimationDrawable.isOneShot());
+ runTestOnUiThread(new Runnable() {
+ public void run() {
+ mAnimationDrawable.start();
+ }
+ });
+ delayedCheckDrawable(SECOND_FRAME_INDEX, FIRST_FRAME_DURATION);
+ delayedCheckDrawable(THIRD_FRAME_INDEX, SECOND_FRAME_DURATION);
+ // begin to repeat
+ delayedCheckDrawable(FIRST_FRAME_INDEX, THIRD_FRAME_DURATION);
+
+ runTestOnUiThread(new Runnable() {
+ public void run() {
+ mAnimationDrawable.stop();
+ mAnimationDrawable.setOneShot(true);
+ assertTrue(mAnimationDrawable.isOneShot());
+ mAnimationDrawable.start();
+ }
+ });
+ delayedCheckDrawable(SECOND_FRAME_INDEX, FIRST_FRAME_DURATION);
+ delayedCheckDrawable(THIRD_FRAME_INDEX, SECOND_FRAME_DURATION);
+ // do not repeat
+ assertStoppedAnimation(THIRD_FRAME_INDEX, THIRD_FRAME_DURATION);
+ }
+
+ @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 = "Android API javadocs are incomplete")
+ public void testInflate() throws XmlPullParserException, IOException {
+ mAnimationDrawable = new AnimationDrawable();
+ DrawableContainerState drawableContainerState =
+ (DrawableContainerState) mAnimationDrawable.getConstantState();
+
+ XmlResourceParser parser = getResourceParser(R.xml.anim_list_correct);
+ mAnimationDrawable.inflate(mResources, parser, Xml.asAttributeSet(parser));
+ // android:visible="false"
+ assertFalse(mAnimationDrawable.isVisible());
+ // android:oneShot="true"
+ assertTrue(mAnimationDrawable.isOneShot());
+ // android:variablePadding="true"
+ assertNull(drawableContainerState.getConstantPadding());
+ assertEquals(2, mAnimationDrawable.getNumberOfFrames());
+ assertEquals(2000, mAnimationDrawable.getDuration(0));
+ assertEquals(1000, mAnimationDrawable.getDuration(1));
+ assertSame(mAnimationDrawable.getFrame(0), mAnimationDrawable.getCurrent());
+
+ parser = getResourceParser(R.xml.anim_list_missing_list_attrs);
+ mAnimationDrawable.inflate(mResources, parser, Xml.asAttributeSet(parser));
+ // use current the visibility
+ assertFalse(mAnimationDrawable.isVisible());
+ // default value of android:oneShot is false
+ assertFalse(mAnimationDrawable.isOneShot());
+ // default value of android:variablePadding is false
+ assertNotNull(drawableContainerState.getConstantPadding());
+ // add a new frame from xml
+ assertEquals(3, mAnimationDrawable.getNumberOfFrames());
+ assertEquals(2000, mAnimationDrawable.getDuration(0));
+ assertEquals(1000, mAnimationDrawable.getDuration(1));
+ assertEquals(2000, mAnimationDrawable.getDuration(2));
+ assertSame(mAnimationDrawable.getFrame(0), mAnimationDrawable.getCurrent());
+
+ parser = getResourceParser(R.xml.anim_list_missing_item_drawable);
+ try {
+ mAnimationDrawable.inflate(mResources, parser, Xml.asAttributeSet(parser));
+ fail("Should throw XmlPullParserException if drawable of item is missing");
+ } catch (XmlPullParserException e) {
+ // expected
+ }
+ }
+
+ @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 = "should add @throws clause into javadoc of "
+ + "AnimationDrawable#inflate(Resources, XmlPullParser, AttributeSet) "
+ + "when param r, parser or attrs is null")
+ public void testInflateWithNullParameters() throws XmlPullParserException, IOException {
+ XmlResourceParser parser = getResourceParser(R.drawable.animationdrawable);
+ try {
+ mAnimationDrawable.inflate(null, parser, Xml.asAttributeSet(parser));
+ fail("Should throw NullPointerException if resource is null");
+ } catch (NullPointerException e) {
+ // expected
+ }
+
+ try {
+ mAnimationDrawable.inflate(mResources, null, Xml.asAttributeSet(parser));
+ fail("Should throw NullPointerException if parser is null");
+ } catch (NullPointerException e) {
+ // expected
+ }
+
+ try {
+ mAnimationDrawable.inflate(mResources, parser, null);
+ fail("Should throw NullPointerException if AttributeSet is null");
+ } catch (NullPointerException e) {
+ // expected
+ }
+ }
+
+ @TestTargetNew(
+ level = TestLevel.SUFFICIENT,
+ method = "mutate",
+ args = {}
+ )
+ @ToBeFixed(bug = "", explanation = "mutate always throws out NullPointerException")
+ public void testMutate() {
+ AnimationDrawable d1 = (AnimationDrawable) mResources
+ .getDrawable(R.drawable.animationdrawable);
+ // multiple instances inflated from the same resource do not share the state
+ // simply call mutate to make sure it does not throw an exception
+ d1.mutate();
+ }
+
+ private XmlResourceParser getResourceParser(int resId) throws XmlPullParserException,
+ IOException {
+ XmlResourceParser parser = mResources.getXml(resId);
+ int type;
+ while ((type = parser.next()) != XmlPullParser.START_TAG
+ && type != XmlPullParser.END_DOCUMENT) {
+ // Empty loop
+ }
+ return parser;
+ }
+
+ /**
+ * Delayed check specific frame should be current one in timeout.
+ * @param index - expected index of frame.
+ * @param timeout - timeout.
+ */
+ private void delayedCheckDrawable(final int index, long timeout) {
+ new DelayedCheck(timeout + TOLERANCE) {
+ Drawable expected = mAnimationDrawable.getFrame(index);
+ @Override
+ protected boolean check() {
+ return mAnimationDrawable.getCurrent().equals(expected);
+ }
+ }.run();
+ }
+
+ /**
+ * Assert animation had been stopped. It will sleep duration + TOLERANCE milliseconds and
+ * then make sure current frame had not been changed.
+ * @param index - index of current frame.
+ * @param duration - duration of current frame.
+ */
+ private void assertStoppedAnimation(int index, long duration) throws InterruptedException {
+ Thread.sleep(duration + TOLERANCE);
+ assertSame(mAnimationDrawable.getFrame(index), mAnimationDrawable.getCurrent());
+ }
+}