Camera3: Add support channel when there is only one raw stream

This makes sure that in the case of single raw stream:
1. Metadata and statistics can be collected for raw result.
2. Works around a mm-camera daemon limitation where single raw
stream cannot be supported.

Bug: 14014546
Change-Id: I7a3787b8190f7d01d3dc2c43f8ab174a855ccc16
diff --git a/camera/QCamera2/HAL3/QCamera3Channel.cpp b/camera/QCamera2/HAL3/QCamera3Channel.cpp
index aaaa5b1..de2557b 100644
--- a/camera/QCamera2/HAL3/QCamera3Channel.cpp
+++ b/camera/QCamera2/HAL3/QCamera3Channel.cpp
@@ -2480,5 +2480,96 @@
     return rc;
 }
 
+cam_dimension_t QCamera3SupportChannel::kDim = {640, 480};
+
+QCamera3SupportChannel::QCamera3SupportChannel(uint32_t cam_handle,
+                    mm_camera_ops_t *cam_ops,
+                    cam_padding_info_t *paddingInfo,
+                    void *userData) :
+                        QCamera3Channel(cam_handle, cam_ops,
+                                NULL, paddingInfo, userData),
+                        mMemory(NULL)
+{
+}
+
+QCamera3SupportChannel::~QCamera3SupportChannel()
+{
+    if (m_bIsActive)
+        stop();
+
+    if (mMemory) {
+        mMemory->deallocate();
+        delete mMemory;
+        mMemory = NULL;
+    }
+}
+
+int32_t QCamera3SupportChannel::initialize()
+{
+    int32_t rc;
+
+    if (mMemory || m_numStreams > 0) {
+        ALOGE("%s: metadata channel already initialized", __func__);
+        return -EINVAL;
+    }
+
+    rc = init(NULL, NULL);
+    if (rc < 0) {
+        ALOGE("%s: init failed", __func__);
+        return rc;
+    }
+
+    // Hardcode to VGA size for now
+    rc = QCamera3Channel::addStream(CAM_STREAM_TYPE_CALLBACK,
+        CAM_FORMAT_YUV_420_NV21, kDim, MIN_STREAMING_BUFFER_NUM);
+    if (rc < 0) {
+        ALOGE("%s: addStream failed", __func__);
+    }
+    return rc;
+}
+
+int32_t QCamera3SupportChannel::request(buffer_handle_t * /*buffer*/,
+                                                uint32_t /*frameNumber*/)
+{
+    return NO_ERROR;
+}
+
+void QCamera3SupportChannel::streamCbRoutine(
+                        mm_camera_super_buf_t *super_frame,
+                        QCamera3Stream * /*stream*/)
+{
+    if (super_frame == NULL || super_frame->num_bufs != 1) {
+        ALOGE("%s: super_frame is not valid", __func__);
+        return;
+    }
+    bufDone(super_frame);
+    free(super_frame);
+}
+
+QCamera3Memory* QCamera3SupportChannel::getStreamBufs(uint32_t len)
+{
+    int rc;
+
+    mMemory = new QCamera3HeapMemory();
+    if (!mMemory) {
+        ALOGE("%s: unable to create heap memory", __func__);
+        return NULL;
+    }
+    rc = mMemory->allocate(MIN_STREAMING_BUFFER_NUM, len, true);
+    if (rc < 0) {
+        ALOGE("%s: unable to allocate heap memory", __func__);
+        delete mMemory;
+        mMemory = NULL;
+        return NULL;
+    }
+    return mMemory;
+}
+
+void QCamera3SupportChannel::putStreamBufs()
+{
+    mMemory->deallocate();
+    delete mMemory;
+    mMemory = NULL;
+}
 
 }; // namespace qcamera
diff --git a/camera/QCamera2/HAL3/QCamera3Channel.h b/camera/QCamera2/HAL3/QCamera3Channel.h
index a7da610..2758261 100755
--- a/camera/QCamera2/HAL3/QCamera3Channel.h
+++ b/camera/QCamera2/HAL3/QCamera3Channel.h
@@ -137,7 +137,7 @@
     virtual void streamCbRoutine(mm_camera_super_buf_t *super_frame,
                                             QCamera3Stream *stream);
 
-    virtual QCamera3Memory *getStreamBufs(uint32_t le);
+    virtual QCamera3Memory *getStreamBufs(uint32_t len);
     virtual void putStreamBufs();
     mm_camera_buf_def_t* getInternalFormatBuffer(buffer_handle_t* buffer);
     virtual int32_t registerBuffer(buffer_handle_t *buffer);
@@ -171,7 +171,7 @@
     virtual void streamCbRoutine(mm_camera_super_buf_t *super_frame,
                             QCamera3Stream *stream);
 
-    virtual QCamera3Memory *getStreamBufs(uint32_t le);
+    virtual QCamera3Memory *getStreamBufs(uint32_t len);
     virtual void putStreamBufs();
     virtual int32_t registerBuffer(buffer_handle_t * /*buffer*/)
             { return NO_ERROR; };
@@ -200,7 +200,7 @@
     virtual void streamCbRoutine(mm_camera_super_buf_t *super_frame,
                             QCamera3Stream *stream);
 
-    virtual QCamera3Memory *getStreamBufs(uint32_t le);
+    virtual QCamera3Memory *getStreamBufs(uint32_t len);
     virtual void putStreamBufs();
     void dumpRawSnapshot(mm_camera_buf_def_t *frame);
     virtual int32_t registerBuffer(buffer_handle_t * /*buffer*/)
@@ -263,7 +263,7 @@
     virtual void streamCbRoutine(mm_camera_super_buf_t *super_frame,
             QCamera3Stream *stream);
 
-    virtual QCamera3Memory *getStreamBufs(uint32_t le);
+    virtual QCamera3Memory *getStreamBufs(uint32_t len);
     virtual void putStreamBufs();
 
     bool isWNREnabled() {return m_bWNROn;};
@@ -346,6 +346,32 @@
     QCamera3HeapMemory *mMemory;
 };
 
+/* QCamera3SupportChannel is for HAL internal consumption only */
+class QCamera3SupportChannel : public QCamera3Channel
+{
+public:
+    QCamera3SupportChannel(uint32_t cam_handle,
+                    mm_camera_ops_t *cam_ops,
+                    cam_padding_info_t *paddingInfo,
+                    void *userData);
+    virtual ~QCamera3SupportChannel();
+
+    virtual int32_t initialize();
+
+    virtual int32_t request(buffer_handle_t *buffer, uint32_t frameNumber);
+    virtual void streamCbRoutine(mm_camera_super_buf_t *super_frame,
+                            QCamera3Stream *stream);
+
+    virtual QCamera3Memory *getStreamBufs(uint32_t le);
+    virtual void putStreamBufs();
+    virtual int32_t registerBuffer(buffer_handle_t * /*buffer*/)
+            { return NO_ERROR; };
+
+    static cam_dimension_t kDim;
+private:
+    QCamera3HeapMemory *mMemory;
+};
+
 }; // namespace qcamera
 
 #endif /* __QCAMERA_CHANNEL_H__ */
diff --git a/camera/QCamera2/HAL3/QCamera3HWI.cpp b/camera/QCamera2/HAL3/QCamera3HWI.cpp
index efc8176..d7229ff 100644
--- a/camera/QCamera2/HAL3/QCamera3HWI.cpp
+++ b/camera/QCamera2/HAL3/QCamera3HWI.cpp
@@ -239,6 +239,7 @@
       mMetadataChannel(NULL),
       mPictureChannel(NULL),
       mRawChannel(NULL),
+      mSupportChannel(NULL),
       mFirstRequest(false),
       mParamHeap(NULL),
       mParameters(NULL),
@@ -298,6 +299,8 @@
             channel->stop();
         }
     }
+    if (mSupportChannel)
+        mSupportChannel->stop();
 
     for (List<stream_info_t *>::iterator it = mStreamInfo.begin();
         it != mStreamInfo.end(); it++) {
@@ -306,6 +309,10 @@
             delete channel;
         free (*it);
     }
+    if (mSupportChannel) {
+        delete mSupportChannel;
+        mSupportChannel = NULL;
+    }
 
     mPictureChannel = NULL;
 
@@ -616,6 +623,33 @@
         return rc;
     }
 
+    /* Create dummy stream if there is one single raw stream */
+    if (streamList->num_streams == 1 &&
+            (streamList->streams[0]->format == HAL_PIXEL_FORMAT_RAW_OPAQUE ||
+            streamList->streams[0]->format == HAL_PIXEL_FORMAT_RAW16)) {
+        mSupportChannel = new QCamera3SupportChannel(
+                mCameraHandle->camera_handle,
+                mCameraHandle->ops,
+                &gCamCapability[mCameraId]->padding_info,
+                this);
+        if (!mSupportChannel) {
+            ALOGE("%s: dummy channel cannot be created", __func__);
+            pthread_mutex_unlock(&mMutex);
+            return -ENOMEM;
+        }
+
+        rc = mSupportChannel->initialize();
+        if (rc < 0) {
+            ALOGE("%s: dummy channel initialization failed", __func__);
+            delete mSupportChannel;
+            mSupportChannel = NULL;
+            delete mMetadataChannel;
+            mMetadataChannel = NULL;
+            pthread_mutex_unlock(&mMutex);
+            return rc;
+        }
+    }
+
     /* Allocate channel objects for the requested streams */
     for (size_t i = 0; i < streamList->num_streams; i++) {
         camera3_stream_t *newStream = streamList->streams[i];
@@ -769,6 +803,13 @@
 
     int32_t hal_version = CAM_HAL_V3;
     stream_config_info.num_streams = streamList->num_streams;
+    if (mSupportChannel) {
+        stream_config_info.stream_sizes[stream_config_info.num_streams] =
+                QCamera3SupportChannel::kDim;
+        stream_config_info.type[stream_config_info.num_streams] =
+                CAM_STREAM_TYPE_CALLBACK;
+        stream_config_info.num_streams++;
+    }
 
     // settings/parameters don't carry over for new configureStreams
     memset(mParameters, 0, sizeof(metadata_buffer_t));
@@ -1059,7 +1100,7 @@
                 mCallbackOps->notify(mCallbackOps, &notify_msg);
                 i->timestamp = notify_msg.message.shutter.timestamp;
                 i->bNotified = 1;
-                ALOGV("%s: Dummy notification !!!! notify frame_number = %d, capture_time = %lld",
+                ALOGV("%s: Support notification !!!! notify frame_number = %d, capture_time = %lld",
                     __func__, i->frame_number, notify_msg.message.shutter.timestamp);
             }
 
@@ -1479,6 +1520,9 @@
         ALOGD("%s: Start META Channel", __func__);
         mMetadataChannel->start();
 
+        if (mSupportChannel)
+            mSupportChannel->start();
+
         //First initialize all streams
         for (List<stream_info_t *>::iterator it = mStreamInfo.begin();
             it != mStreamInfo.end(); it++) {
@@ -1486,6 +1530,8 @@
             rc = channel->initialize();
             if (NO_ERROR != rc) {
                 ALOGE("%s : Channel initialization failed %d", __func__, rc);
+                if (mSupportChannel)
+                    mSupportChannel->stop();
                 mMetadataChannel->stop();
                 pthread_mutex_unlock(&mMutex);
                 return rc;
@@ -1731,6 +1777,9 @@
         (*it)->status = INVALID;
     }
 
+    if (mSupportChannel) {
+        mSupportChannel->stop();
+    }
     if (mMetadataChannel) {
         /* If content of mStreamInfo is not 0, there is metadata stream */
         mMetadataChannel->stop();
diff --git a/camera/QCamera2/HAL3/QCamera3HWI.h b/camera/QCamera2/HAL3/QCamera3HWI.h
index 299e07b..aa4a30a 100755
--- a/camera/QCamera2/HAL3/QCamera3HWI.h
+++ b/camera/QCamera2/HAL3/QCamera3HWI.h
@@ -227,6 +227,7 @@
     QCamera3MetadataChannel *mMetadataChannel;
     QCamera3PicChannel *mPictureChannel;
     QCamera3RawChannel *mRawChannel;
+    QCamera3SupportChannel *mSupportChannel;
 
      //First request yet to be processed after configureStreams
     bool mFirstRequest;