Camera: add HAL1 recording batching support

Test: Angler HAL1 + set mBatchSize to 4 locally
Bug: 35997432
Change-Id: I6baf112f9da56534ae81008bad818fba1e76a294
diff --git a/camera/device/1.0/default/CameraDevice.cpp b/camera/device/1.0/default/CameraDevice.cpp
index 819525b..6eeda1c 100644
--- a/camera/device/1.0/default/CameraDevice.cpp
+++ b/camera/device/1.0/default/CameraDevice.cpp
@@ -420,6 +420,39 @@
     }
 }
 
+void CameraDevice::handleCallbackTimestamp(
+        nsecs_t timestamp, int32_t msg_type,
+        MemoryId memId , unsigned index, native_handle_t* handle) {
+    uint32_t batchSize = 0;
+    {
+        Mutex::Autolock _l(mBatchLock);
+        batchSize = mBatchSize;
+    }
+
+    if (batchSize == 0) { // non-batch mode
+        mDeviceCallback->handleCallbackTimestamp(
+                (DataCallbackMsg) msg_type, handle, memId, index, timestamp);
+    } else { // batch mode
+        Mutex::Autolock _l(mBatchLock);
+        size_t inflightSize = mInflightBatch.size();
+        if (inflightSize == 0) {
+            mBatchMsgType = msg_type;
+        } else if (mBatchMsgType != msg_type) {
+            ALOGE("%s: msg_type change (from %d to %d) is not supported!",
+                    __FUNCTION__, mBatchMsgType, msg_type);
+            return;
+        }
+        mInflightBatch.push_back({handle, memId, index, timestamp});
+
+        // Send batched frames to camera framework
+        if (mInflightBatch.size() >= batchSize) {
+            mDeviceCallback->handleCallbackTimestampBatch(
+                    (DataCallbackMsg) mBatchMsgType, mInflightBatch);
+            mInflightBatch.clear();
+        }
+    }
+}
+
 void CameraDevice::sDataCbTimestamp(nsecs_t timestamp, int32_t msg_type,
         const camera_memory_t *data, unsigned index, void *user) {
     ALOGV("%s", __FUNCTION__);
@@ -450,8 +483,7 @@
             object->mDeviceCallback->dataCallbackTimestamp(
                     (DataCallbackMsg) msg_type, mem->handle.mId, index, timestamp);
         } else {
-            object->mDeviceCallback->handleCallbackTimestamp(
-                    (DataCallbackMsg) msg_type, handle, mem->handle.mId, index, timestamp);
+            object->handleCallbackTimestamp(timestamp, msg_type, mem->handle.mId, index, handle);
         }
     }
 }
@@ -827,6 +859,17 @@
     return Void();
 }
 
+Return<void> CameraDevice::releaseRecordingFrameHandleBatch(
+        const hidl_vec<VideoFrameMessage>& msgs) {
+    ALOGV("%s(%s)", __FUNCTION__, mCameraId.c_str());
+    Mutex::Autolock _l(mLock);
+    for (auto& msg : msgs) {
+        releaseRecordingFrameLocked(
+                msg.data, msg.bufferIndex, msg.frameData.getNativeHandle());
+    }
+    return Void();
+}
+
 Return<Status> CameraDevice::autoFocus() {
     ALOGV("%s(%s)", __FUNCTION__, mCameraId.c_str());
     Mutex::Autolock _l(mLock);
diff --git a/camera/device/1.0/default/CameraDevice_1_0.h b/camera/device/1.0/default/CameraDevice_1_0.h
index 2568f86..ad5f582 100644
--- a/camera/device/1.0/default/CameraDevice_1_0.h
+++ b/camera/device/1.0/default/CameraDevice_1_0.h
@@ -93,6 +93,8 @@
     Return<void> releaseRecordingFrame(uint32_t memId, uint32_t bufferIndex) override;
     Return<void> releaseRecordingFrameHandle(
             uint32_t memId, uint32_t bufferIndex, const hidl_handle& frame) override;
+    Return<void> releaseRecordingFrameHandleBatch(
+            const hidl_vec<VideoFrameMessage>&) override;
     Return<Status> autoFocus() override;
     Return<Status> cancelAutoFocus() override;
     Return<Status> takePicture() override;
@@ -169,6 +171,16 @@
 
     bool mMetadataMode = false;
 
+    mutable Mutex mBatchLock;
+    // Start of protection scope for mBatchLock
+    uint32_t mBatchSize = 0; // 0 for non-batch mode, set to other value to start batching
+    int32_t mBatchMsgType;   // Maybe only allow DataCallbackMsg::VIDEO_FRAME?
+    std::vector<HandleTimestampMessage> mInflightBatch;
+    // End of protection scope for mBatchLock
+
+    void handleCallbackTimestamp(
+            nsecs_t timestamp, int32_t msg_type,
+            MemoryId memId , unsigned index, native_handle_t* handle);
     void releaseRecordingFrameLocked(uint32_t memId, uint32_t bufferIndex, const native_handle_t*);
 
     // shared memory methods
@@ -178,13 +190,13 @@
     // Device callback forwarding methods
     static void sNotifyCb(int32_t msg_type, int32_t ext1, int32_t ext2, void *user);
     static void sDataCb(int32_t msg_type, const camera_memory_t *data, unsigned int index,
-                          camera_frame_metadata_t *metadata, void *user);
+                        camera_frame_metadata_t *metadata, void *user);
     static void sDataCbTimestamp(nsecs_t timestamp, int32_t msg_type,
                                     const camera_memory_t *data, unsigned index, void *user);
 
     // Preview window callback forwarding methods
     static int sDequeueBuffer(struct preview_stream_ops* w,
-                                buffer_handle_t** buffer, int *stride);
+                              buffer_handle_t** buffer, int *stride);
 
     static int sLockBuffer(struct preview_stream_ops* w, buffer_handle_t* buffer);
 
@@ -195,7 +207,7 @@
     static int sSetBufferCount(struct preview_stream_ops* w, int count);
 
     static int sSetBuffersGeometry(struct preview_stream_ops* w,
-                                     int width, int height, int format);
+                                   int width, int height, int format);
 
     static int sSetCrop(struct preview_stream_ops *w, int left, int top, int right, int bottom);