resolve merge conflicts of 3fce3ef to nyc-mr1-dev-plus-aosp

Change-Id: If319afe3976bedd64226e128164457f461eb7042
diff --git a/services/camera/libcameraservice/device3/Camera3BufferManager.cpp b/services/camera/libcameraservice/device3/Camera3BufferManager.cpp
index ae20887..1f01144 100644
--- a/services/camera/libcameraservice/device3/Camera3BufferManager.cpp
+++ b/services/camera/libcameraservice/device3/Camera3BufferManager.cpp
@@ -43,7 +43,8 @@
 Camera3BufferManager::~Camera3BufferManager() {
 }
 
-status_t Camera3BufferManager::registerStream(const StreamInfo& streamInfo) {
+status_t Camera3BufferManager::registerStream(wp<Camera3OutputStream>& stream,
+        const StreamInfo& streamInfo) {
     ATRACE_CALL();
 
     int streamId = streamInfo.streamId;
@@ -112,6 +113,8 @@
     }
     currentStreamSet.streamInfoMap.add(streamId, streamInfo);
     currentStreamSet.handoutBufferCountMap.add(streamId, 0);
+    currentStreamSet.attachedBufferCountMap.add(streamId, 0);
+    mStreamMap.add(streamId, stream);
 
     // The max allowed buffer count should be the max of buffer count of each stream inside a stream
     // set.
@@ -124,6 +127,7 @@
 
 status_t Camera3BufferManager::unregisterStream(int streamId, int streamSetId) {
     ATRACE_CALL();
+
     Mutex::Autolock l(mLock);
     ALOGV("%s: unregister stream %d with stream set %d", __FUNCTION__,
             streamId, streamSetId);
@@ -142,9 +146,11 @@
     StreamSet& currentSet = mStreamSetMap.editValueFor(streamSetId);
     BufferList& freeBufs = currentSet.freeBuffers;
     BufferCountMap& handOutBufferCounts = currentSet.handoutBufferCountMap;
+    BufferCountMap& attachedBufferCounts = currentSet.attachedBufferCountMap;
     InfoMap& infoMap = currentSet.streamInfoMap;
     removeBuffersFromBufferListLocked(freeBufs, streamId);
     handOutBufferCounts.removeItem(streamId);
+    attachedBufferCounts.removeItem(streamId);
 
     // Remove the stream info from info map and recalculate the buffer count water mark.
     infoMap.removeItem(streamId);
@@ -154,6 +160,8 @@
             currentSet.maxAllowedBufferCount = infoMap[i].totalBufferCount;
         }
     }
+    mStreamMap.removeItem(streamId);
+
     // Lazy solution: when a stream is unregistered, the streams will be reconfigured, reset
     // the water mark and let it grow again.
     currentSet.allocatedBufferWaterMark = 0;
@@ -193,6 +201,16 @@
         return INVALID_OPERATION;
     }
 
+    BufferCountMap& attachedBufferCounts = streamSet.attachedBufferCountMap;
+    size_t& attachedBufferCount = attachedBufferCounts.editValueFor(streamId);
+    if (attachedBufferCount > bufferCount) {
+        // We've already attached more buffers to this stream than we currently have
+        // outstanding, so have the stream just use an already-attached buffer
+        bufferCount++;
+        return ALREADY_EXISTS;
+    }
+    ALOGV("Stream %d set %d: Get buffer for stream: Allocate new", streamId, streamSetId);
+
     GraphicBufferEntry buffer =
             getFirstBufferFromBufferListLocked(streamSet.freeBuffers, streamId);
 
@@ -215,8 +233,9 @@
             ALOGV("%s: allocation done", __FUNCTION__);
         }
 
-        // Increase the hand-out buffer count for tracking purpose.
+        // Increase the hand-out and attached buffer counts for tracking purposes.
         bufferCount++;
+        attachedBufferCount++;
         // Update the water mark to be the max hand-out buffer count + 1. An additional buffer is
         // added to reduce the chance of buffer allocation during stream steady state, especially
         // for cases where one stream is active, the other stream may request some buffers randomly.
@@ -235,12 +254,25 @@
         // buffers for them.
         StreamId firstOtherStreamId = CAMERA3_STREAM_ID_INVALID;
         if (streamSet.streamInfoMap.size() > 1) {
+            bool freeBufferIsAttached = false;
             for (size_t i = 0; i < streamSet.streamInfoMap.size(); i++) {
                 firstOtherStreamId = streamSet.streamInfoMap[i].streamId;
-                if (firstOtherStreamId != streamId &&
-                        hasBufferForStreamLocked(streamSet.freeBuffers, firstOtherStreamId)) {
-                    break;
+                if (firstOtherStreamId != streamId) {
+
+                    size_t otherBufferCount  =
+                            streamSet.handoutBufferCountMap.valueFor(firstOtherStreamId);
+                    size_t otherAttachedBufferCount =
+                            streamSet.attachedBufferCountMap.valueFor(firstOtherStreamId);
+                    if (otherAttachedBufferCount > otherBufferCount) {
+                        freeBufferIsAttached = true;
+                        break;
+                    }
+                    if (hasBufferForStreamLocked(streamSet.freeBuffers, firstOtherStreamId)) {
+                        freeBufferIsAttached = false;
+                        break;
+                    }
                 }
+                firstOtherStreamId = CAMERA3_STREAM_ID_INVALID;
             }
             if (firstOtherStreamId == CAMERA3_STREAM_ID_INVALID) {
                 return OK;
@@ -249,12 +281,39 @@
             // This will drop the reference to one free buffer, which will effectively free one
             // buffer (from the free buffer list) for the inactive streams.
             size_t totalAllocatedBufferCount = streamSet.freeBuffers.size();
-            for (size_t i = 0; i < streamSet.handoutBufferCountMap.size(); i++) {
-                totalAllocatedBufferCount += streamSet.handoutBufferCountMap[i];
+            for (size_t i = 0; i < streamSet.attachedBufferCountMap.size(); i++) {
+                totalAllocatedBufferCount += streamSet.attachedBufferCountMap[i];
             }
             if (totalAllocatedBufferCount > streamSet.allocatedBufferWaterMark) {
                 ALOGV("%s: free a buffer from stream %d", __FUNCTION__, firstOtherStreamId);
-                getFirstBufferFromBufferListLocked(streamSet.freeBuffers, firstOtherStreamId);
+                if (freeBufferIsAttached) {
+                    ALOGV("Stream %d: Freeing buffer: detach", firstOtherStreamId);
+                    sp<Camera3OutputStream> stream =
+                            mStreamMap.valueFor(firstOtherStreamId).promote();
+                    if (stream == nullptr) {
+                        ALOGE("%s: unable to promote stream %d to detach buffer", __FUNCTION__,
+                                firstOtherStreamId);
+                        return INVALID_OPERATION;
+                    }
+
+                    // Detach and then drop the buffer.
+                    //
+                    // Need to unlock because the stream may also be calling
+                    // into the buffer manager in parallel to signal buffer
+                    // release, or acquire a new buffer.
+                    {
+                        mLock.unlock();
+                        sp<GraphicBuffer> buffer;
+                        stream->detachBuffer(&buffer, /*fenceFd*/ nullptr);
+                        mLock.lock();
+                    }
+                    size_t& otherAttachedBufferCount =
+                            streamSet.attachedBufferCountMap.editValueFor(firstOtherStreamId);
+                    otherAttachedBufferCount--;
+                } else {
+                    // Droppable buffer is in the free buffer list, grab and drop
+                    getFirstBufferFromBufferListLocked(streamSet.freeBuffers, firstOtherStreamId);
+                }
             }
         }
     } else {
@@ -265,6 +324,37 @@
     return OK;
 }
 
+status_t Camera3BufferManager::onBufferReleased(int streamId, int streamSetId) {
+    ATRACE_CALL();
+    Mutex::Autolock l(mLock);
+
+    ALOGV("Stream %d set %d: Buffer released", streamId, streamSetId);
+    if (mAllocator == NULL) {
+        ALOGE("%s: allocator is NULL, buffer manager is bad state.", __FUNCTION__);
+        return INVALID_OPERATION;
+    }
+
+    if (!checkIfStreamRegisteredLocked(streamId, streamSetId)){
+        ALOGV("%s: signaling buffer release for an already unregistered stream "
+                "(stream %d with set id %d)", __FUNCTION__, streamId, streamSetId);
+        return OK;
+    }
+
+    if (mGrallocVersion < HARDWARE_DEVICE_API_VERSION(1,0)) {
+        StreamSet& streamSet = mStreamSetMap.editValueFor(streamSetId);
+        BufferCountMap& handOutBufferCounts = streamSet.handoutBufferCountMap;
+        size_t& bufferCount = handOutBufferCounts.editValueFor(streamId);
+        bufferCount--;
+        ALOGV("%s: Stream %d set %d: Buffer count now %zu", __FUNCTION__, streamId, streamSetId,
+                bufferCount);
+    } else {
+        // TODO: implement gralloc V1 support
+        return BAD_VALUE;
+    }
+
+    return OK;
+}
+
 status_t Camera3BufferManager::returnBufferForStream(int streamId,
         int streamSetId, const sp<GraphicBuffer>& buffer, int fenceFd) {
     ATRACE_CALL();
@@ -295,10 +385,12 @@
             }
         }
 
-        // Update the hand-out buffer count for this buffer.
+        // Update the handed out and attached buffer count for this buffer.
         BufferCountMap& handOutBufferCounts = streamSet.handoutBufferCountMap;
         size_t& bufferCount = handOutBufferCounts.editValueFor(streamId);
         bufferCount--;
+        size_t& attachedBufferCount = streamSet.attachedBufferCountMap.editValueFor(streamId);
+        attachedBufferCount--;
     } else {
         // TODO: implement this.
         return BAD_VALUE;
@@ -329,6 +421,13 @@
             lines.appendFormat("            stream id: %d, buffer count: %zu.\n",
                     streamId, bufferCount);
         }
+        lines.appendFormat("          Attached buffer counts:\n");
+        for (size_t m = 0; m < mStreamSetMap[i].attachedBufferCountMap.size(); m++) {
+            int streamId = mStreamSetMap[i].attachedBufferCountMap.keyAt(m);
+            size_t bufferCount = mStreamSetMap[i].attachedBufferCountMap.valueAt(m);
+            lines.appendFormat("            stream id: %d, attached buffer count: %zu.\n",
+                    streamId, bufferCount);
+        }
 
         lines.appendFormat("          Free buffer count: %zu\n",
                 mStreamSetMap[i].freeBuffers.size());
@@ -394,9 +493,6 @@
         }
     }
 
-    ALOGW_IF(i == bufferList.end(), "%s: Unable to find buffers for stream %d",
-            __FUNCTION__, streamId);
-
     return OK;
 }
 
diff --git a/services/camera/libcameraservice/device3/Camera3BufferManager.h b/services/camera/libcameraservice/device3/Camera3BufferManager.h
index 7942ae6..ab6541e 100644
--- a/services/camera/libcameraservice/device3/Camera3BufferManager.h
+++ b/services/camera/libcameraservice/device3/Camera3BufferManager.h
@@ -29,6 +29,7 @@
 namespace camera3 {
 
 struct StreamInfo;
+class Camera3OutputStream;
 
 /**
  * A class managing the graphic buffers that is used by camera output streams. It allocates and
@@ -81,7 +82,7 @@
      *                     and other streams that were already registered with the same stream set
      *                     ID.
      */
-    status_t registerStream(const StreamInfo &streamInfo);
+    status_t registerStream(wp<Camera3OutputStream>& stream, const StreamInfo &streamInfo);
 
     /**
      * This method unregisters a stream from this buffer manager.
@@ -114,6 +115,8 @@
      * Return values:
      *
      *  OK:        Getting buffer for this stream was successful.
+     *  ALREADY_EXISTS: Enough free buffers are already attached to this output buffer queue,
+     *             user should just dequeue from the buffer queue.
      *  BAD_VALUE: stream ID or streamSetId are invalid, or stream ID and stream set ID
      *             combination doesn't match what was registered, or this stream wasn't registered
      *             to this buffer manager before.
@@ -122,6 +125,28 @@
     status_t getBufferForStream(int streamId, int streamSetId, sp<GraphicBuffer>* gb, int* fenceFd);
 
     /**
+     * This method notifies the manager that a buffer has been released by the consumer.
+     *
+     * The buffer is not returned to the buffer manager, but is available for the stream the buffer
+     * is attached to for dequeuing.
+     *
+     * The notification lets the manager know how many buffers are directly available to the stream.
+     *
+     * If onBufferReleased is called for a given released buffer,
+     * returnBufferForStream may not be called for the same buffer, until the
+     * buffer has been reused. The manager will call detachBuffer on the stream
+     * if it needs the released buffer otherwise.
+     *
+     * Return values:
+     *
+     *  OK:        Buffer release was processed succesfully
+     *  BAD_VALUE: stream ID or streamSetId are invalid, or stream ID and stream set ID
+     *             combination doesn't match what was registered, or this stream wasn't registered
+     *             to this buffer manager before.
+     */
+    status_t onBufferReleased(int streamId, int streamSetId);
+
+    /**
      * This method returns a buffer for a stream to this buffer manager.
      *
      * When a buffer is returned, it is treated as a free buffer and may either be reused for future
@@ -245,6 +270,12 @@
          * The count of the buffers that were handed out to the streams of this set.
          */
         BufferCountMap handoutBufferCountMap;
+        /**
+         * The count of the buffers that are attached to the streams of this set.
+         * An attached buffer may be free or handed out
+         */
+        BufferCountMap attachedBufferCountMap;
+
         StreamSet() {
             allocatedBufferWaterMark = 0;
             maxAllowedBufferCount = 0;
@@ -256,6 +287,7 @@
      */
     typedef int StreamSetId;
     KeyedVector<StreamSetId, StreamSet> mStreamSetMap;
+    KeyedVector<StreamId, wp<Camera3OutputStream>> mStreamMap;
 
     // TODO: There is no easy way to query the Gralloc version in this code yet, we have different
     // code paths for different Gralloc versions, hardcode something here for now.
diff --git a/services/camera/libcameraservice/device3/Camera3Device.cpp b/services/camera/libcameraservice/device3/Camera3Device.cpp
index 140b424..bbe7317 100644
--- a/services/camera/libcameraservice/device3/Camera3Device.cpp
+++ b/services/camera/libcameraservice/device3/Camera3Device.cpp
@@ -2733,6 +2733,7 @@
         mParent(parent),
         mStatusTracker(statusTracker),
         mHal3Device(hal3Device),
+        mListener(nullptr),
         mId(getId(parent)),
         mReconfigured(false),
         mDoPause(false),
@@ -3790,7 +3791,8 @@
  */
 
 Camera3Device::PreparerThread::PreparerThread() :
-        Thread(/*canCallJava*/false), mActive(false), mCancelNow(false) {
+        Thread(/*canCallJava*/false), mListener(nullptr),
+        mActive(false), mCancelNow(false) {
 }
 
 Camera3Device::PreparerThread::~PreparerThread() {
diff --git a/services/camera/libcameraservice/device3/Camera3DummyStream.cpp b/services/camera/libcameraservice/device3/Camera3DummyStream.cpp
index c74038b..5123785 100644
--- a/services/camera/libcameraservice/device3/Camera3DummyStream.cpp
+++ b/services/camera/libcameraservice/device3/Camera3DummyStream.cpp
@@ -76,6 +76,13 @@
     return OK;
 }
 
+status_t Camera3DummyStream::detachBuffer(sp<GraphicBuffer>* buffer, int* fenceFd) {
+    (void) buffer;
+    (void) fenceFd;
+    // Do nothing
+    return OK;
+}
+
 status_t Camera3DummyStream::configureQueueLocked() {
     // Do nothing
     return OK;
diff --git a/services/camera/libcameraservice/device3/Camera3DummyStream.h b/services/camera/libcameraservice/device3/Camera3DummyStream.h
index 6c8859c..639619e 100644
--- a/services/camera/libcameraservice/device3/Camera3DummyStream.h
+++ b/services/camera/libcameraservice/device3/Camera3DummyStream.h
@@ -54,6 +54,8 @@
 
     status_t         setTransform(int transform);
 
+    virtual status_t detachBuffer(sp<GraphicBuffer>* buffer, int* fenceFd);
+
     /**
      * Return if this output stream is for video encoding.
      */
diff --git a/services/camera/libcameraservice/device3/Camera3OutputStream.cpp b/services/camera/libcameraservice/device3/Camera3OutputStream.cpp
index dcadf36..bc8f631 100644
--- a/services/camera/libcameraservice/device3/Camera3OutputStream.cpp
+++ b/services/camera/libcameraservice/device3/Camera3OutputStream.cpp
@@ -156,24 +156,35 @@
 
     ANativeWindowBuffer* anb;
     int fenceFd = -1;
+    bool gotBufferFromManager = false;
+
     if (mUseBufferManager) {
         sp<GraphicBuffer> gb;
         res = mBufferManager->getBufferForStream(getId(), getStreamSetId(), &gb, &fenceFd);
-        if (res != OK) {
+        if (res == OK) {
+            // Attach this buffer to the bufferQueue: the buffer will be in dequeue state after a
+            // successful return.
+            anb = gb.get();
+            res = mConsumer->attachBuffer(anb);
+            if (res != OK) {
+                ALOGE("%s: Stream %d: Can't attach the output buffer to this surface: %s (%d)",
+                        __FUNCTION__, mId, strerror(-res), res);
+                return res;
+            }
+            gotBufferFromManager = true;
+            ALOGV("Stream %d: Attached new buffer", getId());
+        } else if (res == ALREADY_EXISTS) {
+            // Have sufficient free buffers already attached, can just
+            // dequeue from buffer queue
+            ALOGV("Stream %d: Reusing attached buffer", getId());
+            gotBufferFromManager = false;
+        } else if (res != OK) {
             ALOGE("%s: Stream %d: Can't get next output buffer from buffer manager: %s (%d)",
                     __FUNCTION__, mId, strerror(-res), res);
             return res;
         }
-        // Attach this buffer to the bufferQueue: the buffer will be in dequeue state after a
-        // successful return.
-        anb = gb.get();
-        res = mConsumer->attachBuffer(anb);
-        if (res != OK) {
-            ALOGE("%s: Stream %d: Can't attach the output buffer to this surface: %s (%d)",
-                    __FUNCTION__, mId, strerror(-res), res);
-            return res;
-        }
-    } else {
+    }
+    if (!gotBufferFromManager) {
         /**
          * Release the lock briefly to avoid deadlock for below scenario:
          * Thread 1: StreamingProcessor::startStream -> Camera3Stream::isConfiguring().
@@ -469,10 +480,15 @@
      * HAL3.2 devices may not support the dynamic buffer registeration.
      */
     if (mBufferManager != 0 && mSetId > CAMERA3_STREAM_SET_ID_INVALID) {
+        uint32_t consumerUsage = 0;
+        getEndpointUsage(&consumerUsage);
         StreamInfo streamInfo(
                 getId(), getStreamSetId(), getWidth(), getHeight(), getFormat(), getDataSpace(),
-                camera3_stream::usage, mTotalBufferCount, /*isConfigured*/true);
-        res = mBufferManager->registerStream(streamInfo);
+                camera3_stream::usage | consumerUsage, mTotalBufferCount,
+                /*isConfigured*/true);
+        wp<Camera3OutputStream> weakThis(this);
+        res = mBufferManager->registerStream(weakThis,
+                streamInfo);
         if (res == OK) {
             // Disable buffer allocation for this BufferQueue, buffer manager will take over
             // the buffer allocation responsibility.
@@ -608,34 +624,49 @@
         return;
     }
 
+    ALOGV("Stream %d: Buffer released", stream->getId());
+    status_t res = stream->mBufferManager->onBufferReleased(
+        stream->getId(), stream->getStreamSetId());
+    if (res != OK) {
+        ALOGE("%s: signaling buffer release to buffer manager failed: %s (%d).", __FUNCTION__,
+                strerror(-res), res);
+        stream->mState = STATE_ERROR;
+    }
+}
+
+status_t Camera3OutputStream::detachBuffer(sp<GraphicBuffer>* buffer, int* fenceFd) {
+    Mutex::Autolock l(mLock);
+
+    ALOGV("Stream %d: detachBuffer", getId());
+    if (buffer == nullptr) {
+        return BAD_VALUE;
+    }
+
     sp<Fence> fence;
-    sp<GraphicBuffer> buffer;
-    int fenceFd = -1;
-    status_t res = stream->mConsumer->detachNextBuffer(&buffer, &fence);
+    status_t res = mConsumer->detachNextBuffer(buffer, &fence);
     if (res == NO_MEMORY) {
         // This may rarely happen, which indicates that the released buffer was freed by other
         // call (e.g., attachBuffer, dequeueBuffer etc.) before reaching here. We should notify the
         // buffer manager that this buffer has been freed. It's not fatal, but should be avoided,
         // therefore log a warning.
-        buffer = 0;
+        *buffer = 0;
         ALOGW("%s: the released buffer has already been freed by the buffer queue!", __FUNCTION__);
     } else if (res != OK) {
         // Other errors are fatal.
         ALOGE("%s: detach next buffer failed: %s (%d).", __FUNCTION__, strerror(-res), res);
-        stream->mState = STATE_ERROR;
-        return;
+        mState = STATE_ERROR;
+        return res;
     }
 
-    if (fence!= 0 && fence->isValid()) {
-        fenceFd = fence->dup();
+    if (fenceFd != nullptr) {
+        if (fence!= 0 && fence->isValid()) {
+            *fenceFd = fence->dup();
+        } else {
+            *fenceFd = -1;
+        }
     }
-    res = stream->mBufferManager->returnBufferForStream(stream->getId(), stream->getStreamSetId(),
-                buffer, fenceFd);
-    if (res != OK) {
-        ALOGE("%s: return buffer to buffer manager failed: %s (%d).", __FUNCTION__,
-                strerror(-res), res);
-       stream->mState = STATE_ERROR;
-    }
+
+    return OK;
 }
 
 bool Camera3OutputStream::isConsumerConfigurationDeferred() const {
diff --git a/services/camera/libcameraservice/device3/Camera3OutputStream.h b/services/camera/libcameraservice/device3/Camera3OutputStream.h
index 2feca27..5507cfc 100644
--- a/services/camera/libcameraservice/device3/Camera3OutputStream.h
+++ b/services/camera/libcameraservice/device3/Camera3OutputStream.h
@@ -151,6 +151,8 @@
           wp<Camera3OutputStream> mParent;
     };
 
+    virtual status_t detachBuffer(sp<GraphicBuffer>* buffer, int* fenceFd);
+
     /**
      * Set the graphic buffer manager to get/return the stream buffers.
      *
diff --git a/services/camera/libcameraservice/device3/Camera3OutputStreamInterface.h b/services/camera/libcameraservice/device3/Camera3OutputStreamInterface.h
index 7c09c40..3f83c89 100644
--- a/services/camera/libcameraservice/device3/Camera3OutputStreamInterface.h
+++ b/services/camera/libcameraservice/device3/Camera3OutputStreamInterface.h
@@ -49,6 +49,16 @@
      * Set the consumer surface to the output stream.
      */
     virtual status_t setConsumer(sp<Surface> consumer) = 0;
+
+    /**
+     * Detach an unused buffer from the stream.
+     *
+     * buffer must be non-null; fenceFd may null, and if it is non-null, but
+     * there is no valid fence associated with the detached buffer, it will be
+     * set to -1.
+     *
+     */
+    virtual status_t detachBuffer(sp<GraphicBuffer>* buffer, int* fenceFd) = 0;
 };
 
 } // namespace camera3