概述
//图像缓冲区
sp mGraphicBuffer;
//在slot数组中的索引
int mBuf;
…
}
BufferQueue中的 mSlots[32],mQueue都是指向GraphicBuffer的,只是应用的地方不一样
mQueue:是加工好的数据,Consumer可以消耗了
mSlots:所有的缓冲 Producer在里面找合适的空闲buffer,其实我感觉也可以用一个freeQueue.
生产者(app端)
//要缓冲区,
BufferQueue ::dequeueBuffer()从mSlots中获取一段空闲的buffer
{
//统计一下正在dequeue中 正acquired中的
for (int i = 0; i < maxBufferCount; i++) {
const int state = mSlots[i].mBufferState;
switch (state) {
case BufferSlot::DEQUEUED:
dequeuedCount++;
break;
case BufferSlot::ACQUIRED:
acquiredCount++;
break;
case BufferSlot::FREE:
//选择最早(mFrameNumber最小)queue的buffer,这种buffer其他硬件已经用完的可能性最大了
if ((found < 0) || mSlots[i].mFrameNumber < mSlots[found].mFrameNumber) {
found = i;
}
break;
}
if(found<0){ 可能找不到buffer需要等待空闲buffer
DequeueCondition.wait(mMutex)
}
}
}
//数据填充进去了,通知consumer消费把
BufferQueue :: queueBuffer 把加工好的buffer推到mQueue中
{
找到buf索引位置的buffer,以前dequeue出的索引
BufferItem item;
item.mAcquireCalled = mSlots[buf].mAcquireCalled;
item.mGraphicBuffer = mSlots[buf].mGraphicBuffer;
item.mFrameNumber = mFrameCounter; //每次加1,最小的肯定是最早推进去的
item.mBuf = buf;
if (mQueue.empty()) {
mQueue.push_back(item);
}
//通知dequeue中等待的,dequeue可能没有缓存了,在等待呢
mDequeueCondition.broadcast();
//通知Consumer数据准备好了
listener->onFrameAvailable();
}
消费者 (SurfaceFlinger服务)
//要数据
BufferQueue :: acquireBuffer(BufferItem *buffer, nsecs_t expectedPresent) 从mQueue中获取一段加工好的buffer
{
//获取队列头的,别设置一系列状态
Fifo::iterator front(mQueue.begin());
int buf = front->mBuf; //solt中的索引
*buffer = *front;
mQueue.erase(front);
mDequeueCondition.broadcast();
}
//数据用完了,归还回去
BufferQueue::releaseBuffer( int buf, const sp& fence,…) {
if (mSlots[buf].mBufferState == BufferSlot::ACQUIRED) {//验证一下状态,然后归还,就是修改写一下slot的状态
mSlots[buf].mFence = fence; //这个是为了与其他硬件同步的
mSlots[buf].mBufferState = BufferSlot::FREE;
}
mDequeueCondition.broadcast();
return NO_ERROR;
}
BufferQueue对谁的生死那么关心呢
IBinder::DeathRecipient
void BufferQueue::binderDied(const wp& who) {//binder死掉后回调这个的
int api = mConnectedApi;
this->disconnect(api);
}
disconnect(){
//把所有的buffer全清掉
freeAllBuffersLocked();
sp token = mConnectedProducerToken;
token->unlinkToDeath(static_castIBinder::DeathRecipient*(this));
最后
为了方便有学习需要的朋友,我把资料都整理成了视频教程(实际上比预期多花了不少精力),由于篇幅有限,都放在了我的GitHub上,点击即可免费获取!
Androidndroid架构视频+BAT面试专题PDF+学习笔记
当程序员容易,当一个优秀的程序员是需要不断学习的,从初级程序员到高级程序员,从初级架构师到资深架构师,或者走向管理,从技术经理到技术总监,每个阶段都需要掌握不同的能力。早早确定自己的职业方向,才能在工作和能力提升中甩开同龄人。
- 无论你现在水平怎么样一定要 持续学习 没有鸡汤,别人看起来的毫不费力,其实费了很大力,这四个字就是我的建议!!
- 我希望每一个努力生活的IT工程师,都会得到自己想要的,因为我们很辛苦,我们应得的。
当程序员容易,当一个优秀的程序员是需要不断学习的,从初级程序员到高级程序员,从初级架构师到资深架构师,或者走向管理,从技术经理到技术总监,每个阶段都需要掌握不同的能力。早早确定自己的职业方向,才能在工作和能力提升中甩开同龄人。
无论你现在水平怎么样一定要 持续学习 没有鸡汤,别人看起来的毫不费力,其实费了很大力,没有人能随随便便成功。
加油,共勉。
最后
以上就是搞怪大雁为你收集整理的Android BufferQueue生产消费原理(八),flutter消息推送方案的全部内容,希望文章能够帮你解决Android BufferQueue生产消费原理(八),flutter消息推送方案所遇到的程序开发问题。
如果觉得靠谱客网站的内容还不错,欢迎将靠谱客网站推荐给程序员好友。
发表评论 取消回复