问题现象

EID 或 HUD 中 SurfaceView 区域不显示。

20240329-144046.mp4

问题分析

已有分析文档:

1280X1280.PNG

1280X1280 (1).PNG

从上面的截图说明 UnityMain 线程卡在了 Surface::dequeueBuffer() 函数,而 Binder 线程中 dequeueBuffer() 函数卡在了 BufferQueueConsumer::disconnect() 函数中等待锁。

sequenceDiagram

participant S as Surface
participant P as BufferQueueProducer
participant C as BufferQueueConsumer

S ->> P: dequeueBuffer
Note right of P: Lock mutex
P ->> C: onFrameDequeued
Note right of C: Lock mutex
C ->> C: disconnect()
Note right of C: Unlock
C -->> P: 
Note right of P: Unlock

BufferQueueProducer::dequeueBuffer() 中在 mCore->mMutex 锁代码块中调用了 onFrameDequeued()

status_t BufferQueueProducer::dequeueBuffer(int* outSlot, sp<android::Fence>* outFence,
                                            uint32_t width, uint32_t height, PixelFormat format,
                                            uint64_t usage, uint64_t* outBufferAge,
                                            FrameEventHistoryDelta* outTimestamps) {
    ...
    { // Autolock scope
        std::lock_guard<std::mutex> lock(mCore->mMutex);
        ...
        if (!(returnFlags & BUFFER_NEEDS_REALLOCATION)) {
            if (mCore->mConsumerListener != nullptr) {
                mCore->mConsumerListener->onFrameDequeued(mSlots[*outSlot].mGraphicBuffer->getId());
            }
        }
    } // Autolock scope
    ...
        { // Autolock scope
            std::lock_guard<std::mutex> lock(mCore->mMutex);

            if (error == NO_ERROR && !mCore->mIsAbandoned) {
                graphicBuffer->setGenerationNumber(mCore->mGenerationNumber);
                mSlots[*outSlot].mGraphicBuffer = graphicBuffer;
                if (mCore->mConsumerListener != nullptr) {
                    mCore->mConsumerListener->onFrameDequeued(
                            mSlots[*outSlot].mGraphicBuffer->getId());
                }
            }
            ...
        } // Autolock scope
    ...
}

从调用栈看,onFrameDequeued() 最终调用了 BufferQueueConsumer::disconnect(),而在该函数中又申请了锁 mCore->mMutex

status_t BufferQueueConsumer::disconnect() {
    ATRACE_CALL();
    std::lock_guard<std::mutex> lock(mCore->mMutex);
    ...
    return NO_ERROR;
}

因为 std::mutex 是不可重入的锁,所以 disconnect() 函数卡死了。

HUD 不显示的问题原因是当 camera 释放时会调用 BufferQueueProducer::cancelBuffer(),该函数中锁代码块中调用 onFrameCancelled(),而 onFrameCancelled() 有可能会调用 disconnect(),所以与 EID 不显示问题原因相同。