Camera2: Copy metadata buffers for streaming.
Using the passed-in buffer directly is incorrect; copy them so that
concurrent access can be controlled, and ownership is clear.
Bug: 6243944
Change-Id: Iad22c0dc166b7739e6c5dbfa39aac631b974c95a
diff --git a/services/camera/libcameraservice/Camera2Device.cpp b/services/camera/libcameraservice/Camera2Device.cpp
index 6a1e9ea..b81d54c 100644
--- a/services/camera/libcameraservice/Camera2Device.cpp
+++ b/services/camera/libcameraservice/Camera2Device.cpp
@@ -302,6 +302,12 @@
mStreamSlotCount = 0;
return OK;
}
+ camera_metadata_t *buf2 = clone_camera_metadata(buf);
+ if (!buf2) {
+ ALOGE("%s: Unable to clone metadata buffer!", __FUNCTION__);
+ return NO_MEMORY;
+ }
+
if (mStreamSlotCount > 1) {
List<camera_metadata_t*>::iterator deleter = ++mStreamSlot.begin();
freeBuffers(++mStreamSlot.begin(), mStreamSlot.end());
@@ -309,9 +315,9 @@
}
if (mStreamSlotCount == 1) {
free_camera_metadata( *(mStreamSlot.begin()) );
- *(mStreamSlot.begin()) = buf;
+ *(mStreamSlot.begin()) = buf2;
} else {
- mStreamSlot.push_front(buf);
+ mStreamSlot.push_front(buf2);
mStreamSlotCount = 1;
}
return signalConsumerLocked();
@@ -322,11 +328,22 @@
{
ALOGV("%s: E", __FUNCTION__);
Mutex::Autolock l(mMutex);
+ status_t res;
+
if (mStreamSlotCount > 0) {
freeBuffers(mStreamSlot.begin(), mStreamSlot.end());
}
- mStreamSlot = bufs;
- mStreamSlotCount = mStreamSlot.size();
+ mStreamSlotCount = 0;
+ for (List<camera_metadata_t*>::const_iterator r = bufs.begin();
+ r != bufs.end(); r++) {
+ camera_metadata_t *r2 = clone_camera_metadata(*r);
+ if (!r2) {
+ ALOGE("%s: Unable to clone metadata buffer!", __FUNCTION__);
+ return NO_MEMORY;
+ }
+ mStreamSlot.push_back(r2);
+ mStreamSlotCount++;
+ }
return signalConsumerLocked();
}
diff --git a/services/camera/libcameraservice/Camera2Device.h b/services/camera/libcameraservice/Camera2Device.h
index e8a68d3..2da3ade 100644
--- a/services/camera/libcameraservice/Camera2Device.h
+++ b/services/camera/libcameraservice/Camera2Device.h
@@ -87,7 +87,8 @@
// Set repeating buffer(s); if the queue is empty on a dequeue call, the
// queue copies the contents of the stream slot into the queue, and then
- // dequeues the first new entry.
+ // dequeues the first new entry. The metadata buffers passed in are
+ // copied.
status_t setStreamSlot(camera_metadata_t *buf);
status_t setStreamSlot(const List<camera_metadata_t*> &bufs);