Camera3: Protect against simultaneous camera instances

When frameworks try to open the 2nd camera instance, CTS test
allows open to fail, but doesn't allow startPreview to fail.

The way camera daemon is written, ISP hardware is reserved during
startPreview, but only released when all streams are removed.
The removal of streams happens when camera is closed. Because of this,
the current logic allows the 2nd open to succeed, but startPreview
will fail. This is not good!

Block the 2nd open in HAL until we have a better underlying design
to address this issue.

Change-Id: If00b1227f0794171cea3b43c7af28dd766a1943e
Signed-off-by: Iliyan Malchev <malchev@google.com>
diff --git a/camera/QCamera2/HAL3/QCamera3HWI.cpp b/camera/QCamera2/HAL3/QCamera3HWI.cpp
index db34c3c..0344f88 100644
--- a/camera/QCamera2/HAL3/QCamera3HWI.cpp
+++ b/camera/QCamera2/HAL3/QCamera3HWI.cpp
@@ -50,6 +50,10 @@
 parm_buffer_t *prevSettings;
 const camera_metadata_t *gStaticMetadata[MM_CAMERA_MAX_NUM_SENSORS];
 
+pthread_mutex_t QCamera3HardwareInterface::mCameraSessionLock =
+    PTHREAD_MUTEX_INITIALIZER;
+unsigned int QCamera3HardwareInterface::mCameraSessionActive = 0;
+
 const QCamera3HardwareInterface::QCameraMap QCamera3HardwareInterface::EFFECT_MODES_MAP[] = {
     { ANDROID_CONTROL_EFFECT_MODE_OFF,       CAM_EFFECT_MODE_OFF },
     { ANDROID_CONTROL_EFFECT_MODE_MONO,       CAM_EFFECT_MODE_MONO },
@@ -150,6 +154,7 @@
     : mCameraId(cameraId),
       mCameraHandle(NULL),
       mCameraOpened(false),
+      mCameraInitialized(false),
       mCallbackOps(NULL),
       mInputStream(NULL),
       mMetadataChannel(NULL),
@@ -190,11 +195,13 @@
 {
     ALOGV("%s: E", __func__);
     /* Clean up all channels */
-    if (mMetadataChannel) {
+    if (mCameraInitialized) {
         mMetadataChannel->stop();
         delete mMetadataChannel;
         mMetadataChannel = NULL;
+        deinitParameters();
     }
+
     /* We need to stop all streams before deleting any stream */
     for (List<stream_info_t *>::iterator it = mStreamInfo.begin();
         it != mStreamInfo.end(); it++) {
@@ -212,9 +219,8 @@
         free(mJpegSettings);
         mJpegSettings = NULL;
     }
-
-    deinitParameters();
-    closeCamera();
+    if (mCameraOpened)
+        closeCamera();
 
     for (size_t i = 0; i < CAMERA3_TEMPLATE_COUNT; i++)
         if (mDefaultMetadata[i])
@@ -242,18 +248,27 @@
  *==========================================================================*/
 int QCamera3HardwareInterface::openCamera(struct hw_device_t **hw_device)
 {
-    //int rc = NO_ERROR;
     int rc = 0;
+    pthread_mutex_lock(&mCameraSessionLock);
+    if (mCameraSessionActive) {
+        ALOGE("%s: multiple simultaneous camera instance not supported", __func__);
+        pthread_mutex_unlock(&mCameraSessionLock);
+        return INVALID_OPERATION;
+    }
+
     if (mCameraOpened) {
         *hw_device = NULL;
         return PERMISSION_DENIED;
     }
 
     rc = openCamera();
-    if (rc == 0)
+    if (rc == 0) {
         *hw_device = &mCameraDevice.common;
-    else
+        mCameraSessionActive = 1;
+    } else
         *hw_device = NULL;
+
+    pthread_mutex_unlock(&mCameraSessionLock);
     return rc;
 }
 
@@ -348,6 +363,7 @@
     mCallbackOps = callback_ops;
 
     pthread_mutex_unlock(&mMutex);
+    mCameraInitialized = true;
     return 0;
 
 err3:
@@ -3173,6 +3189,10 @@
         return BAD_VALUE;
     }
     delete hw;
+
+    pthread_mutex_lock(&mCameraSessionLock);
+    mCameraSessionActive = 0;
+    pthread_mutex_unlock(&mCameraSessionLock);
     ALOGV("%s: X", __func__);
     return ret;
 }
diff --git a/camera/QCamera2/HAL3/QCamera3HWI.h b/camera/QCamera2/HAL3/QCamera3HWI.h
index d2d5632..05ce3a3 100644
--- a/camera/QCamera2/HAL3/QCamera3HWI.h
+++ b/camera/QCamera2/HAL3/QCamera3HWI.h
@@ -162,6 +162,7 @@
     uint8_t            mCameraId;
     mm_camera_vtbl_t  *mCameraHandle;
     bool               mCameraOpened;
+    bool               mCameraInitialized;
     camera_metadata_t *mDefaultMetadata[CAMERA3_TEMPLATE_COUNT];
 
     const camera3_callback_ops_t *mCallbackOps;
@@ -211,6 +212,9 @@
     static const QCameraMap ANTIBANDING_MODES_MAP[];
     static const QCameraMap AE_FLASH_MODE_MAP[];
     static const QCameraMap FLASH_MODES_MAP[];
+
+    static pthread_mutex_t mCameraSessionLock;
+    static unsigned int mCameraSessionActive;
 };
 
 }; // namespace qcamera