Add buffer management to V4L2 wrapper.

Functions to enqueue and dequeue buffers.
Extended gralloc helper with a mass-unlock function.

Change-Id: I72c83138fd37463d314bf02b5df5befc68bc05af
diff --git a/modules/camera/3_4/V4L2Gralloc.cpp b/modules/camera/3_4/V4L2Gralloc.cpp
index d46d119..111996e 100644
--- a/modules/camera/3_4/V4L2Gralloc.cpp
+++ b/modules/camera/3_4/V4L2Gralloc.cpp
@@ -82,14 +82,7 @@
   HAL_LOG_ENTER();
 
   // Unlock buffers that are still locked.
-  for (auto const& entry : mBufferMap) {
-    mModule->unlock(mModule, *entry.second->camera_buffer->buffer);
-    // Clean up dynamically allocated stuff.
-    if (entry.second->transform_dest) {
-      delete [] reinterpret_cast<uint8_t*>(entry.first);
-    }
-    delete entry.second;
-  }
+  unlockAllBuffers();
 }
 
 int V4L2Gralloc::lock(const camera3_stream_buffer_t* camera_buffer,
@@ -270,4 +263,31 @@
   return 0;
 }
 
+int V4L2Gralloc::unlockAllBuffers() {
+  HAL_LOG_ENTER();
+
+  bool failed = false;
+  for (auto const& entry : mBufferMap) {
+    int res = mModule->unlock(mModule, *entry.second->camera_buffer->buffer);
+    if (res) {
+      failed = true;
+    }
+    // When there is a transform to be made, the buffer returned by lock()
+    // is dynamically allocated (to hold the pre-transform data).
+    if (entry.second->transform_dest) {
+      delete [] reinterpret_cast<uint8_t*>(entry.first);
+    }
+    // The BufferData entry is always dynamically allocated in lock().
+    delete entry.second;
+  }
+
+  // If any unlock failed, return error.
+  if (failed) {
+    return -ENODEV;
+  }
+
+  return 0;
+}
+
+
 } // namespace default_camera_hal