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/Camera2Client.cpp b/services/camera/libcameraservice/Camera2Client.cpp
index 948b59f..9bcaef1 100644
--- a/services/camera/libcameraservice/Camera2Client.cpp
+++ b/services/camera/libcameraservice/Camera2Client.cpp
@@ -536,7 +536,7 @@
             // Already running preview - need to stop and create a new stream
             // TODO: Optimize this so that we don't wait for old stream to drain
             // before spinning up new stream
-            mDevice->clearStreamingRequest();
+            mStreamingProcessor->stopStream();
             l.mParameters.state = Parameters::WAITING_FOR_PREVIEW_WINDOW;
             break;
     }
@@ -719,6 +719,7 @@
 
 void Camera2Client::stopPreviewL() {
     ATRACE_CALL();
+    status_t res;
     Parameters::State state;
     {
         SharedParameters::Lock l(mParameters);
@@ -740,6 +741,11 @@
             // no break - identical to preview
         case Parameters::PREVIEW:
             mStreamingProcessor->stopStream();
+            res = mDevice->waitUntilDrained();
+            if (res != OK) {
+                ALOGE("%s: Camera %d: Waiting to stop streaming failed: %s (%d)",
+                        __FUNCTION__, mCameraId, strerror(-res), res);
+            }
             // no break
         case Parameters::WAITING_FOR_PREVIEW_WINDOW: {
             SharedParameters::Lock l(mParameters);
@@ -946,9 +952,14 @@
     int triggerId;
     {
         SharedParameters::Lock l(mParameters);
+        if (l.mParameters.state < Parameters::PREVIEW) {
+            return INVALID_OPERATION;
+        }
+
         l.mParameters.currentAfTriggerId = ++l.mParameters.afTriggerCounter;
         triggerId = l.mParameters.currentAfTriggerId;
     }
+    syncWithDevice();
 
     mDevice->triggerAutofocus(triggerId);
 
@@ -967,6 +978,7 @@
         SharedParameters::Lock l(mParameters);
         triggerId = ++l.mParameters.afTriggerCounter;
     }
+    syncWithDevice();
 
     mDevice->triggerCancelAutofocus(triggerId);
 
@@ -1017,6 +1029,9 @@
         return res;
     }
 
+    // Need HAL to have correct settings before (possibly) triggering precapture
+    syncWithDevice();
+
     res = mCaptureSequencer->startCapture();
     if (res != OK) {
         ALOGE("%s: Camera %d: Unable to start capture: %s (%d)",
@@ -1397,13 +1412,18 @@
     return mZslProcessor->getStreamId();
 }
 
-status_t Camera2Client::registerFrameListener(int32_t id,
+status_t Camera2Client::registerFrameListener(int32_t minId, int32_t maxId,
         wp<camera2::FrameProcessor::FilteredListener> listener) {
-    return mFrameProcessor->registerListener(id, listener);
+    return mFrameProcessor->registerListener(minId, maxId, listener);
 }
 
-status_t Camera2Client::removeFrameListener(int32_t id) {
-    return mFrameProcessor->removeListener(id);
+status_t Camera2Client::removeFrameListener(int32_t minId, int32_t maxId,
+        wp<camera2::FrameProcessor::FilteredListener> listener) {
+    return mFrameProcessor->removeListener(minId, maxId, listener);
+}
+
+status_t Camera2Client::stopStream() {
+    return mStreamingProcessor->stopStream();
 }
 
 Camera2Client::SharedCameraClient::Lock::Lock(SharedCameraClient &client):
@@ -1432,9 +1452,12 @@
     mCameraClient.clear();
 }
 
-const int32_t Camera2Client::kPreviewRequestId;
-const int32_t Camera2Client::kRecordRequestId;
-const int32_t Camera2Client::kFirstCaptureRequestId;
+const int32_t Camera2Client::kPreviewRequestIdStart;
+const int32_t Camera2Client::kPreviewRequestIdEnd;
+const int32_t Camera2Client::kRecordingRequestIdStart;
+const int32_t Camera2Client::kRecordingRequestIdEnd;
+const int32_t Camera2Client::kCaptureRequestIdStart;
+const int32_t Camera2Client::kCaptureRequestIdEnd;
 
 /** Utility methods */
 
@@ -1443,6 +1466,13 @@
 
     ALOGV("%s: Camera %d: state = %d", __FUNCTION__, getCameraId(), params.state);
 
+    res = mStreamingProcessor->incrementStreamingIds();
+    if (res != OK) {
+        ALOGE("%s: Camera %d: Unable to increment request IDs: %s (%d)",
+                __FUNCTION__, mCameraId, strerror(-res), res);
+        return res;
+    }
+
     res = mStreamingProcessor->updatePreviewRequest(params);
     if (res != OK) {
         ALOGE("%s: Camera %d: Unable to update preview request: %s (%d)",
@@ -1504,4 +1534,23 @@
     }
 }
 
+status_t Camera2Client::syncWithDevice() {
+    ATRACE_CALL();
+    const nsecs_t kMaxSyncTimeout = 100000000; // 100 ms
+    status_t res;
+
+    int32_t activeRequestId = mStreamingProcessor->getActiveRequestId();
+    if (activeRequestId == 0) return OK;
+
+    res = mDevice->waitUntilRequestReceived(activeRequestId, kMaxSyncTimeout);
+    if (res == TIMED_OUT) {
+        ALOGE("%s: Camera %d: Timed out waiting sync with HAL",
+                __FUNCTION__, mCameraId);
+    } else if (res != OK) {
+        ALOGE("%s: Camera %d: Error while waiting to sync with HAL",
+                __FUNCTION__, mCameraId);
+    }
+    return res;
+}
+
 } // namespace android