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