CameraService: Refactor Camera2Client to share a base with ProCameraClient

Change-Id: I249e2a0fc47ae84f29c9d9c4a223fba13da3ee66
diff --git a/services/camera/libcameraservice/Camera2ClientBase.cpp b/services/camera/libcameraservice/Camera2ClientBase.cpp
new file mode 100644
index 0000000..e92ad1c
--- /dev/null
+++ b/services/camera/libcameraservice/Camera2ClientBase.cpp
@@ -0,0 +1,315 @@
+/*
+ * 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_TAG "Camera2ClientBase"
+#define ATRACE_TAG ATRACE_TAG_CAMERA
+//#define LOG_NDEBUG 0
+
+#include <utils/Log.h>
+#include <utils/Trace.h>
+
+#include <cutils/properties.h>
+#include <gui/Surface.h>
+#include <gui/Surface.h>
+#include "camera2/Parameters.h"
+#include "Camera2ClientBase.h"
+#include "camera2/ProFrameProcessor.h"
+
+#include "Camera2Device.h"
+
+namespace android {
+using namespace camera2;
+
+static int getCallingPid() {
+    return IPCThreadState::self()->getCallingPid();
+}
+
+// Interface used by CameraService
+
+template <typename TClientBase>
+Camera2ClientBase<TClientBase>::Camera2ClientBase(
+        const sp<CameraService>& cameraService,
+        const sp<TCamCallbacks>& remoteCallback,
+        const String16& clientPackageName,
+        int cameraId,
+        int cameraFacing,
+        int clientPid,
+        uid_t clientUid,
+        int servicePid):
+        TClientBase(cameraService, remoteCallback, clientPackageName,
+                cameraId, cameraFacing, clientPid, clientUid, servicePid),
+        mSharedCameraCallbacks(remoteCallback)
+{
+    ALOGI("Camera %d: Opened", cameraId);
+    mDevice = new Camera2Device(cameraId);
+}
+
+template <typename TClientBase>
+status_t Camera2ClientBase<TClientBase>::checkPid(const char* checkLocation)
+        const {
+
+    int callingPid = getCallingPid();
+    if (callingPid == TClientBase::mClientPid) return NO_ERROR;
+
+    ALOGE("%s: attempt to use a locked camera from a different process"
+            " (old pid %d, new pid %d)", checkLocation, TClientBase::mClientPid, callingPid);
+    return PERMISSION_DENIED;
+}
+
+template <typename TClientBase>
+status_t Camera2ClientBase<TClientBase>::initialize(camera_module_t *module) {
+    ATRACE_CALL();
+    ALOGV("%s: Initializing client for camera %d", __FUNCTION__,
+          TClientBase::mCameraId);
+    status_t res;
+
+    res = mDevice->initialize(module);
+    if (res != OK) {
+        ALOGE("%s: Camera %d: unable to initialize device: %s (%d)",
+                __FUNCTION__, TClientBase::mCameraId, strerror(-res), res);
+        return NO_INIT;
+    }
+
+    res = mDevice->setNotifyCallback(this);
+
+    return OK;
+}
+
+template <typename TClientBase>
+Camera2ClientBase<TClientBase>::~Camera2ClientBase() {
+    ATRACE_CALL();
+
+    TClientBase::mDestructionStarted = true;
+
+    disconnect();
+
+    ALOGI("Closed Camera %d", TClientBase::mCameraId);
+}
+
+template <typename TClientBase>
+status_t Camera2ClientBase<TClientBase>::dump(int fd,
+                                              const Vector<String16>& args) {
+    String8 result;
+    result.appendFormat("Camera2ClientBase[%d] (%p) PID: %d, dump:\n",
+            TClientBase::mCameraId,
+            TClientBase::getRemoteCallback()->asBinder().get(),
+            TClientBase::mClientPid);
+    result.append("  State: ");
+
+    write(fd, result.string(), result.size());
+    // TODO: print dynamic/request section from most recent requests
+
+    return dumpDevice(fd, args);
+}
+
+template <typename TClientBase>
+status_t Camera2ClientBase<TClientBase>::dumpDevice(
+                                                int fd,
+                                                const Vector<String16>& args) {
+    String8 result;
+
+    result = "  Device dump:\n";
+    write(fd, result.string(), result.size());
+
+    if (!mDevice.get()) {
+        result = "  *** Device is detached\n";
+        write(fd, result.string(), result.size());
+        return NO_ERROR;
+    }
+
+    status_t res = mDevice->dump(fd, args);
+    if (res != OK) {
+        result = String8::format("   Error dumping device: %s (%d)",
+                strerror(-res), res);
+        write(fd, result.string(), result.size());
+    }
+
+    return NO_ERROR;
+}
+
+// ICameraClient2BaseUser interface
+
+
+template <typename TClientBase>
+void Camera2ClientBase<TClientBase>::disconnect() {
+    ATRACE_CALL();
+    Mutex::Autolock icl(mBinderSerializationLock);
+
+    // Allow both client and the media server to disconnect at all times
+    int callingPid = getCallingPid();
+    if (callingPid != TClientBase::mClientPid &&
+        callingPid != TClientBase::mServicePid) return;
+
+    ALOGV("Camera %d: Shutting down", TClientBase::mCameraId);
+
+    detachDevice();
+
+    TClientBase::disconnect();
+
+    ALOGV("Camera %d: Shut down complete complete", TClientBase::mCameraId);
+}
+
+template <typename TClientBase>
+void Camera2ClientBase<TClientBase>::detachDevice() {
+    if (mDevice == 0) return;
+    mDevice->disconnect();
+
+    mDevice.clear();
+
+    ALOGV("Camera %d: Detach complete", TClientBase::mCameraId);
+}
+
+template <typename TClientBase>
+status_t Camera2ClientBase<TClientBase>::connect(
+        const sp<TCamCallbacks>& client) {
+    ATRACE_CALL();
+    ALOGV("%s: E", __FUNCTION__);
+    Mutex::Autolock icl(mBinderSerializationLock);
+
+    if (TClientBase::mClientPid != 0 &&
+        getCallingPid() != TClientBase::mClientPid) {
+
+        ALOGE("%s: Camera %d: Connection attempt from pid %d; "
+                "current locked to pid %d",
+                __FUNCTION__,
+                TClientBase::mCameraId,
+                getCallingPid(),
+                TClientBase::mClientPid);
+        return BAD_VALUE;
+    }
+
+    TClientBase::mClientPid = getCallingPid();
+
+    TClientBase::mRemoteCallback = client;
+    mSharedCameraCallbacks = client;
+
+    return OK;
+}
+
+/** Device-related methods */
+
+template <typename TClientBase>
+void Camera2ClientBase<TClientBase>::notifyError(int errorCode, int arg1,
+                                                 int arg2) {
+    ALOGE("Error condition %d reported by HAL, arguments %d, %d", errorCode,
+          arg1, arg2);
+}
+
+template <typename TClientBase>
+void Camera2ClientBase<TClientBase>::notifyShutter(int frameNumber,
+                                                   nsecs_t timestamp) {
+    (void)frameNumber;
+    (void)timestamp;
+
+    ALOGV("%s: Shutter notification for frame %d at time %lld", __FUNCTION__,
+          frameNumber, timestamp);
+}
+
+template <typename TClientBase>
+void Camera2ClientBase<TClientBase>::notifyAutoFocus(uint8_t newState,
+                                                     int triggerId) {
+    (void)newState;
+    (void)triggerId;
+
+    ALOGV("%s: Autofocus state now %d, last trigger %d",
+          __FUNCTION__, newState, triggerId);
+
+    typename SharedCameraCallbacks::Lock l(mSharedCameraCallbacks);
+    if (l.mRemoteCallback != 0) {
+        l.mRemoteCallback->notifyCallback(CAMERA_MSG_FOCUS_MOVE, 1, 0);
+    }
+    if (l.mRemoteCallback != 0) {
+        l.mRemoteCallback->notifyCallback(CAMERA_MSG_FOCUS, 1, 0);
+    }
+}
+
+template <typename TClientBase>
+void Camera2ClientBase<TClientBase>::notifyAutoExposure(uint8_t newState,
+                                                        int triggerId) {
+    (void)newState;
+    (void)triggerId;
+
+    ALOGV("%s: Autoexposure state now %d, last trigger %d",
+            __FUNCTION__, newState, triggerId);
+}
+
+template <typename TClientBase>
+void Camera2ClientBase<TClientBase>::notifyAutoWhitebalance(uint8_t newState,
+                                                            int triggerId) {
+    (void)newState;
+    (void)triggerId;
+
+    ALOGV("%s: Auto-whitebalance state now %d, last trigger %d",
+            __FUNCTION__, newState, triggerId);
+}
+
+template <typename TClientBase>
+int Camera2ClientBase<TClientBase>::getCameraId() const {
+    return TClientBase::mCameraId;
+}
+
+template <typename TClientBase>
+const sp<CameraDeviceBase>& Camera2ClientBase<TClientBase>::getCameraDevice() {
+    return mDevice;
+}
+
+template <typename TClientBase>
+const sp<CameraService>& Camera2ClientBase<TClientBase>::getCameraService() {
+    return TClientBase::mCameraService;
+}
+
+template <typename TClientBase>
+Camera2ClientBase<TClientBase>::SharedCameraCallbacks::Lock::Lock(
+        SharedCameraCallbacks &client) :
+
+        mRemoteCallback(client.mRemoteCallback),
+        mSharedClient(client) {
+
+    mSharedClient.mRemoteCallbackLock.lock();
+}
+
+template <typename TClientBase>
+Camera2ClientBase<TClientBase>::SharedCameraCallbacks::Lock::~Lock() {
+    mSharedClient.mRemoteCallbackLock.unlock();
+}
+
+template <typename TClientBase>
+Camera2ClientBase<TClientBase>::SharedCameraCallbacks::SharedCameraCallbacks(
+        const sp<TCamCallbacks>&client) :
+
+        mRemoteCallback(client) {
+}
+
+template <typename TClientBase>
+typename Camera2ClientBase<TClientBase>::SharedCameraCallbacks&
+Camera2ClientBase<TClientBase>::SharedCameraCallbacks::operator=(
+        const sp<TCamCallbacks>&client) {
+
+    Mutex::Autolock l(mRemoteCallbackLock);
+    mRemoteCallback = client;
+    return *this;
+}
+
+template <typename TClientBase>
+void Camera2ClientBase<TClientBase>::SharedCameraCallbacks::clear() {
+    Mutex::Autolock l(mRemoteCallbackLock);
+    mRemoteCallback.clear();
+}
+
+template class Camera2ClientBase<CameraService::ProClient>;
+template class Camera2ClientBase<CameraService::Client>;
+
+} // namespace android