am 85075869: Wait for buffers to drain

* commit '8507586903fa803abf535853a169913f2cf2e555':
  Wait for buffers to drain
This commit is contained in:
Andy McFadden 2013-10-18 16:57:01 -07:00 committed by Android Git Automerger
commit 251b11c204

View File

@ -644,6 +644,7 @@ status_t BufferQueue::connect(const sp<IBinder>& token,
producerControlledByApp ? "true" : "false"); producerControlledByApp ? "true" : "false");
Mutex::Autolock lock(mMutex); Mutex::Autolock lock(mMutex);
retry:
if (mAbandoned) { if (mAbandoned) {
ST_LOGE("connect: BufferQueue has been abandoned!"); ST_LOGE("connect: BufferQueue has been abandoned!");
return NO_INIT; return NO_INIT;
@ -654,29 +655,41 @@ status_t BufferQueue::connect(const sp<IBinder>& token,
return NO_INIT; return NO_INIT;
} }
if (mConnectedApi != NO_CONNECTED_API) {
ST_LOGE("connect: already connected (cur=%d, req=%d)",
mConnectedApi, api);
return -EINVAL;
}
// If we disconnect and reconnect quickly, we can be in a state where our slots are
// empty but we have many buffers in the queue. This can cause us to run out of
// memory if we outrun the consumer. Wait here if it looks like we have too many
// buffers queued up.
int maxBufferCount = getMaxBufferCountLocked(false); // worst-case, i.e. largest value
if (mQueue.size() > (size_t) maxBufferCount) {
// TODO: make this bound tighter?
ST_LOGV("queue size is %d, waiting", mQueue.size());
mDequeueCondition.wait(mMutex);
goto retry;
}
int err = NO_ERROR; int err = NO_ERROR;
switch (api) { switch (api) {
case NATIVE_WINDOW_API_EGL: case NATIVE_WINDOW_API_EGL:
case NATIVE_WINDOW_API_CPU: case NATIVE_WINDOW_API_CPU:
case NATIVE_WINDOW_API_MEDIA: case NATIVE_WINDOW_API_MEDIA:
case NATIVE_WINDOW_API_CAMERA: case NATIVE_WINDOW_API_CAMERA:
if (mConnectedApi != NO_CONNECTED_API) { mConnectedApi = api;
ST_LOGE("connect: already connected (cur=%d, req=%d)", output->inflate(mDefaultWidth, mDefaultHeight, mTransformHint, mQueue.size());
mConnectedApi, api);
err = -EINVAL;
} else {
mConnectedApi = api;
output->inflate(mDefaultWidth, mDefaultHeight, mTransformHint, mQueue.size());
// set-up a death notification so that we can disconnect // set-up a death notification so that we can disconnect
// automatically when/if the remote producer dies. // automatically when/if the remote producer dies.
if (token != NULL && token->remoteBinder() != NULL) { if (token != NULL && token->remoteBinder() != NULL) {
status_t err = token->linkToDeath(static_cast<IBinder::DeathRecipient*>(this)); status_t err = token->linkToDeath(static_cast<IBinder::DeathRecipient*>(this));
if (err == NO_ERROR) { if (err == NO_ERROR) {
mConnectedProducerToken = token; mConnectedProducerToken = token;
} else { } else {
ALOGE("linkToDeath failed: %s (%d)", strerror(-err), err); ALOGE("linkToDeath failed: %s (%d)", strerror(-err), err);
}
} }
} }
break; break;