mIsAbandoned) { BQ_LOGE("connect: BufferQueue has been abandoned"); return NO_INIT; } if (mCore->mConsumerListener == nullptr) { BQ_LOGE("connect: BufferQueue has no consumer"); return NO_INIT; } if (output == nullptr) { BQ_LOGE("connect: output was NULL"); return BAD_VALUE; } if (mCore->mConnectedApi != BufferQueueCore::NO_CONNECTED_API) { BQ_LOGE("connect: already connected (cur=%d req=%d)", mCore->mConnectedApi, api); return BAD_VALUE; } "> mIsAbandoned) { BQ_LOGE("connect: BufferQueue has been abandoned"); return NO_INIT; } if (mCore->mConsumerListener == nullptr) { BQ_LOGE("connect: BufferQueue has no consumer"); return NO_INIT; } if (output == nullptr) { BQ_LOGE("connect: output was NULL"); return BAD_VALUE; } if (mCore->mConnectedApi != BufferQueueCore::NO_CONNECTED_API) { BQ_LOGE("connect: already connected (cur=%d req=%d)", mCore->mConnectedApi, api); return BAD_VALUE; } "> mIsAbandoned) { BQ_LOGE("connect: BufferQueue has been abandoned"); return NO_INIT; } if (mCore->mConsumerListener == nullptr) { BQ_LOGE("connect: BufferQueue has no consumer"); return NO_INIT; } if (output == nullptr) { BQ_LOGE("connect: output was NULL"); return BAD_VALUE; } if (mCore->mConnectedApi != BufferQueueCore::NO_CONNECTED_API) { BQ_LOGE("connect: already connected (cur=%d req=%d)", mCore->mConnectedApi, api); return BAD_VALUE; } ">
status_t BufferQueueProducer::connect(const sp<IProducerListener>& listener,
int api, bool producerControlledByApp, QueueBufferOutput *output) {
ATRACE_CALL();
std::lock_guard<std::mutex> lock(mCore->mMutex);
mConsumerName = mCore->mConsumerName;
BQ_LOGV("connect: api=%d producerControlledByApp=%s", api,
producerControlledByApp ? "true" : "false");
if (mCore->mIsAbandoned) {
BQ_LOGE("connect: BufferQueue has been abandoned");
return NO_INIT;
}
if (mCore->mConsumerListener == nullptr) {
BQ_LOGE("connect: BufferQueue has no consumer");
return NO_INIT;
}
if (output == nullptr) {
BQ_LOGE("connect: output was NULL");
return BAD_VALUE;
}
if (mCore->mConnectedApi != BufferQueueCore::NO_CONNECTED_API) {
BQ_LOGE("connect: already connected (cur=%d req=%d)",
mCore->mConnectedApi, api);
return BAD_VALUE;
}
检查一些状态和参数。
int delta = mCore->getMaxBufferCountLocked(mCore->mAsyncMode,
mDequeueTimeout < 0 ?
mCore->mConsumerControlledByApp && producerControlledByApp : false,
mCore->mMaxBufferCount) -
mCore->getMaxBufferCountLocked();
if (!mCore->adjustAvailableSlotsLocked(delta)) {
BQ_LOGE("connect: BufferQueue failed to adjust the number of available "
"slots. Delta = %d", delta);
return BAD_VALUE;
}
从 BufferQueueCore::getMaxBufferCountLocked() 两个重载函数的实现看,delta
的值取决于第二个参数 dequeueBufferCannotBlock
的计算:
mDequeueTimeout < 0 ? mCore->mConsumerControlledByApp && producerControlledByApp : false
其他参数都是一样的,所以 delta
的值是 -1 或 0 或 1。
计算 delta
之后调用 BufferQueueCore::adjustAvailableSlotsLocked() 调整 mUnusedSlots
、mFreeSlots
和 mFreeBuffers
。
int status = NO_ERROR;
switch (api) {
case NATIVE_WINDOW_API_EGL:
case NATIVE_WINDOW_API_CPU:
case NATIVE_WINDOW_API_MEDIA:
case NATIVE_WINDOW_API_CAMERA:
mCore->mConnectedApi = api;
output->width = mCore->mDefaultWidth;
output->height = mCore->mDefaultHeight;
output->transformHint = mCore->mTransformHintInUse = mCore->mTransformHint;
output->numPendingBuffers =
static_cast<uint32_t>(mCore->mQueue.size());
output->nextFrameNumber = mCore->mFrameCounter + 1;
output->bufferReplaced = false;
output->maxBufferCount = mCore->mMaxBufferCount;
if (listener != nullptr) {
// Set up a death notification so that we can disconnect
// automatically if the remote producer dies
#ifndef NO_BINDER
if (IInterface::asBinder(listener)->remoteBinder() != nullptr) {
status = IInterface::asBinder(listener)->linkToDeath(
static_cast<IBinder::DeathRecipient*>(this));
if (status != NO_ERROR) {
BQ_LOGE("connect: linkToDeath failed: %s (%d)",
strerror(-status), status);
}
mCore->mLinkedToDeath = listener;
}
#endif
mCore->mConnectedProducerListener = listener;
mCore->mBufferReleasedCbEnabled = listener->needsReleaseNotify();
}
break;
default:
BQ_LOGE("connect: unknown API %d", api);
status = BAD_VALUE;
break;
}
所有 api
流程处理一样。填充 QueueBufferOutput 成员,有 numPendingBuffers
、nextFrameNumber
、maxBufferCount
。
如果生产者不在同进程,监听死亡并设置 listener。从现在的代码看 mLinkedToDeath
有点重复了,其实只需要用一个 boolean
保存是否监听了死亡即可。
if (listener != NULL) {
if (IInterface::asBinder(listener)->remoteBinder() != NULL) {
status = IInterface::asBinder(listener)->linkToDeath(
static_cast<IBinder::DeathRecipient*>(this));
...
mCore->mLinkedToDeath = listener;
}
if (listener->needsReleaseNotify()) {
mCore->mConnectedProducerListener = listener;
}
}
上面是 mLinkedToDeath
引入时的代码。从这里可以知道,因为当时 mConnectedProducerListener
只有在需要通知的时候才设置,所以需要 mLinkedToDeath
。
mCore->mConnectedPid = BufferQueueThreadState::getCallingPid();
mCore->mBufferHasBeenQueued = false;
mCore->mDequeueBufferCannotBlock = false;
mCore->mQueueBufferCanDrop = false;
mCore->mLegacyBufferDrop = true;
if (mCore->mConsumerControlledByApp && producerControlledByApp) {
mCore->mDequeueBufferCannotBlock = mDequeueTimeout < 0;
mCore->mQueueBufferCanDrop = mDequeueTimeout <= 0;
}
mCore->mAllowAllocation = true;
return status;
}