CTS Test cases
Class :  android.animation.ValueAnimator
7 Test cases

Change-Id: I99ca949ba08962a727cad32e583e3e81d78346b6
diff --git a/CtsTestCaseList.mk b/CtsTestCaseList.mk
index df7b03d..3ccf169 100644
--- a/CtsTestCaseList.mk
+++ b/CtsTestCaseList.mk
@@ -31,6 +31,7 @@
 	CtsAccessibilityServiceTestCases \
 	CtsAccountManagerTestCases \
 	CtsAdminTestCases \
+	CtsAnimationTestCases \
 	CtsAppTestCases \
 	CtsBluetoothTestCases \
 	CtsContentTestCases \
diff --git a/tests/tests/animation/Android.mk b/tests/tests/animation/Android.mk
new file mode 100644
index 0000000..ed9874e
--- /dev/null
+++ b/tests/tests/animation/Android.mk
@@ -0,0 +1,34 @@
+# Copyright (C) 2011 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.
+
+LOCAL_PATH:= $(call my-dir)
+
+include $(CLEAR_VARS)
+
+LOCAL_PACKAGE_NAME := CtsAnimationTestCases
+
+# Don't include this package in any target.
+LOCAL_MODULE_TAGS := optional
+
+# When built, explicitly put it in the data partition.
+LOCAL_MODULE_PATH := $(TARGET_OUT_DATA_APPS)
+
+# All tests should include android.test.runner.
+LOCAL_JAVA_LIBRARIES := android.test.runner
+
+LOCAL_SRC_FILES := $(call all-java-files-under, src)
+
+LOCAL_SDK_VERSION := current
+include $(BUILD_PACKAGE)
+
diff --git a/tests/tests/animation/AndroidManifest.xml b/tests/tests/animation/AndroidManifest.xml
new file mode 100644
index 0000000..f3fd898
--- /dev/null
+++ b/tests/tests/animation/AndroidManifest.xml
@@ -0,0 +1,30 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2011 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.
+-->
+
+<manifest xmlns:android="http://schemas.android.com/apk/res/android"
+    package="com.android.cts.animation">
+
+    <application>
+        <activity android:name="android.animation.cts.AnimationActivity"
+            android:label="AnimationActivity"/>
+        <uses-library android:name="android.test.runner" />
+    </application>
+
+    <instrumentation android:name="android.test.InstrumentationTestRunner"
+                     android:targetPackage="com.android.cts.animation"
+                     android:label="CTS tests for android.animation package"/>
+</manifest>
+
diff --git a/tests/tests/animation/res/layout/animation_main.xml b/tests/tests/animation/res/layout/animation_main.xml
new file mode 100644
index 0000000..81356a1
--- /dev/null
+++ b/tests/tests/animation/res/layout/animation_main.xml
@@ -0,0 +1,23 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2011 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.
+-->
+
+<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
+        android:layout_width="match_parent"
+        android:layout_height="match_parent"
+        android:orientation="vertical" >
+    <FrameLayout android:id="@+id/container" android:layout_width="fill_parent"
+            android:layout_height="fill_parent"/>
+</LinearLayout>
diff --git a/tests/tests/animation/src/android/animation/cts/AnimationActivity.java b/tests/tests/animation/src/android/animation/cts/AnimationActivity.java
new file mode 100644
index 0000000..ee3202e
--- /dev/null
+++ b/tests/tests/animation/src/android/animation/cts/AnimationActivity.java
@@ -0,0 +1,206 @@
+/*
+ * Copyright (C) 2011 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.animation.cts;
+
+import android.animation.Animator;
+import android.animation.AnimatorListenerAdapter;
+import android.animation.AnimatorSet;
+import android.animation.ArgbEvaluator;
+import android.animation.ObjectAnimator;
+import android.animation.TimeInterpolator;
+import android.animation.ValueAnimator;
+import android.app.Activity;
+import android.content.Context;
+import android.content.Intent;
+import android.graphics.Canvas;
+import android.graphics.Paint;
+import android.graphics.RadialGradient;
+import android.graphics.Shader;
+import android.graphics.drawable.ShapeDrawable;
+import android.graphics.drawable.shapes.OvalShape;
+import android.os.Bundle;
+import android.view.MotionEvent;
+import android.view.View;
+import android.view.ViewGroup;
+import android.view.animation.AccelerateInterpolator;
+import java.util.ArrayList;
+
+import com.android.cts.animation.R;
+
+public class AnimationActivity extends Activity {
+    private static final String BALL_HEIGHT = "ballwidth";
+    private static final String BALL_WIDTH = "ballheight";
+    private static final String STARTX = "startx";
+    private static final String STARTY = "starty";
+    private static final String DELTAX = "deltax";
+    private static final String DELTAY = "deltay";
+    private static final String DURATION = "duration";
+
+    float mBallHeight = 50f;
+    float mBallWidth = 50f;
+    float mStartX = 200f;
+    float mStartY = 200f;
+    float mDeltaX = 200f;
+    float mDeltaY = 200f;
+    long mDuration = 1000;
+    public AnimationView view = null;
+    private boolean isAnimationRunning = false;
+
+    @Override
+    public void onCreate(Bundle bundle){
+        super.onCreate(bundle);
+        Intent intent = this.getIntent();
+        Bundle extras = intent.getExtras();
+        if(extras != null) {
+            mBallHeight = extras.getFloat(BALL_HEIGHT);
+            mBallWidth = extras.getFloat(BALL_WIDTH);
+            mStartX = extras.getFloat(STARTX);
+            mStartY = extras.getFloat(STARTY);
+            mDeltaX = extras.getFloat(DELTAX);
+            mDeltaY = extras.getFloat(DELTAY);
+            mDuration = extras.getInt(DURATION);
+        }
+        setContentView(R.layout.animation_main);
+        view = new AnimationView(this);
+        ViewGroup viewGroup = (ViewGroup) findViewById(R.id.container);
+        viewGroup.addView(view);
+    }
+
+    public ValueAnimator createAnimator(Object object,String propertyName, long duration,
+            int repeatCount, int repeatMode,
+            TimeInterpolator timeInterpolator, float start, float end){
+        ValueAnimator valueAnimator = ObjectAnimator.ofFloat(object, propertyName, start,end);
+        valueAnimator.setDuration(duration);
+        valueAnimator.setRepeatCount(repeatCount);
+        valueAnimator.setInterpolator(timeInterpolator);
+        valueAnimator.setRepeatMode(repeatMode);
+        return valueAnimator;
+    }
+
+    public ValueAnimator createAnimatorWithRepeatMode(int repeatMode) {
+        return createAnimator(view.newBall, "y", 1000,ValueAnimator.INFINITE, repeatMode,
+                new AccelerateInterpolator(), mStartY, mStartY + mDeltaY);
+    }
+
+    public ValueAnimator createAnimatorWithRepeatCount(int repeatCount) {
+        return createAnimator(view.newBall, "y", 1000,repeatCount, ValueAnimator.REVERSE,
+                new AccelerateInterpolator(), mStartY, mStartY + mDeltaY);
+    }
+
+    public ValueAnimator createAnimatorWithDuration(long duration) {
+        return createAnimator(view.newBall, "y", duration ,ValueAnimator.INFINITE,
+                ValueAnimator.REVERSE,new AccelerateInterpolator(), mStartY, mStartY + mDeltaY);
+    }
+
+    public void startAnimation(long duration){
+        ValueAnimator bounceAnimator = ObjectAnimator.ofFloat(view.newBall, "y", mStartY,
+                mStartY + mDeltaY);
+        bounceAnimator.setDuration(duration);
+        bounceAnimator.setRepeatCount(ValueAnimator.INFINITE);
+        bounceAnimator.setInterpolator(new AccelerateInterpolator());
+        bounceAnimator.setRepeatMode(ValueAnimator.REVERSE);
+        view.bounceAnimator = bounceAnimator;
+        view.animateBall();
+    }
+
+    public void startAnimation(ValueAnimator valueAnimator){
+        view.bounceAnimator = valueAnimator;
+        view.animateBall();
+        isAnimationRunning = true;
+    }
+
+    public class AnimationView extends View {
+        private static final int RED = 0xffFF8080;
+        private static final int BLUE = 0xff8080FF;
+        public ShapeHolder newBall = null;
+        public final ArrayList<ShapeHolder> balls = new ArrayList<ShapeHolder>();
+        AnimatorSet animation = null;
+        public ValueAnimator bounceAnimator;
+
+        public AnimationView(Context context) {
+            super(context);
+            ValueAnimator colorAnim = ObjectAnimator.ofInt(this, "backgroundColor", RED, BLUE);
+            colorAnim.setDuration(1000);
+            colorAnim.setEvaluator(new ArgbEvaluator());
+            colorAnim.setRepeatCount(1);
+            colorAnim.setRepeatMode(ValueAnimator.REVERSE);
+            colorAnim.start();
+            newBall = addBall(mBallHeight, mBallWidth);
+        }
+
+        @Override
+        public boolean onTouchEvent(MotionEvent event) {
+
+
+            return true;
+        }
+
+        public void animateBall() {
+            float startY = mStartY;
+            float endY = startY + mDeltaY;
+            AnimatorSet bouncer = new AnimatorSet();
+            bouncer.play(bounceAnimator);
+            // Fading animation - remove the ball when the animation is done
+            ValueAnimator fadeAnim = ObjectAnimator.ofFloat(newBall, "alpha", 1f, 0f);
+            fadeAnim.setDuration(250);
+            fadeAnim.addListener(new AnimatorListenerAdapter() {
+                @Override
+                public void onAnimationEnd(Animator animation) {
+                    balls.remove(((ObjectAnimator)animation).getTarget());
+                }
+            });
+
+            // Sequence the two animations to play one after the other
+            AnimatorSet animatorSet = new AnimatorSet();
+            animatorSet.play(bouncer).before(fadeAnim);
+            animatorSet.start();
+        }
+
+        private ShapeHolder addBall(float x, float y) {
+            OvalShape circle = new OvalShape();
+            circle.resize(x, y);
+            ShapeDrawable drawable = new ShapeDrawable(circle);
+            ShapeHolder shapeHolder = new ShapeHolder(drawable);
+            shapeHolder.setX(x - 25f);
+            shapeHolder.setY(y - 25f);
+            Paint paint = drawable.getPaint();
+            shapeHolder.setPaint(paint);
+            int red = (int)(Math.random() * 255);
+            int green = (int)(Math.random() * 255);
+            int blue = (int)(Math.random() * 255);
+            int color = 0xff000000 | red << 16 | green << 8 | blue;
+            int darkColor = 0xff000000 | red/4 << 16 | green/4 << 8 | blue/4;
+            RadialGradient gradient = new RadialGradient(37.5f, 12.5f,
+                    50f, color, darkColor, Shader.TileMode.CLAMP);
+            paint.setShader(gradient);
+            balls.add(shapeHolder);
+            return shapeHolder;
+        }
+
+        @Override
+        protected void onDraw(Canvas canvas) {
+            for (int i = 0; i < balls.size(); ++i) {
+                ShapeHolder shapeHolder = balls.get(i);
+                canvas.save();
+                canvas.translate(shapeHolder.getX(), shapeHolder.getY());
+                shapeHolder.getShape().draw(canvas);
+                canvas.restore();
+            }
+        }
+    }
+}
+
diff --git a/tests/tests/animation/src/android/animation/cts/ShapeHolder.java b/tests/tests/animation/src/android/animation/cts/ShapeHolder.java
new file mode 100644
index 0000000..f8d5fa6
--- /dev/null
+++ b/tests/tests/animation/src/android/animation/cts/ShapeHolder.java
@@ -0,0 +1,111 @@
+/*
+ * Copyright (C) 2011 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.animation.cts;
+
+import android.graphics.drawable.ShapeDrawable;
+import android.graphics.drawable.shapes.Shape;
+import android.graphics.Paint;
+import android.graphics.RadialGradient;
+
+/**
+ * A data structure that holds a Shape and various properties that can be used to define
+ * how the shape is drawn.
+ */
+public class ShapeHolder {
+    private float mX = 0, mY = 0;
+    private ShapeDrawable mShape;
+    private int mColor;
+    private RadialGradient mGradient;
+    private float mAlpha = 1f;
+    private Paint mPaint;
+
+    public void setPaint(Paint value) {
+        mPaint = value;
+    }
+
+    public Paint getPaint() {
+        return mPaint;
+    }
+
+    public void setX(float value) {
+        mX = value;
+    }
+
+    public float getX() {
+        return mX;
+    }
+
+    public void setY(float value) {
+        mY = value;
+    }
+
+    public float getY() {
+        return mY;
+    }
+
+    public void setShape(ShapeDrawable value) {
+        mShape = value;
+    }
+
+    public ShapeDrawable getShape() {
+        return mShape;
+    }
+
+    public int getColor() {
+        return mColor;
+    }
+
+    public void setColor(int value) {
+        mShape.getPaint().setColor(value);
+        mColor = value;
+    }
+
+    public void setGradient(RadialGradient value) {
+        mGradient = value;
+    }
+    public RadialGradient getGradient() {
+        return mGradient;
+    }
+
+    public void setAlpha(float alpha) {
+        this.mAlpha = alpha;
+        mShape.setAlpha((int)((alpha * 255f) + .5f));
+    }
+
+    public float getWidth() {
+        return mShape.getShape().getWidth();
+    }
+
+    public void setWidth(float width) {
+        Shape s = mShape.getShape();
+        s.resize(width, s.getHeight());
+    }
+
+    public float getHeight() {
+        return mShape.getShape().getHeight();
+    }
+
+    public void setHeight(float height) {
+        Shape s = mShape.getShape();
+        s.resize(s.getWidth(), height);
+    }
+
+    public ShapeHolder(ShapeDrawable s) {
+        mShape = s;
+    }
+}
+
diff --git a/tests/tests/animation/src/android/animation/cts/ValueAnimatorTest.java b/tests/tests/animation/src/android/animation/cts/ValueAnimatorTest.java
new file mode 100644
index 0000000..314c06d
--- /dev/null
+++ b/tests/tests/animation/src/android/animation/cts/ValueAnimatorTest.java
@@ -0,0 +1,103 @@
+/*
+ * Copyright (C) 2011 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.animation.cts;
+
+import android.animation.ValueAnimator;
+import android.app.Instrumentation;
+import android.content.Intent;
+import android.test.ActivityInstrumentationTestCase2;
+
+public class ValueAnimatorTest extends
+        ActivityInstrumentationTestCase2<AnimationActivity> {
+    private AnimationActivity mActivity;
+    private Instrumentation mInstrumentation;
+    private ValueAnimator mValueAnimator;
+    private long mDuration;
+
+    public ValueAnimatorTest() {
+        super("com.android.cts.animation",AnimationActivity.class);
+    }
+
+    public ValueAnimatorTest(Class<AnimationActivity> activityClass) {
+        super("com.android.cts.animation",AnimationActivity.class);
+    }
+
+    @Override
+    protected void setUp() throws Exception {
+        super.setUp();
+        setActivityInitialTouchMode(false);
+        mActivity = getActivity();
+        mValueAnimator = mActivity.createAnimatorWithDuration(mDuration);
+    }
+
+    public void testDuration() throws Throwable {
+        final long duration = 2000;
+        ValueAnimator valueAnimatorLocal = mActivity.createAnimatorWithDuration(duration);
+        startAnimation(valueAnimatorLocal);
+        assertEquals(duration, valueAnimatorLocal.getDuration());
+    }
+
+    public void testIsRunning() throws Throwable {
+        assertFalse(mValueAnimator.isRunning());
+        startAnimation(mValueAnimator);
+        ValueAnimator valueAnimatorReturned = mActivity.view.bounceAnimator;
+        assertTrue(valueAnimatorReturned.isRunning());
+    }
+
+    public void testRepeatMode() throws Throwable {
+        ValueAnimator mValueAnimator = mActivity.createAnimatorWithRepeatMode(ValueAnimator.RESTART);
+        startAnimation(mValueAnimator);
+        assertEquals(ValueAnimator.RESTART, mValueAnimator.getRepeatMode());
+    }
+
+    public void testRepeatCount() throws Throwable {
+        int repeatCount = 2;
+        ValueAnimator mValueAnimator = mActivity.createAnimatorWithRepeatCount(repeatCount);
+        startAnimation(mValueAnimator);
+        assertEquals(repeatCount, mValueAnimator.getRepeatCount());
+    }
+
+    public void testStartDelay() {
+        long startDelay = 1000;
+        mValueAnimator.setStartDelay(startDelay);
+        assertEquals(startDelay, mValueAnimator.getStartDelay());
+    }
+
+    public void testCurrentPlayTime() throws Throwable {
+        startAnimation(mValueAnimator);
+        Thread.sleep(100);
+        long currentPlayTime = mValueAnimator.getCurrentPlayTime();
+        assertTrue(currentPlayTime  >  0);
+    }
+
+    public void testGetFrameDelay() throws Throwable {
+        long frameDelay = 10;
+        mValueAnimator.setFrameDelay(frameDelay);
+        startAnimation(mValueAnimator);
+        Thread.sleep(100);
+        long actualFrameDelay = mValueAnimator.getFrameDelay();
+        assertEquals(frameDelay, actualFrameDelay);
+    }
+
+    private void startAnimation(final ValueAnimator mValueAnimator) throws Throwable {
+        this.runTestOnUiThread(new Runnable(){
+            public void run(){
+                mActivity.startAnimation(mValueAnimator);
+            }
+        });
+    }
+}
+