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/camera2/CaptureSequencer.cpp b/services/camera/libcameraservice/camera2/CaptureSequencer.cpp
index d56af64..a849246 100644
--- a/services/camera/libcameraservice/camera2/CaptureSequencer.cpp
+++ b/services/camera/libcameraservice/camera2/CaptureSequencer.cpp
@@ -44,7 +44,7 @@
         mCaptureState(IDLE),
         mTriggerId(0),
         mTimeoutCount(0),
-        mCaptureId(Camera2Client::kFirstCaptureRequestId) {
+        mCaptureId(Camera2Client::kCaptureRequestIdStart) {
     ALOGV("%s", __FUNCTION__);
 }
 
@@ -84,12 +84,12 @@
 }
 
 void CaptureSequencer::onFrameAvailable(int32_t frameId,
-        CameraMetadata &frame) {
+        const CameraMetadata &frame) {
     ALOGV("%s: Listener found new frame", __FUNCTION__);
     ATRACE_CALL();
     Mutex::Autolock l(mInputMutex);
     mNewFrameId = frameId;
-    mNewFrame.acquire(frame);
+    mNewFrame = frame;
     if (!mNewFrameReceived) {
         mNewFrameReceived = true;
         mNewFrameSignal.signal();
@@ -203,7 +203,9 @@
     status_t res = OK;
     ATRACE_CALL();
     mCaptureId++;
-
+    if (mCaptureId >= Camera2Client::kCaptureRequestIdEnd) {
+        mCaptureId = Camera2Client::kCaptureRequestIdStart;
+    }
     {
         Mutex::Autolock l(mInputMutex);
         mBusy = false;
@@ -286,7 +288,7 @@
         return DONE;
     }
 
-    client->registerFrameListener(mCaptureId,
+    client->registerFrameListener(mCaptureId, mCaptureId + 1,
             this);
 
     // TODO: Actually select the right thing here.
@@ -326,7 +328,7 @@
 CaptureSequencer::CaptureState CaptureSequencer::manageStandardStart(
         sp<Camera2Client> &client) {
     ATRACE_CALL();
-    client->registerFrameListener(mCaptureId,
+    client->registerFrameListener(mCaptureId, mCaptureId + 1,
             this);
     {
         SharedParameters::Lock l(client->getParameters());
@@ -421,7 +423,7 @@
     }
 
     if (l.mParameters.state == Parameters::STILL_CAPTURE) {
-        res = client->getCameraDevice()->clearStreamingRequest();
+        res = client->stopStream();
         if (res != OK) {
             ALOGE("%s: Camera %d: Unable to stop preview for still capture: "
                     "%s (%d)",
@@ -482,7 +484,7 @@
             ALOGW("Mismatched capture timestamps: Metadata frame %lld,"
                     " captured buffer %lld", entry.data.i64[0], mCaptureTimestamp);
         }
-        client->removeFrameListener(mCaptureId);
+        client->removeFrameListener(mCaptureId, mCaptureId + 1, this);
 
         mNewFrameReceived = false;
         mNewCaptureReceived = false;
diff --git a/services/camera/libcameraservice/camera2/CaptureSequencer.h b/services/camera/libcameraservice/camera2/CaptureSequencer.h
index 27f3f1c..07e4c01 100644
--- a/services/camera/libcameraservice/camera2/CaptureSequencer.h
+++ b/services/camera/libcameraservice/camera2/CaptureSequencer.h
@@ -57,7 +57,7 @@
     void notifyAutoExposure(uint8_t newState, int triggerId);
 
     // Notifications from the frame processor
-    virtual void onFrameAvailable(int32_t frameId, CameraMetadata &frame);
+    virtual void onFrameAvailable(int32_t frameId, const CameraMetadata &frame);
 
     // Notifications from the JPEG processor
     void onCaptureAvailable(nsecs_t timestamp, sp<MemoryBase> captureBuffer);
diff --git a/services/camera/libcameraservice/camera2/FrameProcessor.cpp b/services/camera/libcameraservice/camera2/FrameProcessor.cpp
index 0c8560b..064607c 100644
--- a/services/camera/libcameraservice/camera2/FrameProcessor.cpp
+++ b/services/camera/libcameraservice/camera2/FrameProcessor.cpp
@@ -36,17 +36,30 @@
     ALOGV("%s: Exit", __FUNCTION__);
 }
 
-status_t FrameProcessor::registerListener(int32_t id,
-        wp<FilteredListener> listener) {
+status_t FrameProcessor::registerListener(int32_t minId,
+        int32_t maxId, wp<FilteredListener> listener) {
     Mutex::Autolock l(mInputMutex);
-    ALOGV("%s: Registering listener for frame id %d",
-            __FUNCTION__, id);
-    return mListeners.replaceValueFor(id, listener);
+    ALOGV("%s: Registering listener for frame id range %d - %d",
+            __FUNCTION__, minId, maxId);
+    RangeListener rListener = { minId, maxId, listener };
+    mRangeListeners.push_back(rListener);
+    return OK;
 }
 
-status_t FrameProcessor::removeListener(int32_t id) {
+status_t FrameProcessor::removeListener(int32_t minId,
+        int32_t maxId, wp<FilteredListener> listener) {
     Mutex::Autolock l(mInputMutex);
-    return mListeners.removeItem(id);
+    List<RangeListener>::iterator item = mRangeListeners.begin();
+    while (item != mRangeListeners.end()) {
+        if (item->minId == minId &&
+                item->maxId == maxId &&
+                item->listener == listener) {
+            item = mRangeListeners.erase(item);
+        } else {
+            item++;
+        }
+    }
+    return OK;
 }
 
 void FrameProcessor::dump(int fd, const Vector<String16>& args) {
@@ -97,8 +110,7 @@
         res = processFaceDetect(frame, client);
         if (res != OK) break;
 
-        // Must be last - listener can take ownership of frame
-        res = processListener(frame, client);
+        res = processListeners(frame, client);
         if (res != OK) break;
 
         if (!frame.isEmpty()) {
@@ -114,11 +126,11 @@
     return;
 }
 
-status_t FrameProcessor::processListener(CameraMetadata &frame,
+status_t FrameProcessor::processListeners(const CameraMetadata &frame,
         sp<Camera2Client> &client) {
     status_t res;
     ATRACE_CALL();
-    camera_metadata_entry_t entry;
+    camera_metadata_ro_entry_t entry;
 
     entry = frame.find(ANDROID_REQUEST_ID);
     if (entry.count == 0) {
@@ -127,22 +139,30 @@
         return BAD_VALUE;
     }
     int32_t frameId = entry.data.i32[0];
-    ALOGV("%s: Got frame with ID %d", __FUNCTION__, frameId);
 
-    sp<FilteredListener> listener;
+    List<sp<FilteredListener> > listeners;
     {
         Mutex::Autolock l(mInputMutex);
-        ssize_t listenerIndex = mListeners.indexOfKey(frameId);
-        if (listenerIndex != NAME_NOT_FOUND) {
-            listener = mListeners[listenerIndex].promote();
-            if (listener == 0) {
-                mListeners.removeItemsAt(listenerIndex, 1);
+
+        List<RangeListener>::iterator item = mRangeListeners.begin();
+        while (item != mRangeListeners.end()) {
+            if (frameId >= item->minId &&
+                    frameId < item->maxId) {
+                sp<FilteredListener> listener = item->listener.promote();
+                if (listener == 0) {
+                    item = mRangeListeners.erase(item);
+                    continue;
+                } else {
+                    listeners.push_back(listener);
+                }
             }
+            item++;
         }
     }
-
-    if (listener != 0) {
-        listener->onFrameAvailable(frameId, frame);
+    ALOGV("Got %d range listeners out of %d", listeners.size(), mRangeListeners.size());
+    List<sp<FilteredListener> >::iterator item = listeners.begin();
+    for (; item != listeners.end(); item++) {
+        (*item)->onFrameAvailable(frameId, frame);
     }
     return OK;
 }
diff --git a/services/camera/libcameraservice/camera2/FrameProcessor.h b/services/camera/libcameraservice/camera2/FrameProcessor.h
index cc8c128..3bd4e25 100644
--- a/services/camera/libcameraservice/camera2/FrameProcessor.h
+++ b/services/camera/libcameraservice/camera2/FrameProcessor.h
@@ -21,6 +21,7 @@
 #include <utils/String16.h>
 #include <utils/Vector.h>
 #include <utils/KeyedVector.h>
+#include <utils/List.h>
 #include "CameraMetadata.h"
 
 struct camera_frame_metadata;
@@ -40,15 +41,14 @@
     ~FrameProcessor();
 
     struct FilteredListener: virtual public RefBase {
-        // Listener may take ownership of frame
-        virtual void onFrameAvailable(int32_t frameId, CameraMetadata &frame) = 0;
+        virtual void onFrameAvailable(int32_t frameId,
+                const CameraMetadata &frame) = 0;
     };
 
-    // Register a listener for a specific frame ID (android.request.id).
-    // De-registers any existing listeners for that ID
-    status_t registerListener(int32_t id, wp<FilteredListener> listener);
-
-    status_t removeListener(int32_t id);
+    // Register a listener for a range of IDs [minId, maxId). Multiple listeners
+    // can be listening to the same range
+    status_t registerListener(int32_t minId, int32_t maxId, wp<FilteredListener> listener);
+    status_t removeListener(int32_t minId, int32_t maxId, wp<FilteredListener> listener);
 
     void dump(int fd, const Vector<String16>& args);
   private:
@@ -58,14 +58,20 @@
     virtual bool threadLoop();
 
     Mutex mInputMutex;
-    KeyedVector<int32_t, wp<FilteredListener> > mListeners;
+
+    struct RangeListener {
+        int32_t minId;
+        int32_t maxId;
+        wp<FilteredListener> listener;
+    };
+    List<RangeListener> mRangeListeners;
 
     void processNewFrames(sp<Camera2Client> &client);
 
     status_t processFaceDetect(const CameraMetadata &frame,
             sp<Camera2Client> &client);
 
-    status_t processListener(CameraMetadata &frame,
+    status_t processListeners(const CameraMetadata &frame,
             sp<Camera2Client> &client);
 
     CameraMetadata mLastFrame;
diff --git a/services/camera/libcameraservice/camera2/StreamingProcessor.cpp b/services/camera/libcameraservice/camera2/StreamingProcessor.cpp
index 8921172..207f780 100644
--- a/services/camera/libcameraservice/camera2/StreamingProcessor.cpp
+++ b/services/camera/libcameraservice/camera2/StreamingProcessor.cpp
@@ -33,7 +33,10 @@
 
 StreamingProcessor::StreamingProcessor(wp<Camera2Client> client):
         mClient(client),
+        mActiveRequest(NONE),
+        mPreviewRequestId(Camera2Client::kPreviewRequestIdStart),
         mPreviewStreamId(NO_STREAM),
+        mRecordingRequestId(Camera2Client::kRecordingRequestIdStart),
         mRecordingStreamId(NO_STREAM),
         mRecordingHeapCount(kDefaultRecordingHeapCount)
 {
@@ -90,7 +93,12 @@
     }
 
     res = mPreviewRequest.update(ANDROID_REQUEST_ID,
-            &Camera2Client::kPreviewRequestId, 1);
+            &mPreviewRequestId, 1);
+    if (res != OK) {
+        ALOGE("%s: Camera %d: Unable to update request id for preview: %s (%d)",
+                __FUNCTION__, client->getCameraId(), strerror(-res), res);
+        return res;
+    }
 
     return OK;
 }
@@ -190,7 +198,7 @@
     return OK;
 }
 
-status_t StreamingProcessor::getPreviewStreamId() const {
+int StreamingProcessor::getPreviewStreamId() const {
     Mutex::Autolock m(mMutex);
     return mPreviewStreamId;
 }
@@ -246,6 +254,14 @@
         return res;
     }
 
+    res = mRecordingRequest.update(ANDROID_REQUEST_ID,
+            &mRecordingRequestId, 1);
+    if (res != OK) {
+        ALOGE("%s: Camera %d: Unable to update request id for request: %s (%d)",
+                __FUNCTION__, client->getCameraId(), strerror(-res), res);
+        return res;
+    }
+
     return OK;
 }
 
@@ -342,7 +358,7 @@
     return OK;
 }
 
-status_t StreamingProcessor::getRecordingStreamId() const {
+int StreamingProcessor::getRecordingStreamId() const {
     return mRecordingStreamId;
 }
 
@@ -351,6 +367,8 @@
     ATRACE_CALL();
     status_t res;
 
+    if (type == NONE) return INVALID_OPERATION;
+
     sp<Camera2Client> client = mClient.promote();
     if (client == 0) return INVALID_OPERATION;
 
@@ -384,6 +402,7 @@
                 __FUNCTION__, client->getCameraId(), strerror(-res), res);
         return res;
     }
+    mActiveRequest = type;
 
     return OK;
 }
@@ -392,6 +411,8 @@
     ATRACE_CALL();
     status_t res;
 
+    Mutex::Autolock m(mMutex);
+
     sp<Camera2Client> client = mClient.promote();
     if (client == 0) return INVALID_OPERATION;
     sp<Camera2Device> device = client->getCameraDevice();
@@ -402,11 +423,38 @@
                 __FUNCTION__, client->getCameraId(), strerror(-res), res);
         return res;
     }
-    res = device->waitUntilDrained();
-    if (res != OK) {
-        ALOGE("%s: Camera %d: Waiting to stop streaming failed: %s (%d)",
-                __FUNCTION__, client->getCameraId(), strerror(-res), res);
-        return res;
+    mActiveRequest = NONE;
+
+    return OK;
+}
+
+int32_t StreamingProcessor::getActiveRequestId() const {
+    Mutex::Autolock m(mMutex);
+    switch (mActiveRequest) {
+        case NONE:
+            return 0;
+        case PREVIEW:
+            return mPreviewRequestId;
+        case RECORD:
+            return mRecordingRequestId;
+        default:
+            ALOGE("%s: Unexpected mode %d", __FUNCTION__, mActiveRequest);
+            return 0;
+    }
+}
+
+status_t StreamingProcessor::incrementStreamingIds() {
+    ATRACE_CALL();
+    Mutex::Autolock m(mMutex);
+
+    status_t res;
+    mPreviewRequestId++;
+    if (mPreviewRequestId >= Camera2Client::kPreviewRequestIdEnd) {
+        mPreviewRequestId = Camera2Client::kPreviewRequestIdStart;
+    }
+    mRecordingRequestId++;
+    if (mRecordingRequestId >= Camera2Client::kRecordingRequestIdEnd) {
+        mRecordingRequestId = Camera2Client::kRecordingRequestIdStart;
     }
     return OK;
 }
diff --git a/services/camera/libcameraservice/camera2/StreamingProcessor.h b/services/camera/libcameraservice/camera2/StreamingProcessor.h
index ac58614..96b100f 100644
--- a/services/camera/libcameraservice/camera2/StreamingProcessor.h
+++ b/services/camera/libcameraservice/camera2/StreamingProcessor.h
@@ -57,6 +57,7 @@
     int getRecordingStreamId() const;
 
     enum StreamType {
+        NONE,
         PREVIEW,
         RECORD
     };
@@ -65,6 +66,11 @@
 
     status_t stopStream();
 
+    // Returns the request ID for the currently streaming request
+    // Returns 0 if there is no active request.
+    status_t getActiveRequestId() const;
+    status_t incrementStreamingIds();
+
     // Callback for new recording frames from HAL
     virtual void onFrameAvailable();
     // Callback from stagefright which returns used recording frames
@@ -81,12 +87,16 @@
 
     wp<Camera2Client> mClient;
 
+    StreamType mActiveRequest;
+
     // Preview-related members
+    int32_t mPreviewRequestId;
     int mPreviewStreamId;
     CameraMetadata mPreviewRequest;
     sp<ANativeWindow> mPreviewWindow;
 
     // Recording-related members
+    int32_t mRecordingRequestId;
     int mRecordingStreamId;
     int mRecordingFrameCount;
     sp<BufferItemConsumer> mRecordingConsumer;
diff --git a/services/camera/libcameraservice/camera2/ZslProcessor.cpp b/services/camera/libcameraservice/camera2/ZslProcessor.cpp
index 56e9743..5208574 100644
--- a/services/camera/libcameraservice/camera2/ZslProcessor.cpp
+++ b/services/camera/libcameraservice/camera2/ZslProcessor.cpp
@@ -69,16 +69,16 @@
     }
 }
 
-void ZslProcessor::onFrameAvailable(int32_t frameId, CameraMetadata &frame) {
+void ZslProcessor::onFrameAvailable(int32_t frameId, const CameraMetadata &frame) {
     Mutex::Autolock l(mInputMutex);
-    camera_metadata_entry_t entry;
+    camera_metadata_ro_entry_t entry;
     entry = frame.find(ANDROID_SENSOR_TIMESTAMP);
     nsecs_t timestamp = entry.data.i64[0];
     ALOGVV("Got preview frame for timestamp %lld", timestamp);
 
     if (mState != RUNNING) return;
 
-    mFrameList.editItemAt(mFrameListHead).acquire(frame);
+    mFrameList.editItemAt(mFrameListHead) = frame;
     mFrameListHead = (mFrameListHead + 1) % kFrameListDepth;
 
     findMatchesLocked();
@@ -185,7 +185,9 @@
             return res;
         }
     }
-    client->registerFrameListener(Camera2Client::kPreviewRequestId, this);
+    client->registerFrameListener(Camera2Client::kPreviewRequestIdStart,
+            Camera2Client::kPreviewRequestIdEnd,
+            this);
 
     return OK;
 }
@@ -297,7 +299,7 @@
             return INVALID_OPERATION;
         }
 
-        res = client->getCameraDevice()->clearStreamingRequest();
+        res = client->stopStream();
         if (res != OK) {
             ALOGE("%s: Camera %d: Unable to stop preview for ZSL capture: "
                 "%s (%d)",
diff --git a/services/camera/libcameraservice/camera2/ZslProcessor.h b/services/camera/libcameraservice/camera2/ZslProcessor.h
index 1f433ce..c80e7f4 100644
--- a/services/camera/libcameraservice/camera2/ZslProcessor.h
+++ b/services/camera/libcameraservice/camera2/ZslProcessor.h
@@ -52,7 +52,7 @@
     // From mZslConsumer
     virtual void onFrameAvailable();
     // From FrameProcessor
-    virtual void onFrameAvailable(int32_t frameId, CameraMetadata &frame);
+    virtual void onFrameAvailable(int32_t frameId, const CameraMetadata &frame);
 
     virtual void onBufferReleased(buffer_handle_t *handle);