题外话

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

<span style="font-size: 15px"><span style="font-size: 16px">Android 12(S) 图形显示系统 - 开篇</span></span>-LMLPHP


 

一、前言


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

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

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

<span style="font-size: 15px"><span style="font-size: 16px">Android 12(S) 图形显示系统 - 开篇</span></span>-LMLPHP

二、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

<span style="font-size: 15px"><span style="font-size: 16px">Android 12(S) 图形显示系统 - 开篇</span></span>-LMLPHP
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清除;

<span style="font-size: 15px"><span style="font-size: 16px">Android 12(S) 图形显示系统 - 开篇</span></span>-LMLPHP

7. 谁调用了consumerConnect呢?

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

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

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

    (1)继承关系

<span style="font-size: 15px"><span style="font-size: 16px">Android 12(S) 图形显示系统 - 开篇</span></span>-LMLPHP

     (2)BLASTBufferQueue的构造函数中:

<span style="font-size: 15px"><span style="font-size: 16px">Android 12(S) 图形显示系统 - 开篇</span></span>-LMLPHP
9. 所以BufferQueueCore::mConsumerListener设置的就是ConsumerBase的实例

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

<span style="font-size: 15px"><span style="font-size: 16px">Android 12(S) 图形显示系统 - 开篇</span></span>-LMLPHP


本文作者@二的次方  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方法

<span style="font-size: 15px"><span style="font-size: 16px">Android 12(S) 图形显示系统 - 开篇</span></span>-LMLPHP

    (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

<span style="font-size: 15px"><span style="font-size: 16px">Android 12(S) 图形显示系统 - 开篇</span></span>-LMLPHP

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) 图形显示系统 - 开篇



<span style="font-size: 15px"><span style="font-size: 16px">Android 12(S) 图形显示系统 - 开篇</span></span>-LMLPHP

心有猛虎,细嗅蔷薇,生活就该无惧无悔

<span style="font-size: 15px"><span style="font-size: 16px">Android 12(S) 图形显示系统 - 开篇</span></span>-LMLPHP
作者:二的次方
本文版权归作者和博客园共有,转载必须给出原文链接,并保留此段声明,否则保留追究法律责任的权利
03-22 12:45