Add zoom functions and sendCommand.

b2060030
diff --git a/camera/libcameraservice/CameraHardwareStub.cpp b/camera/libcameraservice/CameraHardwareStub.cpp
index 35f4846..8ad1f69 100644
--- a/camera/libcameraservice/CameraHardwareStub.cpp
+++ b/camera/libcameraservice/CameraHardwareStub.cpp
@@ -368,6 +368,12 @@
     return mParameters;
 }
 
+status_t CameraHardwareStub::sendCommand(int32_t command, int32_t arg1,
+                                         int32_t arg2)
+{
+    return BAD_VALUE;
+}
+
 void CameraHardwareStub::release()
 {
 }
diff --git a/camera/libcameraservice/CameraHardwareStub.h b/camera/libcameraservice/CameraHardwareStub.h
index f957fa8..8a67024 100644
--- a/camera/libcameraservice/CameraHardwareStub.h
+++ b/camera/libcameraservice/CameraHardwareStub.h
@@ -57,6 +57,8 @@
     virtual status_t    dump(int fd, const Vector<String16>& args) const;
     virtual status_t    setParameters(const CameraParameters& params);
     virtual CameraParameters  getParameters() const;
+    virtual status_t    sendCommand(int32_t command, int32_t arg1,
+                                    int32_t arg2);
     virtual void release();
 
     static sp<CameraHardwareInterface> createInstance();
diff --git a/camera/libcameraservice/CameraService.cpp b/camera/libcameraservice/CameraService.cpp
index bab7d08..8279914 100644
--- a/camera/libcameraservice/CameraService.cpp
+++ b/camera/libcameraservice/CameraService.cpp
@@ -195,7 +195,7 @@
     android_atomic_dec(&mUsers);
 }
 
-static sp<MediaPlayer> newMediaPlayer(const char *file) 
+static sp<MediaPlayer> newMediaPlayer(const char *file)
 {
     sp<MediaPlayer> mp = new MediaPlayer();
     if (mp->setDataSource(file) == NO_ERROR) {
@@ -267,7 +267,7 @@
 status_t CameraService::Client::unlock()
 {
     int callingPid = getCallingPid();
-    LOGD("unlock from pid %d (mClientPid %d)", callingPid, mClientPid);    
+    LOGD("unlock from pid %d (mClientPid %d)", callingPid, mClientPid);
     Mutex::Autolock _l(mLock);
     // allow anyone to use camera
     status_t result = checkPid();
@@ -648,7 +648,7 @@
 status_t CameraService::Client::startPreview()
 {
     LOGD("startPreview (pid %d)", getCallingPid());
-    
+
     return startCameraMode(CAMERA_PREVIEW_MODE);
 }
 
@@ -1134,6 +1134,21 @@
     return params;
 }
 
+status_t CameraService::Client::sendCommand(int32_t cmd, int32_t arg1, int32_t arg2)
+{
+    LOGD("sendCommand (pid %d)", getCallingPid());
+    Mutex::Autolock lock(mLock);
+    status_t result = checkPid();
+    if (result != NO_ERROR) return result;
+
+    if (mHardware == 0) {
+        LOGE("mHardware is NULL, returning.");
+        return INVALID_OPERATION;
+    }
+
+    return mHardware->sendCommand(cmd, arg1, arg2);
+}
+
 void CameraService::Client::copyFrameAndPostCopiedFrame(sp<IMemoryHeap> heap, size_t offset, size_t size)
 {
     LOGV("copyFrameAndPostCopiedFrame");
diff --git a/camera/libcameraservice/CameraService.h b/camera/libcameraservice/CameraService.h
index 0a909cf..2e3597f 100644
--- a/camera/libcameraservice/CameraService.h
+++ b/camera/libcameraservice/CameraService.h
@@ -122,6 +122,9 @@
         // get preview/capture parameters - key/value pairs
         virtual String8         getParameters() const;
 
+        // send command to camera driver
+        virtual status_t        sendCommand(int32_t cmd, int32_t arg1, int32_t arg2);
+
         // our client...
         const sp<ICameraClient>&    getCameraClient() const { return mCameraClient; }
 
diff --git a/core/java/android/hardware/Camera.java b/core/java/android/hardware/Camera.java
index 66f5740..3806fa8 100644
--- a/core/java/android/hardware/Camera.java
+++ b/core/java/android/hardware/Camera.java
@@ -301,7 +301,7 @@
 
             case CAMERA_MSG_ZOOM:
                 if (mZoomCallback != null) {
-                    mZoomCallback.onZoomUpdate(msg.arg1, mCamera);
+                    mZoomCallback.onZoomUpdate(msg.arg1, msg.arg2 != 0, mCamera);
                 }
                 return;
 
@@ -468,6 +468,26 @@
     }
 
     /**
+     * Zooms to the requested value smoothly. Driver will generate {@link
+     * #ZoomCallback} for the current zoom value and whether zoom is stopped.
+     * The applications can call {@link #stopSmoothZoom} to stop the zoom
+     * earlier. The applications should not call startSmoothZoom again or {@link
+     * android.hardware.Camera.Parameters#setZoom(int)} before the zoom stops.
+     *
+     * @param value zoom value. The valid range is 0 to {@link
+     *              android.hardware.Camera.Parameters#getMaxZoom}.
+     * @hide
+     */
+    public native final void startSmoothZoom(int value);
+
+    /**
+     * Stops the smooth zoom. The applications should wait for the {@link
+     * #ZoomCallback} to know when the zoom is actually stopped.
+     * @hide
+     */
+    public native final void stopSmoothZoom();
+
+    /**
      * Handles the zoom callback.
      *
      * @hide
@@ -476,18 +496,21 @@
     {
         /**
          * Callback for zoom updates
-         * @param zoomLevel   new zoom level in 1/1000 increments,
-         * e.g. a zoom of 3.2x is stored as 3200. Accuracy of the
-         * value is dependent on the hardware implementation. Not
-         * all devices will generate this callback.
+         *
+         * @param zoomValue the current zoom value. In smooth zoom mode, camera
+         *                  generates this callback for every new zoom value.
+         * @param stopped whether smooth zoom is stopped. If the value is true,
+         *                this is the last zoom update for the application.
+         *
          * @param camera  the Camera service object
+         * @see android.hardware.Camera.Parameters#startSmoothZoom
          */
-        void onZoomUpdate(int zoomLevel, Camera camera);
+        void onZoomUpdate(int zoomValue, boolean stopped, Camera camera);
     };
 
     /**
-     * Registers a callback to be invoked when the zoom
-     * level is updated by the camera driver.
+     * Registers a callback to be invoked when the zoom value is updated by the
+     * camera driver during smooth zoom.
      * @param cb the callback to run
      * @hide
      */
@@ -642,20 +665,24 @@
          * Flash will not be fired.
          */
         public static final String FLASH_MODE_OFF = "off";
+
         /**
          * Flash will be fired automatically when required. The flash may be fired
          * during preview, auto-focus, or snapshot depending on the driver.
          */
         public static final String FLASH_MODE_AUTO = "auto";
+
         /**
          * Flash will always be fired during snapshot. The flash may also be
          * fired during preview or auto-focus depending on the driver.
          */
         public static final String FLASH_MODE_ON = "on";
+
         /**
          * Flash will be fired in red-eye reduction mode.
          */
         public static final String FLASH_MODE_RED_EYE = "red-eye";
+
         /**
          * Constant emission of light during preview, auto-focus and snapshot.
          * This can also be used for video recording.
@@ -684,12 +711,14 @@
          * Auto-focus mode.
          */
         public static final String FOCUS_MODE_AUTO = "auto";
+
         /**
          * Focus is set at infinity. Applications should not call
          * {@link #autoFocus(AutoFocusCallback)} in this mode.
          */
         public static final String FOCUS_MODE_INFINITY = "infinity";
         public static final String FOCUS_MODE_MACRO = "macro";
+
         /**
          * Focus is fixed. The camera is always in this mode if the focus is not
          * adjustable. If the camera has auto-focus, this mode can fix the
@@ -1367,6 +1396,80 @@
             return split(str);
         }
 
+        /**
+         * Gets current zoom value. This also works when smooth zoom is in
+         * progress.
+         *
+         * @return the current zoom value. The range is 0 to {@link
+         *          #getMaxZoom}.
+         * @hide
+         */
+        public int getZoom() {
+            return getInt("zoom");
+        }
+
+        /**
+         * Sets current zoom value. If {@link #startSmoothZoom(int)} has been
+         * called and zoom is not stopped yet, applications should not call this
+         * method.
+         *
+         * @param value zoom value. The valid range is 0 to {@link #getMaxZoom}.
+         * @hide
+         */
+        public void setZoom(int value) {
+            set("zoom", value);
+        }
+
+        /**
+         * Returns true if zoom is supported. Applications should call this
+         * before using other zoom methods.
+         *
+         * @return true if zoom is supported.
+         * @hide
+         */
+        public boolean isZoomSupported() {
+            String str = get("zoom-supported");
+            return "true".equals(str);
+        }
+
+        /**
+         * Gets the maximum zoom value allowed for snapshot. This is the maximum
+         * value that applications can set to {@link #setZoom(int)}.
+         *
+         * @return the maximum zoom value supported by the camera.
+         * @hide
+         */
+        public int getMaxZoom() {
+            return getInt("max-zoom");
+        }
+
+        /**
+         * Gets the zoom factors of all zoom values.
+         *
+         * @return the zoom factors in 1/100 increments. Ex: a zoom of 3.2x is
+         *         returned as 320. Accuracy of the value is dependent on the
+         *         hardware implementation. The first element of the list is the
+         *         zoom factor of first zoom value. If the first zoom value is
+         *         0, the zoom factor should be 100. The last element is the
+         *         zoom factor of zoom value {@link #getMaxZoom}.
+         * @hide
+         */
+        public List<Integer> getZoomFactors() {
+            return splitInt(get("zoom-factors"));
+        }
+
+        /**
+         * Returns true if smooth zoom is supported. Applications should call
+         * this before using other smooth zoom methods.
+         *
+         * @return true if smooth zoom is supported.
+         * @hide
+         */
+        public boolean isSmoothZoomSupported() {
+            String str = get("smooth-zoom-supported");
+            return "true".equals(str);
+        }
+
         // Splits a comma delimited string to an ArrayList of String.
         // Return null if the passing string is null or the size is 0.
         private ArrayList<String> split(String str) {
diff --git a/core/jni/android_hardware_Camera.cpp b/core/jni/android_hardware_Camera.cpp
index e944654..5b6bd35 100644
--- a/core/jni/android_hardware_Camera.cpp
+++ b/core/jni/android_hardware_Camera.cpp
@@ -413,6 +413,28 @@
     }
 }
 
+static void android_hardware_Camera_startSmoothZoom(JNIEnv *env, jobject thiz, jint value)
+{
+    LOGD("startSmoothZoom");
+    sp<Camera> camera = get_native_camera(env, thiz, NULL);
+    if (camera == 0) return;
+
+    if (camera->sendCommand(CAMERA_CMD_START_SMOOTH_ZOOM, value, 0) != NO_ERROR) {
+        jniThrowException(env, "java/lang/RuntimeException", "start smooth zoom failed");
+    }
+}
+
+static void android_hardware_Camera_stopSmoothZoom(JNIEnv *env, jobject thiz)
+{
+    LOGD("stopSmoothZoom");
+    sp<Camera> camera = get_native_camera(env, thiz, NULL);
+    if (camera == 0) return;
+
+    if (camera->sendCommand(CAMERA_CMD_STOP_SMOOTH_ZOOM, 0, 0) != NO_ERROR) {
+        jniThrowException(env, "java/lang/RuntimeException", "stop smooth zoom failed");
+    }
+}
+
 //-------------------------------------------------
 
 static JNINativeMethod camMethods[] = {
@@ -461,6 +483,12 @@
   { "unlock",
     "()V",
     (void*)android_hardware_Camera_unlock },
+  { "startSmoothZoom",
+    "(I)V",
+    (void *)android_hardware_Camera_startSmoothZoom },
+  { "stopSmoothZoom",
+    "()V",
+    (void *)android_hardware_Camera_stopSmoothZoom },
 };
 
 struct field {
diff --git a/include/ui/Camera.h b/include/ui/Camera.h
index 9ceb8fd..5219772 100644
--- a/include/ui/Camera.h
+++ b/include/ui/Camera.h
@@ -78,6 +78,12 @@
     CAMERA_MSG_ALL_MSGS         = 0x1FF
 };
 
+// cmdType in sendCommand functions
+enum {
+    CAMERA_CMD_START_SMOOTH_ZOOM     = 1,
+    CAMERA_CMD_STOP_SMOOTH_ZOOM      = 2,
+};
+
 // camera fatal errors
 enum {
     CAMERA_ERROR_UKNOWN  = 1,
@@ -155,6 +161,9 @@
             // get preview/capture parameters - key/value pairs
             String8     getParameters() const;
 
+            // send command to camera driver
+            status_t    sendCommand(int32_t cmd, int32_t arg1, int32_t arg2);
+
             void        setListener(const sp<CameraListener>& listener);
             void        setPreviewCallbackFlags(int preview_callback_flag);
 
diff --git a/include/ui/CameraHardwareInterface.h b/include/ui/CameraHardwareInterface.h
index 5fbb7d8..af40f31 100644
--- a/include/ui/CameraHardwareInterface.h
+++ b/include/ui/CameraHardwareInterface.h
@@ -147,7 +147,7 @@
      * Returns true if recording is enabled.
      */
     virtual bool        recordingEnabled() = 0;
-    
+
     /**
      * Release a record frame previously returned by CAMERA_MSG_VIDEO_FRAME.
      */
@@ -186,11 +186,16 @@
     virtual CameraParameters  getParameters() const = 0;
 
     /**
+     * Send command to camera driver.
+     */
+    virtual status_t sendCommand(int32_t cmd, int32_t arg1, int32_t arg2) = 0;
+
+    /**
      * Release the hardware resources owned by this object.  Note that this is
      * *not* done in the destructor.
      */
     virtual void release() = 0;
-    
+
     /**
      * Dump state of the camera hardware
      */
diff --git a/include/ui/ICamera.h b/include/ui/ICamera.h
index 7595e36..5642691 100644
--- a/include/ui/ICamera.h
+++ b/include/ui/ICamera.h
@@ -87,6 +87,9 @@
 
     // get preview/capture parameters - key/value pairs
     virtual String8         getParameters() const = 0;
+
+    // send command to camera driver
+    virtual status_t        sendCommand(int32_t cmd, int32_t arg1, int32_t arg2) = 0;
 };
 
 // ----------------------------------------------------------------------------
diff --git a/libs/ui/Camera.cpp b/libs/ui/Camera.cpp
index 0c6d340..09a36f1 100644
--- a/libs/ui/Camera.cpp
+++ b/libs/ui/Camera.cpp
@@ -278,6 +278,15 @@
     return params;
 }
 
+// send command to camera driver
+status_t Camera::sendCommand(int32_t cmd, int32_t arg1, int32_t arg2)
+{
+    LOGD("sendCommand");
+    sp <ICamera> c = mCamera;
+    if (c == 0) return NO_INIT;
+    return c->sendCommand(cmd, arg1, arg2);
+}
+
 void Camera::setListener(const sp<CameraListener>& listener)
 {
     Mutex::Autolock _l(mLock);
diff --git a/libs/ui/ICamera.cpp b/libs/ui/ICamera.cpp
index fd7e084..e1b3ec7 100644
--- a/libs/ui/ICamera.cpp
+++ b/libs/ui/ICamera.cpp
@@ -36,6 +36,7 @@
     TAKE_PICTURE,
     SET_PARAMETERS,
     GET_PARAMETERS,
+    SEND_COMMAND,
     CONNECT,
     LOCK,
     UNLOCK,
@@ -205,6 +206,17 @@
         remote()->transact(GET_PARAMETERS, data, &reply);
         return reply.readString8();
     }
+    virtual status_t sendCommand(int32_t cmd, int32_t arg1, int32_t arg2)
+    {
+        LOGD("sendCommand");
+        Parcel data, reply;
+        data.writeInterfaceToken(ICamera::getInterfaceDescriptor());
+        data.writeInt32(cmd);
+        data.writeInt32(arg1);
+        data.writeInt32(arg2);
+        remote()->transact(SEND_COMMAND, data, &reply);
+        return reply.readInt32();
+    }
     virtual status_t connect(const sp<ICameraClient>& cameraClient)
     {
         Parcel data, reply;
@@ -331,6 +343,15 @@
              reply->writeString8(getParameters());
             return NO_ERROR;
          } break;
+        case SEND_COMMAND: {
+            LOGD("SEND_COMMAND");
+            CHECK_INTERFACE(ICamera, data, reply);
+            int command = data.readInt32();
+            int arg1 = data.readInt32();
+            int arg2 = data.readInt32();
+            reply->writeInt32(sendCommand(command, arg1, arg2));
+            return NO_ERROR;
+         } break;
         case CONNECT: {
             CHECK_INTERFACE(ICamera, data, reply);
             sp<ICameraClient> cameraClient = interface_cast<ICameraClient>(data.readStrongBinder());