题外话

疫情隔离在家,周末还在努力学习的我  .....


一、前言


上一篇文章中,有基本讲清楚Producer一端的处理逻辑,最后也留下了一个疑问:

Consumer是什么时候来消费数据的?他是自己主动来取的?还是收到了某种通知后再来处理的?

这篇文章,就带着这些疑问来开始分析源码。开头还是把这种流程图贴一下

二、Listener监听器的回调过程解析


生产者写完数据,把buffer还给buffer queue后,又是怎样通知消费者来使用的呢?

下面这些解析步骤,就是回答上面的问题

1. 生产者把数据写入buffer后,调用BufferQueueProducer::queueBuffer 入队列这个buffer;

2. 怎么去通知消费者来取呢? queueBuffer函数中会调用frameAvailableListener->onFrameAvailable(item);

3. frameAvailableListener是什么呢?frameAvailableListener = mCore->mConsumerListener;

4. mCore即为BufferQueueCore, BufferQueueCore中有成员 sp<IConsumerListener> mConsumerListener


5. BufferQueueCore::mConsumerListener 是什么时候设置的呢?

(1) BufferQueueConsumer::connect中设置

status_t BufferQueueConsumer::connect(
const sp<IConsumerListener>& consumerListener, bool controlledByApp) {
....
mCore->mConsumerListener = consumerListener;
mCore->mConsumerControlledByApp = controlledByApp;
}

(2) BufferQueueConsumer::disconnect中清除

status_t BufferQueueConsumer::disconnect() {
...
mCore->mConsumerListener = nullptr;
}

注:BufferQueueProducer和BufferQueueConsumer是BufferQueueCore的友元类,所以可以直接访问其私有成员

6. BufferQueueConsumer::connect、disconnect是在哪里调用的呢?

(1)BufferQueueConsumer::consumerConnect中调用connect设置监听器;

(2)BufferQueueConsumer::consumerDisconnect中调用disconnect清除;

7. 谁调用了consumerConnect呢?

(1)ConsumerBase 的构造函数中调用 mConsumer->consumerConnect(proxy, controlledByApp);

(2)这里的mConsumer是BLASTBufferQueue中创建BLASTBufferItemConsumer时一路设置下来的BufferQueueConsumer对象;

8. 设置是的Listener是从哪里传递过来的呢?

(1)继承关系

(2)BLASTBufferQueue的构造函数中:


9. 所以BufferQueueCore::mConsumerListener设置的就是ConsumerBase的实例

10. 因此,frameAvailableListener->onFrameAvailable(item)回调时,会走到ConsumerBase::onFrameAvailable中


本文作者@二的次方  2022-03-22发布于博客园


=========== 再接着下一个阶段 ==========

11. ConsumerBase::onFrameAvailable中继续调用


void ConsumerBase::onFrameAvailable(const BufferItem& item) {
CB_LOGV("onFrameAvailable"); sp<FrameAvailableListener> listener;
{ // scope for the lock
Mutex::Autolock lock(mFrameAvailableMutex);
listener = mFrameAvailableListener.promote();
} if (listener != nullptr) {
CB_LOGV("actually calling onFrameAvailable");
listener->onFrameAvailable(item);
}
}

12. ConsumerBase中的成员mFrameAvailableListener是什么东西呢?

(1)ConsumerBase类中成员定义 wp<FrameAvailableListener> mFrameAvailableListener;

(2)继承关系 BLASTBufferQueue继承自ConsumerBase::FrameAvailableListener,并实现onFrameAvailable方法

(3)在BLASTBufferQueue的构造函数中:mBufferItemConsumer->setFrameAvailableListener(this);

(4)最终会调用到ConsumerBase::setFrameAvailableListener

(5)所以ConsumerBase中的成员mFrameAvailableListener指向的是BLASTBufferQueue实例对象

13. 所以,ConsumerBase::onFrameAvailable再继续回调时,流程就回到了BLASTBufferQueue::onFrameAvailable

void BLASTBufferQueue::onFrameAvailable(const BufferItem& item) {
....
processNextBufferLocked(nextTransactionSet /* useNextTransaction */);
}

14. 继续走就进到BLASTBufferQueue::processNextBufferLocked

void BLASTBufferQueue::processNextBufferLocked(bool useNextTransaction) {
....
BufferItem bufferItem;
status_t status =
mBufferItemConsumer->acquireBuffer(&bufferItem, 0 /* expectedPresent */, false);
....
}

15. 消费者调用acquireBuffer去BufferQueue中请求一个可以处理的buffer

16. 处理就回到了BufferQueue的acquireBuffer逻辑


为了验证分析正确,在BufferQueueConsumer中加log,打印stack dump:

11-13 01:23:57.893  3016  3064 E BufferQueueConsumer: stackdump:#00 pc 00056f69  /system/lib/libgui.so (android::BufferQueueConsumer::acquireBuffer(android::BufferItem*, long long, unsigned long long)+72)
11-13 01:23:57.893 3016 3064 E BufferQueueConsumer: stackdump:#01 pc 00076967 /system/lib/libgui.so (android::ConsumerBase::acquireBufferLocked(android::BufferItem*, long long, unsigned long long)+62)
11-13 01:23:57.893 3016 3064 E BufferQueueConsumer: stackdump:#02 pc 000756cd /system/lib/libgui.so (android::BufferItemConsumer::acquireBuffer(android::BufferItem*, long long, bool)+44)
11-13 01:23:57.893 3016 3064 E BufferQueueConsumer: stackdump:#03 pc 0006c8b5 /system/lib/libgui.so (android::BLASTBufferQueue::processNextBufferLocked(bool)+164)
11-13 01:23:57.893 3016 3064 E BufferQueueConsumer: stackdump:#04 pc 0006d8d9 /system/lib/libgui.so (android::BLASTBufferQueue::onFrameAvailable(android::BufferItem const&)+132)
11-13 01:23:57.893 3016 3064 E BufferQueueConsumer: stackdump:#05 pc 000761ab /system/lib/libgui.so (android::ConsumerBase::onFrameAvailable(android::BufferItem const&)+110)
11-13 01:23:57.893 3016 3064 E BufferQueueConsumer: stackdump:#06 pc 000563e9 /system/lib/libgui.so (android::BufferQueue::ProxyConsumerListener::onFrameAvailable(android::BufferItem const&)+52)
11-13 01:23:57.893 3016 3064 E BufferQueueConsumer: stackdump:#07 pc 0005da6f /system/lib/libgui.so (android::BufferQueueProducer::queueBuffer(int, android::IGraphicBufferProducer::QueueBufferInput const&, android::IGraphicBufferProducer::QueueBufferOutput*)+1858)
11-13 01:23:57.893 3016 3064 E BufferQueueConsumer: stackdump:#08 pc 000a0d8b /system/lib/libgui.so (android::Surface::queueBuffer(ANativeWindowBuffer*, int)+442)

如logcat所示,符合我们分析的逻辑过程。

千辛万苦终于走到BufferQueueConsumer::acquireBuffer的地方!

此时流程已经到了开头图片的右半边描述的逻辑,我们下篇文章继续分析

三、小结


这篇文章主要解析了Produncer调用queueBuffer后,如何通过FrameAvailableListener把信息通知到Consumer,也解析了FrameAvailableListener是在哪里设置的。


必读:

Android 12(S) 图形显示系统 - 开篇



Android 12(S) 图形显示系统 - BufferQueue的工作流程(十)的更多相关文章

  1. Android 12(S) 图形显示系统 - BufferQueue的工作流程(八)

    题外话 最近总有一个感觉:在不断学习中,越发的感觉自己的无知,自己是不是要从"愚昧之巅"掉到"绝望之谷"了,哈哈哈 邓宁-克鲁格效应 一.前言 前面的文章中已经 ...

  2. Android 12(S) 图形显示系统 - BufferQueue的工作流程(九)

    题外话 Covid-19疫情的强烈反弹,小区里检测出了无症状感染者.小区封闭管理,我也不得不居家办公了.既然这么大把的时间可以光明正大的宅家里,自然要好好利用,八个字 == 努力工作,好好学习 一.前 ...

  3. Android 12(S) 图形显示系统 - BufferQueue的工作流程(十一)

    题外话 我竟然已经写了这个系列的十一篇文章了,虽然内容很浅显,虽然内容很枯燥,虽然内容也许没营养,但我为自己的坚持点赞! 一.前言 前面的两篇文章,分别讲解了Producer的处理逻辑和queue b ...

  4. Android 12(S) 图形显示系统 - BufferQueue/BLASTBufferQueue之初识(六)

    题外话 你有没有听见,心里有一声咆哮,那一声咆哮,它好像在说:我就是要从后面追上去! 写文章真的好痛苦,特别是自己对这方面的知识也一知半解就更加痛苦了.这已经是这个系列的第六篇了,很多次都想放弃了,但 ...

  5. Android 12(S) 图形显示系统 - 解读Gralloc架构及GraphicBuffer创建/传递/释放(十四)

    必读: Android 12(S) 图形显示系统 - 开篇 一.前言 在前面的文章中,已经出现过 GraphicBuffer 的身影,GraphicBuffer 是Android图形显示系统中的一个重 ...

  6. Android 12(S) 图形显示系统 - 简单聊聊 SurfaceView 与 BufferQueue的关联(十三)

    必读: Android 12(S) 图形显示系统 - 开篇 一.前言 前面的文章中,讲解的内容基本都是从我们提供的一个 native demo Android 12(S) 图形显示系统 - 示例应用( ...

  7. Android 12(S) 图形显示系统 - 初识ANativeWindow/Surface/SurfaceControl(七)

    题外话 "行百里者半九十",是说步行一百里路,走过九十里,只能算是走了一半.因为步行越接近目的地,走起来越困难.借指凡事到了接近成功,往往是最吃力.最艰难的时段.劝人做事贵在坚持, ...

  8. Android 12(S) 图形显示系统 - 示例应用(二)

    1 前言 为了更深刻的理解Android图形系统抽象的概念和BufferQueue的工作机制,这篇文章我们将从Native Level入手,基于Android图形系统API写作一个简单的图形处理小程序 ...

  9. Android 12(S) 图形显示系统 - 基本概念(一)

    1 前言 Android图形系统是系统框架中一个非常重要的子系统,与其它子系统一样,Android 框架提供了各种用于 2D 和 3D 图形渲染的 API供开发者使用来创建绚丽多彩的应用APP.图形渲 ...

随机推荐

  1. JavaWeb中jsp路径斜杆(/)跟没斜杆的路径映射问题

    在JavaWeb开发中,只要是写URL地址,那么建议最好以"/"开头,也就是使用绝对路径的方式,那么这个"/"到底代表什么呢?可以用如下的方式来记忆" ...

  2. 使用污点分析检查log4j问题

    摘要:log4j问题的余波还在继续,为什么这个问题潜伏了这么长时间,大家一直没有发现?这里从静态分析的角度谈下log4j问题的发现. 本文分享自华为云社区<使用污点分析检查log4j问题> ...

  3. Solution -「CF 555E」Case of Computer Network

    \(\mathcal{Description}\)   Link.   给定 \(n\) 个点 \(m\) 条边的无向图,判断是否有给每条边定向的方案,使得 \(q\) 组有序点对 \((s,t)\) ...

  4. 多图|一文详解Nacos参数!

    Nacos 中的参数有很多,如:命名空间.分组名.服务名.保护阈值.服务路由类型.临时实例等,那这些参数都是什么意思?又该如何设置?接下来我们一起来盘它. 1.命名空间 在 Nacos 中通过命名空间 ...

  5. Spring Bean配置加载为BeanDefinition全过程(注解配置)

    生产中有很多形式的的配置方式,本文仅分析注解配置.对于其他形式的配置区别主观以为主要在配置文件的解析过程不同,不一一分析了.本文以利用Dubbo框架开发rpc服务端为例详细阐述配置类的解析.数据保存. ...

  6. react 也就这么回事 01 —— React 元素的创建和渲染

    React 是一个用于构建用户界面的 JavaScript 库 它包括两个库:react.js 和 react-dom.js react.js:React 的核心库,提供了 React.js 的核心功 ...

  7. pytest(13)-多线程、多进程执行用例

    有些项目的测试用例较多,测试用例时需要分布式执行,缩短运行时间. pytest框架中提供可用于分布式执行测试用例的插件:pytest-parallel.pytest-xdist,接下来我们来学习这两个 ...

  8. Paxos 学习笔记2 - Multi-Paxos

    Paxos 学习笔记2 - Multi-Paxos 图片来自 John Ousterhout 的 Raft user study 系列课程 Multi-Paxos 论文里对很多问题并没有描述清楚,所以 ...

  9. CobaltStrike逆向学习系列(10):TeamServer 启动流程分析

    这是[信安成长计划]的第 10 篇文章 关注微信公众号[信安成长计划] 0x00 目录 0x01 基本校验与解析 0x02 初始化 0x03 启动 Listeners 在之前的分析中,都是针对 Cob ...

  10. StringBuilder与String互转

    StringBuilder类是一个可变的字符序列. StringBuilder()           构造一个不带任何字符的字符串生成器,其初始容量为 16 个字符.StringBuilder(Ch ...