Add camera service support for SurfaceTexture.

This change enables the use of a SurfaceTexture in place of a Surface as
the destination of camera preview frames.

Change-Id: Ic70d404c8fe261e9d5da6f1de93d6babb5b191cb
diff --git a/camera/Android.mk b/camera/Android.mk
index 03ff229..2f16923 100644
--- a/camera/Android.mk
+++ b/camera/Android.mk
@@ -14,7 +14,8 @@
 	libbinder \
 	libhardware \
 	libsurfaceflinger_client \
-	libui
+	libui \
+	libgui
 
 LOCAL_MODULE:= libcamera_client
 
diff --git a/camera/Camera.cpp b/camera/Camera.cpp
index ab626ad..907f119 100644
--- a/camera/Camera.cpp
+++ b/camera/Camera.cpp
@@ -182,6 +182,20 @@
     }
 }
 
+// pass the buffered ISurfaceTexture to the camera service
+status_t Camera::setPreviewTexture(const sp<ISurfaceTexture>& surfaceTexture)
+{
+    LOGV("setPreviewTexture(%p)", surfaceTexture.get());
+    sp <ICamera> c = mCamera;
+    if (c == 0) return NO_INIT;
+    if (surfaceTexture != 0) {
+        return c->setPreviewTexture(surfaceTexture);
+    } else {
+        LOGD("app passed NULL surface");
+        return c->setPreviewTexture(0);
+    }
+}
+
 // start preview mode
 status_t Camera::startPreview()
 {
diff --git a/camera/ICamera.cpp b/camera/ICamera.cpp
index 7ba8d12..0881d65 100644
--- a/camera/ICamera.cpp
+++ b/camera/ICamera.cpp
@@ -28,6 +28,7 @@
 enum {
     DISCONNECT = IBinder::FIRST_CALL_TRANSACTION,
     SET_PREVIEW_DISPLAY,
+    SET_PREVIEW_TEXTURE,
     SET_PREVIEW_CALLBACK_FLAG,
     START_PREVIEW,
     STOP_PREVIEW,
@@ -78,6 +79,18 @@
         return reply.readInt32();
     }
 
+    // pass the buffered SurfaceTexture to the camera service
+    status_t setPreviewTexture(const sp<ISurfaceTexture>& surfaceTexture)
+    {
+        LOGV("setPreviewTexture");
+        Parcel data, reply;
+        data.writeInterfaceToken(ICamera::getInterfaceDescriptor());
+        sp<IBinder> b(surfaceTexture->asBinder());
+        data.writeStrongBinder(b);
+        remote()->transact(SET_PREVIEW_TEXTURE, data, &reply);
+        return reply.readInt32();
+    }
+
     // set the preview callback flag to affect how the received frames from
     // preview are handled. See Camera.h for details.
     void setPreviewCallbackFlag(int flag)
@@ -296,6 +309,13 @@
             reply->writeInt32(setPreviewDisplay(surface));
             return NO_ERROR;
         } break;
+        case SET_PREVIEW_TEXTURE: {
+            LOGV("SET_PREVIEW_TEXTURE");
+            CHECK_INTERFACE(ICamera, data, reply);
+            sp<ISurfaceTexture> st = interface_cast<ISurfaceTexture>(data.readStrongBinder());
+            reply->writeInt32(setPreviewTexture(st));
+            return NO_ERROR;
+        } break;
         case SET_PREVIEW_CALLBACK_FLAG: {
             LOGV("SET_PREVIEW_CALLBACK_TYPE");
             CHECK_INTERFACE(ICamera, data, reply);
diff --git a/include/camera/Camera.h b/include/camera/Camera.h
index c95f31e..e5f7e62 100644
--- a/include/camera/Camera.h
+++ b/include/camera/Camera.h
@@ -19,6 +19,7 @@
 
 #include <utils/Timers.h>
 #include <camera/ICameraClient.h>
+#include <gui/ISurfaceTexture.h>
 
 namespace android {
 
@@ -175,6 +176,9 @@
             // pass the buffered Surface to the camera service
             status_t    setPreviewDisplay(const sp<Surface>& surface);
 
+            // pass the buffered ISurfaceTexture to the camera service
+            status_t    setPreviewTexture(const sp<ISurfaceTexture>& surfaceTexture);
+
             // start preview mode, must call setPreviewDisplay first
             status_t    startPreview();
 
diff --git a/include/camera/ICamera.h b/include/camera/ICamera.h
index b69e075..b2310a6 100644
--- a/include/camera/ICamera.h
+++ b/include/camera/ICamera.h
@@ -24,6 +24,7 @@
 #include <binder/IMemory.h>
 #include <utils/String8.h>
 #include <camera/Camera.h>
+#include <gui/ISurfaceTexture.h>
 
 namespace android {
 
@@ -48,6 +49,10 @@
     // pass the buffered Surface to the camera service
     virtual status_t        setPreviewDisplay(const sp<Surface>& surface) = 0;
 
+    // pass the buffered ISurfaceTexture to the camera service
+    virtual status_t        setPreviewTexture(
+            const sp<ISurfaceTexture>& surfaceTexture) = 0;
+
     // set the preview callback flag to affect how the received frames from
     // preview are handled.
     virtual void            setPreviewCallbackFlag(int flag) = 0;
diff --git a/services/camera/libcameraservice/Android.mk b/services/camera/libcameraservice/Android.mk
index 87975af..b52fc69 100644
--- a/services/camera/libcameraservice/Android.mk
+++ b/services/camera/libcameraservice/Android.mk
@@ -49,7 +49,8 @@
     libcutils \
     libmedia \
     libcamera_client \
-    libsurfaceflinger_client
+    libsurfaceflinger_client \
+    libgui
 
 LOCAL_MODULE:= libcameraservice
 
diff --git a/services/camera/libcameraservice/CameraService.cpp b/services/camera/libcameraservice/CameraService.cpp
index 15f6a44..3d8ca7a 100644
--- a/services/camera/libcameraservice/CameraService.cpp
+++ b/services/camera/libcameraservice/CameraService.cpp
@@ -27,6 +27,7 @@
 #include <binder/MemoryHeapBase.h>
 #include <cutils/atomic.h>
 #include <cutils/properties.h>
+#include <gui/SurfaceTextureClient.h>
 #include <hardware/hardware.h>
 #include <media/AudioSystem.h>
 #include <media/mediaplayer.h>
@@ -306,6 +307,8 @@
     mCameraFacing = cameraFacing;
     mClientPid = clientPid;
     mMsgEnabled = 0;
+    mSurface = 0;
+    mPreviewWindow = 0;
     mHardware->setCallbacks(notifyCallback,
                             dataCallback,
                             dataCallbackTimestamp,
@@ -470,19 +473,16 @@
 
     // return if no change in surface.
     // asBinder() is safe on NULL (returns NULL)
-    if (getISurface(surface)->asBinder() == mSurface->asBinder()) {
+    if (getISurface(surface)->asBinder() == mSurface) {
         return result;
     }
 
     if (mSurface != 0) {
         LOG1("clearing old preview surface %p", mSurface.get());
     }
-    if (surface != 0) {
-        mSurface = getISurface(surface);
-    } else {
-        mSurface = 0;
-    }
+    mSurface = getISurface(surface)->asBinder();
     mPreviewWindow = surface;
+
     // If preview has been already started, register preview
     // buffers now.
     if (mHardware->previewEnabled()) {
@@ -496,6 +496,45 @@
     return result;
 }
 
+// set the SurfaceTexture that the preview will use
+status_t CameraService::Client::setPreviewTexture(
+        const sp<ISurfaceTexture>& surfaceTexture) {
+    LOG1("setPreviewTexture(%p) (pid %d)", surfaceTexture.get(),
+            getCallingPid());
+    Mutex::Autolock lock(mLock);
+    status_t result = checkPidAndHardware();
+    if (result != NO_ERROR) return result;
+
+    // return if no change in surface.
+    // asBinder() is safe on NULL (returns NULL)
+    if (surfaceTexture->asBinder() == mSurface) {
+        return result;
+    }
+
+    if (mSurface != 0) {
+        LOG1("clearing old preview surface %p", mSurface.get());
+    }
+    mSurface = surfaceTexture->asBinder();
+    if (surfaceTexture != 0) {
+        mPreviewWindow = new SurfaceTextureClient(surfaceTexture);
+    } else {
+        mPreviewWindow = 0;
+    }
+
+    // If preview has been already started, set overlay or register preview
+    // buffers now.
+    if (mHardware->previewEnabled()) {
+        // XXX: What if the new preview window is 0?
+        if (mPreviewWindow != 0) {
+            native_window_set_buffers_transform(mPreviewWindow.get(),
+                                                mOrientation);
+            result = mHardware->setPreviewWindow(mPreviewWindow);
+        }
+    }
+
+    return result;
+}
+
 // set the preview callback flag to affect how the received frames from
 // preview are handled.
 void CameraService::Client::setPreviewCallbackFlag(int callback_flag) {
@@ -960,23 +999,6 @@
     }
     disableMsgType(CAMERA_MSG_SHUTTER);
 
-    // It takes some time before yuvPicture callback to be called.
-    // Register the buffer for raw image here to reduce latency.
-    if (mSurface != 0) {
-        int w, h;
-        CameraParameters params(mHardware->getParameters());
-        if (size == NULL) {
-            params.getPictureSize(&w, &h);
-        } else {
-            w = size->width;
-            h = size->height;
-            w &= ~1;
-            h &= ~1;
-            LOG1("Snapshot image width=%d, height=%d", w, h);
-        }
-        IPCThreadState::self()->flushCommands();
-    }
-
     mLock.unlock();
 }
 
diff --git a/services/camera/libcameraservice/CameraService.h b/services/camera/libcameraservice/CameraService.h
index d78d7e5..ccb9cf7 100644
--- a/services/camera/libcameraservice/CameraService.h
+++ b/services/camera/libcameraservice/CameraService.h
@@ -94,6 +94,7 @@
         virtual status_t        lock();
         virtual status_t        unlock();
         virtual status_t        setPreviewDisplay(const sp<Surface>& surface);
+        virtual status_t        setPreviewTexture(const sp<ISurfaceTexture>& surfaceTexture);
         virtual void            setPreviewCallbackFlag(int flag);
         virtual status_t        startPreview();
         virtual void            stopPreview();
@@ -180,7 +181,8 @@
 
         // Ensures atomicity among the public methods
         mutable Mutex                   mLock;
-        sp<ISurface>                    mSurface;
+        // This is a binder of Surface or SurfaceTexture.
+        sp<IBinder>                     mSurface;
         sp<ANativeWindow>               mPreviewWindow;
 
         // If the user want us to return a copy of the preview frame (instead