Camera: Add ProCamera private binder interface for an API2-light functionality

Change-Id: I2af7a807c99df75ea659e6e6acc9c4fca6a56274
diff --git a/camera/ProCamera.cpp b/camera/ProCamera.cpp
new file mode 100644
index 0000000..134a4a3
--- /dev/null
+++ b/camera/ProCamera.cpp
@@ -0,0 +1,230 @@
+/*
+**
+** Copyright (C) 2013, 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.
+*/
+
+//#define LOG_NDEBUG 0
+#define LOG_TAG "ProCamera"
+#include <utils/Log.h>
+#include <utils/threads.h>
+#include <utils/Mutex.h>
+
+#include <binder/IPCThreadState.h>
+#include <binder/IServiceManager.h>
+#include <binder/IMemory.h>
+
+#include <camera/ProCamera.h>
+#include <camera/ICameraService.h>
+#include <camera/IProCameraUser.h>
+#include <camera/IProCameraCallbacks.h>
+
+#include <gui/IGraphicBufferProducer.h>
+#include <gui/Surface.h>
+
+namespace android {
+
+// client singleton for camera service binder interface
+Mutex ProCamera::mLock;
+sp<ICameraService> ProCamera::mCameraService;
+sp<ProCamera::DeathNotifier> ProCamera::mDeathNotifier;
+
+// establish binder interface to camera service
+const sp<ICameraService>& ProCamera::getCameraService()
+{
+    Mutex::Autolock _l(mLock);
+    if (mCameraService.get() == 0) {
+        sp<IServiceManager> sm = defaultServiceManager();
+        sp<IBinder> binder;
+        do {
+            binder = sm->getService(String16("media.camera"));
+            if (binder != 0)
+                break;
+            ALOGW("CameraService not published, waiting...");
+            usleep(500000); // 0.5 s
+        } while(true);
+        if (mDeathNotifier == NULL) {
+            mDeathNotifier = new DeathNotifier();
+        }
+        binder->linkToDeath(mDeathNotifier);
+        mCameraService = interface_cast<ICameraService>(binder);
+    }
+    ALOGE_IF(mCameraService==0, "no CameraService!?");
+    return mCameraService;
+}
+
+sp<ProCamera> ProCamera::connect(int cameraId)
+{
+    ALOGV("connect");
+    sp<ProCamera> c = new ProCamera();
+    sp<IProCameraCallbacks> cl = c;
+    const sp<ICameraService>& cs = getCameraService();
+    if (cs != 0) {
+        c->mCamera = cs->connect(cl, cameraId);
+    }
+    if (c->mCamera != 0) {
+        c->mCamera->asBinder()->linkToDeath(c);
+        c->mStatus = NO_ERROR;
+    } else {
+        c.clear();
+    }
+    return c;
+}
+
+void ProCamera::disconnect()
+{
+    ALOGV("disconnect");
+    if (mCamera != 0) {
+        mCamera->disconnect();
+        mCamera->asBinder()->unlinkToDeath(this);
+        mCamera = 0;
+    }
+}
+
+ProCamera::ProCamera()
+{
+}
+
+ProCamera::~ProCamera()
+{
+
+}
+
+sp<IProCameraUser> ProCamera::remote()
+{
+    return mCamera;
+}
+
+void ProCamera::binderDied(const wp<IBinder>& who) {
+    ALOGW("IProCameraUser died");
+    notifyCallback(CAMERA_MSG_ERROR, CAMERA_ERROR_SERVER_DIED, 0);
+}
+
+void ProCamera::DeathNotifier::binderDied(const wp<IBinder>& who) {
+    ALOGV("binderDied");
+    Mutex::Autolock _l(ProCamera::mLock);
+    ProCamera::mCameraService.clear();
+    ALOGW("Camera service died!");
+}
+
+
+// callback from camera service
+void ProCamera::notifyCallback(int32_t msgType, int32_t ext1, int32_t ext2)
+{
+    sp<ProCameraListener> listener;
+    {
+        Mutex::Autolock _l(mLock);
+        listener = mListener;
+    }
+    if (listener != NULL) {
+        listener->notify(msgType, ext1, ext2);
+    }
+}
+
+// callback from camera service when frame or image is ready
+void ProCamera::dataCallback(int32_t msgType, const sp<IMemory>& dataPtr,
+                          camera_frame_metadata_t *metadata)
+{
+    sp<ProCameraListener> listener;
+    {
+        Mutex::Autolock _l(mLock);
+        listener = mListener;
+    }
+    if (listener != NULL) {
+        listener->postData(msgType, dataPtr, metadata);
+    }
+}
+
+// callback from camera service when timestamped frame is ready
+void ProCamera::dataCallbackTimestamp(nsecs_t timestamp, int32_t msgType,
+                                                    const sp<IMemory>& dataPtr)
+{
+    sp<ProCameraListener> listener;
+    {
+        Mutex::Autolock _l(mLock);
+        listener = mListener;
+    }
+    if (listener != NULL) {
+        listener->postDataTimestamp(timestamp, msgType, dataPtr);
+    } else {
+        ALOGW("No listener was set. Drop a recording frame.");
+    }
+}
+
+/* IProCameraUser's implementation */
+
+status_t ProCamera::exclusiveTryLock()
+{
+    sp <IProCameraUser> c = mCamera;
+    if (c == 0) return NO_INIT;
+
+    return c->exclusiveTryLock();
+}
+status_t ProCamera::exclusiveLock()
+{
+    sp <IProCameraUser> c = mCamera;
+    if (c == 0) return NO_INIT;
+
+    return c->exclusiveLock();
+}
+status_t ProCamera::exclusiveUnlock()
+{
+    sp <IProCameraUser> c = mCamera;
+    if (c == 0) return NO_INIT;
+
+    return c->exclusiveUnlock();
+}
+bool ProCamera::hasExclusiveLock()
+{
+    sp <IProCameraUser> c = mCamera;
+    if (c == 0) return NO_INIT;
+
+    return c->hasExclusiveLock();
+}
+
+// Note that the callee gets a copy of the metadata.
+int ProCamera::submitRequest(const struct camera_metadata* metadata,
+                             bool streaming)
+{
+    sp <IProCameraUser> c = mCamera;
+    if (c == 0) return NO_INIT;
+
+    return c->submitRequest(const_cast<struct camera_metadata*>(metadata),
+                            streaming);
+}
+
+status_t ProCamera::cancelRequest(int requestId)
+{
+    sp <IProCameraUser> c = mCamera;
+    if (c == 0) return NO_INIT;
+
+    return c->cancelRequest(requestId);
+}
+
+status_t ProCamera::requestStream(int streamId)
+{
+    sp <IProCameraUser> c = mCamera;
+    if (c == 0) return NO_INIT;
+
+    return c->requestStream(streamId);
+}
+status_t ProCamera::cancelStream(int streamId)
+{
+    sp <IProCameraUser> c = mCamera;
+    if (c == 0) return NO_INIT;
+
+    return c->cancelStream(streamId);
+}
+
+}; // namespace android