HAL3: Fix a use-after-free bug

mm_camera_buf_def_t for the source YUV of HDR+ request is wrapped in a
shared_ptr, and the memory for mm_camera_buf_def_t is deallocated after
returnYuvBufferAndEncode returns.

However, mm_camera_buf_def_t pointer is still used in the JPEG callback
later on. So we keep the mm_camera_buf_def_t struct around by keeping a
shared pointer to it.

Also fix a memory leak of input metadata mm_camera_buf_def_t.

Test: for i in {1..50}; do atest -it NativeStillCaptureTest#testStillCapture; done
Bug: 150004253
Change-Id: I67ce2db1aca20245a5c3175008f17640fe6f5390
Merged-In: I67ce2db1aca20245a5c3175008f17640fe6f5390
diff --git a/msm8998/QCamera2/HAL3/QCamera3Channel.cpp b/msm8998/QCamera2/HAL3/QCamera3Channel.cpp
index 0d9d3f6..aa181cd 100644
--- a/msm8998/QCamera2/HAL3/QCamera3Channel.cpp
+++ b/msm8998/QCamera2/HAL3/QCamera3Channel.cpp
@@ -4084,7 +4084,7 @@
 
 int32_t QCamera3PicChannel::returnYuvBufferAndEncode(mm_camera_buf_def_t *frame,
         buffer_handle_t *outBuffer, uint32_t frameNumber,
-        std::shared_ptr<metadata_buffer_t> metadata)
+        std::shared_ptr<metadata_buffer_t> metadata, mm_camera_buf_def_t *metaFrame)
 {
     int32_t rc = OK;
 
@@ -4173,7 +4173,7 @@
     metadataBuf->camera_handle = m_camHandle;
     metadataBuf->ch_id = getMyHandle();
     metadataBuf->num_bufs = 1;
-    metadataBuf->bufs[0] = (mm_camera_buf_def_t *)calloc(1, sizeof(mm_camera_buf_def_t));
+    metadataBuf->bufs[0] = metaFrame;
     metadataBuf->bufs[0]->buffer = metadata.get();
 
     // Start processing the metadata
diff --git a/msm8998/QCamera2/HAL3/QCamera3Channel.h b/msm8998/QCamera2/HAL3/QCamera3Channel.h
index 4a8c358..7f97b82 100644
--- a/msm8998/QCamera2/HAL3/QCamera3Channel.h
+++ b/msm8998/QCamera2/HAL3/QCamera3Channel.h
@@ -581,7 +581,8 @@
     // Return a YUV buffer (from getYuvBufferForRequest) and request jpeg encoding.
     int32_t returnYuvBufferAndEncode(mm_camera_buf_def_t *frame,
             buffer_handle_t *outBuffer, uint32_t frameNumber,
-            std::shared_ptr<metadata_buffer_t> metadata);
+            std::shared_ptr<metadata_buffer_t> metadata,
+            mm_camera_buf_def_t *metaFrame);
 
     // Return a YUV buffer (from getYuvBufferForRequest) without requesting jpeg encoding.
     int32_t returnYuvBuffer(mm_camera_buf_def_t *frame);
diff --git a/msm8998/QCamera2/HAL3/QCamera3HWI.cpp b/msm8998/QCamera2/HAL3/QCamera3HWI.cpp
index d8a9a24..8dcba39 100644
--- a/msm8998/QCamera2/HAL3/QCamera3HWI.cpp
+++ b/msm8998/QCamera2/HAL3/QCamera3HWI.cpp
@@ -5513,7 +5513,6 @@
     bufsForCurRequest.frame_number = frameNumber;
     // Mark current timestamp for the new request
     bufsForCurRequest.timestamp = systemTime(CLOCK_MONOTONIC);
-    bufsForCurRequest.hdrplus = hdrPlusRequest;
 
     if (hdrPlusRequest) {
         // Save settings for this request.
@@ -14974,10 +14973,29 @@
         status_t res = translateFwkMetadataToHalMetadata(updatedResultMetadata, halMetadata.get(),
                 halStreamId, /*minFrameDuration*/0);
         if (res == OK) {
+            android_errorWriteLog(0x534e4554, "150004253");
+            // Keep a copy of outputBufferDef until the final JPEG buffer is
+            // ready because the JPEG callback uses the mm_camera_buf_def_t
+            // struct. The metaBufDef is stored in a shared_ptr to make sure
+            // it's freed.
+            std::shared_ptr<mm_camera_buf_def_t> metaBufDef =
+                    std::make_shared<mm_camera_buf_def_t>();
+            {
+                pthread_mutex_lock(&mMutex);
+                for (auto& pendingBuffers : mPendingBuffersMap.mPendingBuffersInRequest) {
+                    if (pendingBuffers.frame_number == result->requestId) {
+                        pendingBuffers.mHdrplusInputBuf = pendingRequest.yuvBuffer;
+                        pendingBuffers.mHdrplusInputMetaBuf = metaBufDef;
+                        break;
+                    }
+                }
+                pthread_mutex_unlock(&mMutex);
+            }
+
             // Return the buffer to pic channel for encoding.
             picChannel->returnYuvBufferAndEncode(pendingRequest.yuvBuffer.get(),
                     pendingRequest.frameworkOutputBuffers[0].buffer, result->requestId,
-                    halMetadata);
+                    halMetadata, metaBufDef.get());
         } else {
             // Return the buffer without encoding.
             // TODO: This should not happen but we may want to report an error buffer to camera
diff --git a/msm8998/QCamera2/HAL3/QCamera3HWI.h b/msm8998/QCamera2/HAL3/QCamera3HWI.h
index 9ef806f..6036838 100644
--- a/msm8998/QCamera2/HAL3/QCamera3HWI.h
+++ b/msm8998/QCamera2/HAL3/QCamera3HWI.h
@@ -125,7 +125,8 @@
     // Time when request queued into system
     nsecs_t timestamp;
     List<PendingBufferInfo> mPendingBufferList;
-    bool hdrplus;
+    std::shared_ptr<mm_camera_buf_def_t> mHdrplusInputBuf;
+    std::shared_ptr<mm_camera_buf_def_t> mHdrplusInputMetaBuf;
 } PendingBuffersInRequest;
 
 class PendingBuffersMap {