Add a new Camera API to control the camera's location

Change-Id: Id9a082d2def803eb527e1987875e0d8a22c6e8aa
diff --git a/api/current.xml b/api/current.xml
index a36f066..cd827a6 100644
--- a/api/current.xml
+++ b/api/current.xml
@@ -77585,6 +77585,23 @@
  visibility="public"
 >
 </method>
+<method name="rotate"
+ return="void"
+ abstract="false"
+ native="true"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="x" type="float">
+</parameter>
+<parameter name="y" type="float">
+</parameter>
+<parameter name="z" type="float">
+</parameter>
+</method>
 <method name="rotateX"
  return="void"
  abstract="false"
@@ -77635,6 +77652,23 @@
  visibility="public"
 >
 </method>
+<method name="setLocation"
+ return="void"
+ abstract="false"
+ native="true"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="x" type="float">
+</parameter>
+<parameter name="y" type="float">
+</parameter>
+<parameter name="z" type="float">
+</parameter>
+</method>
 <method name="translate"
  return="void"
  abstract="false"
@@ -266659,7 +266693,7 @@
  deprecated="not deprecated"
  visibility="public"
 >
-<parameter name="t" type="T">
+<parameter name="arg0" type="T">
 </parameter>
 </method>
 </interface>
diff --git a/core/java/android/view/View.java b/core/java/android/view/View.java
index ae06888..e00b9cd 100644
--- a/core/java/android/view/View.java
+++ b/core/java/android/view/View.java
@@ -5748,9 +5748,7 @@
                 }
                 mCamera.save();
                 mMatrix.preScale(mScaleX, mScaleY, mPivotX, mPivotY);
-                mCamera.rotateX(mRotationX);
-                mCamera.rotateY(mRotationY);
-                mCamera.rotateZ(-mRotation);
+                mCamera.rotate(mRotationX, mRotationY, -mRotation);
                 mCamera.getMatrix(matrix3D);
                 matrix3D.preTranslate(-mPivotX, -mPivotY);
                 matrix3D.postTranslate(mPivotX + mTranslationX, mPivotY + mTranslationY);
diff --git a/core/jni/android/graphics/Camera.cpp b/core/jni/android/graphics/Camera.cpp
index 980003e..0d715fd 100644
--- a/core/jni/android/graphics/Camera.cpp
+++ b/core/jni/android/graphics/Camera.cpp
@@ -45,6 +45,18 @@
     v->rotateZ(SkFloatToScalar(degrees));
 }
 
+static void Camera_rotate(JNIEnv* env, jobject obj, jfloat x, jfloat y, jfloat z) {
+    Sk3DView* v = (Sk3DView*)env->GetIntField(obj, gNativeInstanceFieldID);
+    v->rotateX(SkFloatToScalar(x));
+    v->rotateY(SkFloatToScalar(y));
+    v->rotateZ(SkFloatToScalar(z));
+}
+
+static void Camera_setLocation(JNIEnv* env, jobject obj, jfloat x, jfloat y, jfloat z) {
+    Sk3DView* v = (Sk3DView*)env->GetIntField(obj, gNativeInstanceFieldID);
+    v->setCameraLocation(SkFloatToScalar(x), SkFloatToScalar(y), SkFloatToScalar(z));
+}
+
 static void Camera_getMatrix(JNIEnv* env, jobject obj, int native_matrix) {
     Sk3DView* v = (Sk3DView*)env->GetIntField(obj, gNativeInstanceFieldID);
     v->getMatrix((SkMatrix*)native_matrix);
@@ -79,6 +91,8 @@
     { "rotateX",             "(F)V",   (void*)Camera_rotateX       },
     { "rotateY",             "(F)V",   (void*)Camera_rotateY       },
     { "rotateZ",             "(F)V",   (void*)Camera_rotateZ       },
+    { "rotate",              "(FFF)V", (void*)Camera_rotate        },
+    { "setLocation",         "(FFF)V", (void*)Camera_setLocation   },
     { "nativeGetMatrix",     "(I)V",   (void*)Camera_getMatrix     },
     { "nativeApplyToCanvas", "(I)V",   (void*)Camera_applyToCanvas },
     { "dotWithNormal",       "(FFF)F", (void*)Camera_dotWithNormal }
diff --git a/graphics/java/android/graphics/Camera.java b/graphics/java/android/graphics/Camera.java
index 530655f..7ef35a9 100644
--- a/graphics/java/android/graphics/Camera.java
+++ b/graphics/java/android/graphics/Camera.java
@@ -16,24 +16,115 @@
 
 package android.graphics;
 
-
+/**
+ * A camera instance can be used to compute 3D transformations and
+ * generate a matrix that can be applied, for instance, on a
+ * {@link Canvas}.
+ */
 public class Camera {
-
+    /**
+     * Creates a new camera, with empty transformations.
+     */
     public Camera() {
         nativeConstructor();
     }
 
+    /**
+     * Saves the camera state. Each save should be balanced
+     * with a call to {@link #restore()}.
+     * 
+     * @see #save() 
+     */
     public native void save();
+
+    /**
+     * Restores the saved state, if any.
+     * 
+     * @see #restore() 
+     */
     public native void restore();
 
+    /**
+     * Applies a translation transform on all three axis.
+     * 
+     * @param x The distance to translate by on the X axis
+     * @param y The distance to translate by on the Y axis
+     * @param z The distance to translate by on the Z axis
+     */
     public native void translate(float x, float y, float z);
+
+    /**
+     * Applies a rotation transform around the X axis.
+     * 
+     * @param deg The angle of rotation around the X axis, in degrees
+     * 
+     * @see #rotateY(float)
+     * @see #rotateZ(float)
+     * @see #rotate(float, float, float)
+     */
     public native void rotateX(float deg);
+
+    /**
+     * Applies a rotation transform around the Y axis.
+     * 
+     * @param deg The angle of rotation around the Y axis, in degrees
+     * 
+     * @see #rotateX(float)
+     * @see #rotateZ(float)
+     * @see #rotate(float, float, float) 
+     */
     public native void rotateY(float deg);
+
+    /**
+     * Applies a rotation transform around the Z axis.
+     * 
+     * @param deg The angle of rotation around the Z axis, in degrees
+     * 
+     * @see #rotateX(float)
+     * @see #rotateY(float)
+     * @see #rotate(float, float, float)
+     */    
     public native void rotateZ(float deg);
 
+    /**
+     * Applies a rotation transform around all three axis.
+     * 
+     * @param x The angle of rotation around the X axis, in degrees
+     * @param y The angle of rotation around the Y axis, in degrees
+     * @param z The angle of rotation around the Z axis, in degrees
+     * 
+     * @see #rotateX(float)
+     * @see #rotateY(float)
+     * @see #rotateZ(float)
+     */
+    public native void rotate(float x, float y, float z);
+
+    /**
+     * Sets the location of the camera. The default location is set at
+     * 0, 0, -8.
+     * 
+     * @param x The x location of the camera
+     * @param y The y location of the camera
+     * @param z The z location of the camera
+     */
+    public native void setLocation(float x, float y, float z);
+
+    /**
+     * Computes the matrix corresponding to the current transformation
+     * and copies it to the supplied matrix object.
+     * 
+     * @param matrix The matrix to copy the current transforms into
+     */
     public void getMatrix(Matrix matrix) {
         nativeGetMatrix(matrix.native_instance);
     }
+
+    /**
+     * Computes the matrix corresponding to the current transformation
+     * and applies it to the specified Canvas.
+     * 
+     * @param canvas The Canvas to set the transform matrix onto
+     */
     public void applyToCanvas(Canvas canvas) {
         nativeApplyToCanvas(canvas.mNativeCanvas);
     }
@@ -41,7 +132,11 @@
     public native float dotWithNormal(float dx, float dy, float dz);
     
     protected void finalize() throws Throwable {
-        nativeDestructor();
+        try {
+            nativeDestructor();
+        } finally {
+            super.finalize();
+        }
     }
 
     private native void nativeConstructor();
@@ -51,4 +146,3 @@
     
     int native_instance;
 }
-
diff --git a/tests/HwAccelerationTest/AndroidManifest.xml b/tests/HwAccelerationTest/AndroidManifest.xml
index ae7ec45..e82f9aa 100644
--- a/tests/HwAccelerationTest/AndroidManifest.xml
+++ b/tests/HwAccelerationTest/AndroidManifest.xml
@@ -397,6 +397,16 @@
         </activity>
 
         <activity
+                android:name="Animated3dActivity"
+                android:label="_Animated 3d"
+                android:theme="@android:style/Theme.Translucent.NoTitleBar">
+            <intent-filter>
+                <action android:name="android.intent.action.MAIN" />
+                <category android:name="android.intent.category.LAUNCHER" />
+            </intent-filter>
+        </activity>
+
+        <activity
                 android:name="SimplePathsActivity"
                 android:label="_SimplePaths">
             <intent-filter>
diff --git a/tests/HwAccelerationTest/res/drawable-nodpi/large_photo.jpg b/tests/HwAccelerationTest/res/drawable-nodpi/large_photo.jpg
new file mode 100644
index 0000000..e23dbb0
--- /dev/null
+++ b/tests/HwAccelerationTest/res/drawable-nodpi/large_photo.jpg
Binary files differ
diff --git a/tests/HwAccelerationTest/src/com/android/test/hwui/Animated3dActivity.java b/tests/HwAccelerationTest/src/com/android/test/hwui/Animated3dActivity.java
new file mode 100644
index 0000000..f632c83
--- /dev/null
+++ b/tests/HwAccelerationTest/src/com/android/test/hwui/Animated3dActivity.java
@@ -0,0 +1,51 @@
+/*
+ * Copyright (C) 2010 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 com.android.test.hwui;
+
+import android.animation.ObjectAnimator;
+import android.app.Activity;
+import android.content.Context;
+import android.graphics.Bitmap;
+import android.graphics.BitmapFactory;
+import android.graphics.Camera;
+import android.graphics.Canvas;
+import android.graphics.Matrix;
+import android.os.Bundle;
+import android.view.View;
+import android.widget.FrameLayout;
+import android.widget.ImageView;
+
+@SuppressWarnings({"UnusedDeclaration"})
+public class Animated3dActivity extends Activity {
+    @Override
+    protected void onCreate(Bundle savedInstanceState) {
+        super.onCreate(savedInstanceState);
+
+        ImageView view = new ImageView(this);
+        view.setImageResource(R.drawable.large_photo);
+
+        setContentView(view, new FrameLayout.LayoutParams(
+                FrameLayout.LayoutParams.MATCH_PARENT, FrameLayout.LayoutParams.MATCH_PARENT
+        ));
+
+        ObjectAnimator animator = ObjectAnimator.ofFloat(view, "rotationY", 0.0f, 360.0f);
+        animator.setDuration(4000);
+        animator.setRepeatCount(ObjectAnimator.INFINITE);
+        animator.setRepeatMode(ObjectAnimator.REVERSE);
+        animator.start();
+    }
+}