Camera2: Synchronize mode changes and triggers

Make sure that changes to various parameters have reached the HAL
before triggering asynchronous events like autofocus or precapture
metering.

Bug: 7107220
Change-Id: I3c50038de1671968eb32004ce538435121934e7e
diff --git a/services/camera/libcameraservice/Camera2Device.cpp b/services/camera/libcameraservice/Camera2Device.cpp
index 25b7a58..d6445c1 100644
--- a/services/camera/libcameraservice/Camera2Device.cpp
+++ b/services/camera/libcameraservice/Camera2Device.cpp
@@ -27,6 +27,7 @@
 
 #include <utils/Log.h>
 #include <utils/Trace.h>
+#include <utils/Timers.h>
 #include "Camera2Device.h"
 
 namespace android {
@@ -228,6 +229,11 @@
     return mRequestQueue.setStreamSlot(NULL);
 }
 
+status_t Camera2Device::waitUntilRequestReceived(int32_t requestId, nsecs_t timeout) {
+    ATRACE_CALL();
+    return mRequestQueue.waitForDequeue(requestId, timeout);
+}
+
 status_t Camera2Device::createStream(sp<ANativeWindow> consumer,
         uint32_t width, uint32_t height, int format, size_t size, int *id) {
     ATRACE_CALL();
@@ -567,6 +573,7 @@
 Camera2Device::MetadataQueue::MetadataQueue():
             mDevice(NULL),
             mFrameCount(0),
+            mLatestRequestId(0),
             mCount(0),
             mStreamSlotCount(0),
             mSignalConsumer(true)
@@ -678,6 +685,16 @@
         mFrameCount++;
     }
 
+    // Check for request ID, and if present, signal waiters.
+    camera_metadata_entry_t requestId;
+    res = find_camera_metadata_entry(b,
+            ANDROID_REQUEST_ID,
+            &requestId);
+    if (res == OK) {
+        mLatestRequestId = requestId.data.i32[0];
+        mNewRequestId.signal();
+    }
+
     *buf = b;
     mCount--;
 
@@ -695,6 +712,22 @@
     return OK;
 }
 
+status_t Camera2Device::MetadataQueue::waitForDequeue(int32_t id,
+        nsecs_t timeout) {
+    Mutex::Autolock l(mMutex);
+    status_t res;
+    while (mLatestRequestId != id) {
+        nsecs_t startTime = systemTime();
+
+        res = mNewRequestId.waitRelative(mMutex, timeout);
+        if (res != OK) return res;
+
+        timeout -= (systemTime() - startTime);
+    }
+
+    return OK;
+}
+
 status_t Camera2Device::MetadataQueue::setStreamSlot(camera_metadata_t *buf)
 {
     ATRACE_CALL();