android Gui系统之SurfaceFlinger(2)---BufferQueue

本文深入解析Android系统中BufferQueue模块的功能,包括BufferQueue如何管理与消费surface,不同应用如何通过BufferQueue分配和使用内存,以及Buffer的状态变迁流程。详细探讨了Buffer内存的来源、BufferQueue与应用之间的互斥操作机制,以及BufferQueue与SurfaceFlinger之间的交互关系,揭示了BufferQueue在UI刷新过程中的关键作用。
部署运行你感兴趣的模型镜像

6 BufferQueue

上一篇已经说到,BufferQueue是SurfaceFlinger管理和消费surface的中介,我们就开始分析bufferqueue。

每个应用 可以由几个BufferQueue?

应用绘制UI 所需的内存从何而来?

应用和SurfaceFlinger 如何互斥共享资源的访问?

6.1 Buffer的状态

复制代码

const char* BufferSlot::bufferStateName(BufferState state) {
    switch (state) {
        case BufferSlot::DEQUEUED: return "DEQUEUED";
        case BufferSlot::QUEUED: return "QUEUED";
        case BufferSlot::FREE: return "FREE";
        case BufferSlot::ACQUIRED: return "ACQUIRED";
        default: return "Unknown";
    }
}

复制代码

状态变迁如下:FREE->DEQUEUED->QUEUED->ACQUIRED->FREE

BufferQueue的状态迁移图:

我们先来看,producer & comsumer 分别是什么?

应用程序需要刷新UI,所以就会产生surface到BufferQueue,so,producer 可以认为就是应用程序,也可以是上一篇里面介绍的ISurfaceComposerClient。

comsumer不用看也知道,就是SurfaceFlinger。所以可以明确一个大致的流程就是,

1)应用需要刷新UI,获取一个buffer的缓冲区,这个操作就是dequeue。经过dequeue以后,该buffer被producer锁定,其他Owner就不能插手了。

2)然后把surface写入到该buffer里面,当producer认为写入结束后,就执行queue的操作,把buffer 归还给bufferqueue。Owner也变成为bufferqueue。

3)当一段buffer里面由数据以后,comsumer就会收到消息,然后去获取该buffer。

复制代码

void BufferQueue::ProxyConsumerListener::onFrameAvailable(
        const android::BufferItem& item) {
    sp<ConsumerListener> listener(mConsumerListener.promote());
    if (listener != NULL) {
        listener->onFrameAvailable(item);
    }
}

复制代码

bufferqueue里面就是comsumerlistener,当有可以使用的buffer后,就会通知comsumer使用。

// mGraphicBuffer points to the buffer allocated for this slot or is NULL
    // if no buffer has been allocated.
    sp<GraphicBuffer> mGraphicBuffer;

可以看到注释,bufferqueue的mSlot[64],并不是都有内容的,也就是mSlot存的是buferr的指针,如果没有,就存null

slot的个数在andorid5.0 里面定义在BufferQueueDefs.h里面,

 enum { NUM_BUFFER_SLOTS = 64 };

 

6.2 Buffer内存的出处

既然producer是主动操作,所以如果在dequeue的时候,已经获取了内存,后面的操作也就不需要分配内存了。

复制代码

status_t BufferQueueProducer::dequeueBuffer(int *outSlot,
        sp<android::Fence> *outFence, bool async,
        uint32_t width, uint32_t height, uint32_t format, uint32_t usage) {
    ATRACE_CALL();
    { // Autolock scope
        Mutex::Autolock lock(mCore->mMutex);
        mConsumerName = mCore->mConsumerName;
    } // Autolock scope

    BQ_LOGV("dequeueBuffer: async=%s w=%u h=%u format=%#x, usage=%#x",
            async ? "true" : "false", width, height, format, usage);

    if ((width && !height) || (!width && height)) {
        BQ_LOGE("dequeueBuffer: invalid size: w=%u h=%u", width, height);
        return BAD_VALUE;
    }

    status_t returnFlags = NO_ERROR;
    EGLDisplay eglDisplay = EGL_NO_DISPLAY;
    EGLSyncKHR eglFence = EGL_NO_SYNC_KHR;
    bool attachedByConsumer = false;

    { // Autolock scope
        Mutex::Autolock lock(mCore->mMutex);
        mCore->waitWhileAllocatingLocked();

        if (format == 0) {
            format = mCore->mDefaultBufferFormat;
        }

        // Enable the usage bits the consumer requested
        usage |= mCore->mConsumerUsageBits;

        int found;
        status_t status = waitForFreeSlotThenRelock("dequeueBuffer", async,
                &found, &returnFlags);
        if (status != NO_ERROR) {
            return status;
        }

        // This should not happen
        if (found == BufferQueueCore::INVALID_BUFFER_SLOT) {
            BQ_LOGE("dequeueBuffer: no available buffer slots");
            return -EBUSY;
        }

        *outSlot = found;
        ATRACE_BUFFER_INDEX(found);

        attachedByConsumer = mSlots[found].mAttachedByConsumer;

        const bool useDefaultSize = !width && !height;
        if (useDefaultSize) {
            width = mCore->mDefaultWidth;
            height = mCore->mDefaultHeight;
        }

        mSlots[found].mBufferState = BufferSlot::DEQUEUED;

        const sp<GraphicBuffer>& buffer(mSlots[found].mGraphicBuffer);
        if ((buffer == NULL) ||
                (static_cast<uint32_t>(buffer->width) != width) ||
                (static_cast<uint32_t>(buffer->height) != height) ||
                (static_cast<uint32_t>(buffer->format) != format) ||
                ((static_cast<uint32_t>(buffer->usage) & usage) != usage))
        {
            mSlots[found].mAcquireCalled = false;
            mSlots[found].mGraphicBuffer = NULL;
            mSlots[found].mRequestBufferCalled = false;
            mSlots[found].mEglDisplay = EGL_NO_DISPLAY;
            mSlots[found].mEglFence = EGL_NO_SYNC_KHR;
            mSlots[found].mFence = Fence::NO_FENCE;

            returnFlags |= BUFFER_NEEDS_REALLOCATION;
        }

        if (CC_UNLIKELY(mSlots[found].mFence == NULL)) {
            BQ_LOGE("dequeueBuffer: about to return a NULL fence - "
                    "slot=%d w=%d h=%d format=%u",
                    found, buffer->width, buffer->height, buffer->format);
        }

        eglDisplay = mSlots[found].mEglDisplay;
        eglFence = mSlots[found].mEglFence;
        *outFence = mSlots[found].mFence;
        mSlots[found].mEglFence = EGL_NO_SYNC_KHR;
        mSlots[found].mFence = Fence::NO_FENCE;
    } // Autolock scope

    if (returnFlags & BUFFER_NEEDS_REALLOCATION) {
        status_t error;
        BQ_LOGV("dequeueBuffer: allocating a new buffer for slot %d", *outSlot);
        sp<GraphicBuffer> graphicBuffer(mCore->mAllocator->createGraphicBuffer(
                    width, height, format, usage, &error));
        if (graphicBuffer == NULL) {
            BQ_LOGE("dequeueBuffer: createGraphicBuffer failed");
            return error;
        }

        { // Autolock scope
            Mutex::Autolock lock(mCore->mMutex);

            if (mCore->mIsAbandoned) {
                BQ_LOGE("dequeueBuffer: BufferQueue has been abandoned");
                return NO_INIT;
            }

            mSlots[*outSlot].mFrameNumber = UINT32_MAX;
            mSlots[*outSlot].mGraphicBuffer = graphicBuffer;
        } // Autolock scope
    }

    if (attachedByConsumer) {
        returnFlags |= BUFFER_NEEDS_REALLOCATION;
    }

    if (eglFence != EGL_NO_SYNC_KHR) {
        EGLint result = eglClientWaitSyncKHR(eglDisplay, eglFence, 0,
                1000000000);
        // If something goes wrong, log the error, but return the buffer without
        // synchronizing access to it. It's too late at this point to abort the
        // dequeue operation.
        if (result == EGL_FALSE) {
            BQ_LOGE("dequeueBuffer: error %#x waiting for fence",
                    eglGetError());
        } else if (result == EGL_TIMEOUT_EXPIRED_KHR) {
            BQ_LOGE("dequeueBuffer: timeout waiting for fence");
        }
        eglDestroySyncKHR(eglDisplay, eglFence);
    }

    BQ_LOGV("dequeueBuffer: returning slot=%d/%" PRIu64 " buf=%p flags=%#x",
            *outSlot,
            mSlots[*outSlot].mFrameNumber,
            mSlots[*outSlot].mGraphicBuffer->handle, returnFlags);

    return returnFlags;
}

复制代码

step1:BufferQueueProducer::waitForFreeSlotThenRelock 循环的主要作用就是查找可以使用的slot。

step2:释放不需要的buffer,并且统计已分配的内存。

复制代码

        // Free up any buffers that are in slots beyond the max buffer count
        for (int s = maxBufferCount; s < BufferQueueDefs::NUM_BUFFER_SLOTS; ++s) {
            assert(mSlots[s].mBufferState == BufferSlot::FREE);
            if (mSlots[s].mGraphicBuffer != NULL) {
                mCore->freeBufferLocked(s);
                *returnFlags |= RELEASE_ALL_BUFFERS;
            }
        }

复制代码

复制代码

for (int s = 0; s < maxBufferCount; ++s) {
            switch (mSlots[s].mBufferState) {
                case BufferSlot::DEQUEUED:
                    ++dequeuedCount;
                    break;
                case BufferSlot::ACQUIRED:
                    ++acquiredCount;
                    break;
                case BufferSlot::FREE:
                    // We return the oldest of the free buffers to avoid
                    // stalling the producer if possible, since the consumer
                    // may still have pending reads of in-flight buffers
                    if (*found == BufferQueueCore::INVALID_BUFFER_SLOT ||
                            mSlots[s].mFrameNumber < mSlots[*found].mFrameNumber) {
                        *found = s;
                    }
                    break;
                default:
                    break;
            }
        }

复制代码

如果有合适的,found 就是可以使用的buffer编号。

如果dequeue too many,but comsumer还来不及消耗掉,这个时候,有可能会导致OOM,所以,判断是否在队列里面有过多的buffer。

等待comsumer消耗后,释放互斥锁。

复制代码

        if (tryAgain) {
            // Return an error if we're in non-blocking mode (producer and
            // consumer are controlled by the application).
            // However, the consumer is allowed to briefly acquire an extra
            // buffer (which could cause us to have to wait here), which is
            // okay, since it is only used to implement an atomic acquire +
            // release (e.g., in GLConsumer::updateTexImage())
            if (mCore->mDequeueBufferCannotBlock &&
                    (acquiredCount <= mCore->mMaxAcquiredBufferCount)) {
                return WOULD_BLOCK;
            }
            mCore->mDequeueCondition.wait(mCore->mMutex);
        }

复制代码

 

在返回dqueueBuffer这个方法:如果没有找到free的slot,就直接返回错误。当然正常情况下是不会发生的。

        // This should not happen
        if (found == BufferQueueCore::INVALID_BUFFER_SLOT) {
            BQ_LOGE("dequeueBuffer: no available buffer slots");
            return -EBUSY;
        }
 mSlots[found].mBufferState = BufferSlot::DEQUEUED;

把找到的buffer的状态设为DEQUEUE。

在判断了mSlot[found]的属性以后,它可能是空的,也有可能不符合当前需要的buffer的size,就给mSlot[found]分配新的属性和内存

复制代码

if ((buffer == NULL) ||
                (static_cast<uint32_t>(buffer->width) != width) ||
                (static_cast<uint32_t>(buffer->height) != height) ||
                (static_cast<uint32_t>(buffer->format) != format) ||
                ((static_cast<uint32_t>(buffer->usage) & usage) != usage))
        {
            mSlots[found].mAcquireCalled = false;
            mSlots[found].mGraphicBuffer = NULL;
            mSlots[found].mRequestBufferCalled = false;
            mSlots[found].mEglDisplay = EGL_NO_DISPLAY;
            mSlots[found].mEglFence = EGL_NO_SYNC_KHR;
            mSlots[found].mFence = Fence::NO_FENCE;

            returnFlags |= BUFFER_NEEDS_REALLOCATION;
        }

        if (CC_UNLIKELY(mSlots[found].mFence == NULL)) {
            BQ_LOGE("dequeueBuffer: about to return a NULL fence - "
                    "slot=%d w=%d h=%d format=%u",
                    found, buffer->width, buffer->height, buffer->format);
        }

        eglDisplay = mSlots[found].mEglDisplay;
        eglFence = mSlots[found].mEglFence;
        *outFence = mSlots[found].mFence;
        mSlots[found].mEglFence = EGL_NO_SYNC_KHR;
        mSlots[found].mFence = Fence::NO_FENCE;
    } // Autolock scope

    if (returnFlags & BUFFER_NEEDS_REALLOCATION) {
        status_t error;
        BQ_LOGV("dequeueBuffer: allocating a new buffer for slot %d", *outSlot);
        sp<GraphicBuffer> graphicBuffer(mCore->mAllocator->createGraphicBuffer(
                    width, height, format, usage, &error));
        if (graphicBuffer == NULL) {
            BQ_LOGE("dequeueBuffer: createGraphicBuffer failed");
            return error;
        }

        { // Autolock scope
            Mutex::Autolock lock(mCore->mMutex);

            if (mCore->mIsAbandoned) {
                BQ_LOGE("dequeueBuffer: BufferQueue has been abandoned");
                return NO_INIT;
            }

            mSlots[*outSlot].mFrameNumber = UINT32_MAX;
            mSlots[*outSlot].mGraphicBuffer = graphicBuffer;
        } // Autolock scope
    }

复制代码

这样buffer对应的内存就是在producer,dequeue操作的时候分配内存的。(if need)

6.3应用程序和BufferQueue的关系

首先看一张surface各类之间的关系:

 这里多了一个Layer的东西,Layer代表一个画面的图层(在android app的角度以前是没有图层的概念的,虽然framework有)。

SurfaceFlinger混合,就是把所有的layer做混合。

我们先来看createlayer:

status_t SurfaceFlinger::createLayer(
        const String8& name,
        const sp<Client>& client,
        uint32_t w, uint32_t h, PixelFormat format, uint32_t flags,
        sp<IBinder>* handle, sp<IGraphicBufferProducer>* gbp)

这里关键是handler & gbp这2个参数。

我们看下去代码:layer 是从createNormalLayer里面来的

复制代码

status_t SurfaceFlinger::createNormalLayer(const sp<Client>& client,
        const String8& name, uint32_t w, uint32_t h, uint32_t flags, PixelFormat& format,
        sp<IBinder>* handle, sp<IGraphicBufferProducer>* gbp, sp<Layer>* outLayer)
{
    // initialize the surfaces
    switch (format) {
    case PIXEL_FORMAT_TRANSPARENT:
    case PIXEL_FORMAT_TRANSLUCENT:
        format = PIXEL_FORMAT_RGBA_8888;
        break;
    case PIXEL_FORMAT_OPAQUE:
        format = PIXEL_FORMAT_RGBX_8888;
        break;
    }

    *outLayer = new Layer(this, client, name, w, h, flags);
    status_t err = (*outLayer)->setBuffers(w, h, format, flags);
    if (err == NO_ERROR) {
        *handle = (*outLayer)->getHandle();
        *gbp = (*outLayer)->getProducer();
    }

    ALOGE_IF(err, "createNormalLayer() failed (%s)", strerror(-err));
    return err;
}

复制代码

producer跟踪源代码可以看到:

class MonitoredProducer : public IGraphicBufferProducer 

通过bind机制,可以认为就是BufferQueue的一个子类。

所以,每一个bufferqueue对应的都是一个layer。

看下handler:

复制代码

sp<IBinder> Layer::getHandle() {
    Mutex::Autolock _l(mLock);

    LOG_ALWAYS_FATAL_IF(mHasSurface,
            "Layer::getHandle() has already been called");

    mHasSurface = true;

    /*
     * The layer handle is just a BBinder object passed to the client
     * (remote process) -- we don't keep any reference on our side such that
     * the dtor is called when the remote side let go of its reference.
     *
     * LayerCleaner ensures that mFlinger->onLayerDestroyed() is called for
     * this layer when the handle is destroyed.
     */

    class Handle : public BBinder, public LayerCleaner {
        wp<const Layer> mOwner;
    public:
        Handle(const sp<SurfaceFlinger>& flinger, const sp<Layer>& layer)
            : LayerCleaner(flinger, layer), mOwner(layer) {
        }
    };

    return new Handle(mFlinger, this);
}

复制代码

没有什么东西,就是LayerCleaner,

它的设计目的就是SurfaceFlinger来清除图层。

所以我们可以得出结论

1)一个app对应一个surfaceFlinger,可以有多个layer,从而对应多个bufferqueue

2)surface的缓冲区内存是BufferQueue在进行dequeue的时候分配的,属于client端。

3)App & SurfaceFlinger都通过bufferQueue来分配和使用缓冲区,所以互斥操作是由BufferQueue来实现。

参考:

《深入理解android内核设计思想》 林学森

 

 

 

 

 

 

 

 

您可能感兴趣的与本文相关的镜像

ACE-Step

ACE-Step

音乐合成
ACE-Step

ACE-Step是由中国团队阶跃星辰(StepFun)与ACE Studio联手打造的开源音乐生成模型。 它拥有3.5B参数量,支持快速高质量生成、强可控性和易于拓展的特点。 最厉害的是,它可以生成多种语言的歌曲,包括但不限于中文、英文、日文等19种语言

<think>我们正在讨论的是当生产者(应用进程)调用queueBuffer后,通过frameAvailableListener->onFrameAvailable(item)触发回调,而消费者在SurfaceFlinger进程(系统服务进程)时的具体调用流程。 这个过程涉及Binder跨进程通信(IPC)。下面详细说明: 1. **生产者进程(应用进程)**: 在应用进程中,当生产者(例如一个Surface)调用queueBuffer时,会通过Binder调用到BufferQueueProducer(在应用进程侧是Bp端代理)的queueBuffer函数。这个调用会传递到BufferQueueProducer在服务端(即SurfaceFlinger进程)的实现。 2. **BufferQueueProducer服务端处理**: 在SurfaceFlinger进程中,BufferQueueProducer(Bn端)的queueBuffer函数被调用。在该函数中,当确定需要通知消费者时,它会调用: ```cpp if (frameAvailableListener != nullptr) { frameAvailableListener->onFrameAvailable(item); } ``` 这里的`frameAvailableListener`实际上是一个Binder代理对象(BpConsumerListener),它指向位于应用进程的消费者监听器吗?不对,这里需要澄清。 注意:在跨进程场景中,消费者(Consumer)在SurfaceFlinger进程中,而生产者(应用进程)调用queueBuffer会通过Binder调用到SurfaceFlinger进程中的BufferQueueProducer(服务端)。当服务端BufferQueueProducer需要通知消费者(也在同一个SurfaceFlinger进程)时,实际上不需要跨进程,因为消费者就在同一个进程。但是,这里有一个关键点:在BufferQueue中,消费者监听器(ConsumerListener)是由消费者注册的,而消费者可能位于不同的进程,也可能位于同一个进程。然而,在典型的应用与SurfaceFlinger交互的场景中,消费者(SurfaceFlinger)和BufferQueueProducer都在系统服务进程(SurfaceFlinger进程)中,所以这里实际上是同一个进程内的调用。 但是,我们之前说“应用进程→SurfaceFlinger系统服务进程”,是指生产者(应用进程)通过Binder调用将数据放入队列(queueBuffer)发生在SurfaceFlinger进程中。而通知消费者(在SurfaceFlinger进程中)则是在同一个进程内。 然而,还有一种情况:当应用进程使用SurfaceView或TextureView时,它可能自己同时是生产者也是消费者(例如,从摄像头获取数据并显示)。但这里我们讨论的是SurfaceFlinger作为消费者的情况。 所以,在应用进程(生产者)调用queueBuffer后,通过Binder IPC调用到SurfaceFlinger进程中的BufferQueueProducer的queueBuffer方法。在queueBuffer方法中,如果需要通知消费者(即SurfaceFlinger中的Layer),那么它会调用已经注册的ConsumerListener(即Layer)的onFrameAvailable方法,而这个调用是在SurfaceFlinger进程内同步发生的。 因此,具体调用流程如下: 步骤1:应用进程(生产者)通过Binder调用queueBuffer到SurfaceFlinger进程的BufferQueueProducer。 步骤2:在SurfaceFlinger进程中,BufferQueueProducer::queueBuffer执行,将缓冲区加入队列,并判断是否需要通知消费者(即检查是否有监听器且满足触发条件)。 步骤3:如果需要通知,则直接调用已经注册的ConsumerListener(即Layer)的onFrameAvailable方法(因为Layer在同一个进程)。 所以,在SurfaceFlinger进程中,调用的是: Layer::onFrameAvailable(const BufferItem& item) 那么,如果消费者在另一个进程(比如应用进程自己消费的情况),那么frameAvailableListener就会是一个BpConsumerListener(指向消费者进程的Binder代理),此时就会通过Binder跨进程调用到消费者进程的BnConsumerListener的onTransact,进而调用到消费者进程的ConsumerListener实现。 但是,问题中明确是“应用进程→SurfaceFlinger系统服务进程”,即消费者是SurfaceFlinger,所以此时是同一进程内调用。 所以,具体调用到的地方就是SurfaceFlinger进程中Layer的onFrameAvailable方法。 下面给出Layer::onFrameAvailable的简化代码(Android源码): ```cpp // frameworks/native/services/surfaceflinger/Layer.cpp void Layer::onFrameAvailable(const BufferItem& item) { // 标记该层有更新 mFlinger->signalLayerUpdate(); // 通知SurfaceFlinger主线程有图层更新 // 记录帧事件(用于性能跟踪) mFrameEventTracker.onFrameAvailable(item.mFrameNumber); } ``` 在`signalLayerUpdate`中,会触发SurfaceFlinger的合成循环(通过EventThread)进行新一轮的合成。 总结:在问题描述的场景中(应用进程生产,SurfaceFlinger消费),`frameAvailableListener->onFrameAvailable(item)`会直接调用到SurfaceFlinger进程中Layer类的onFrameAvailable方法。 注意:在Layer的onFrameAvailable方法中,它只是通知SurfaceFlinger图层更新,并不会立即进行合成。合成的触发是由VSync信号驱动的,而signalLayerUpdate会设置一个标志,并在下一个VSync信号到来时进行合成。 因此,详细调用链为: 应用进程(生产者)queueBuffer → 通过Binder IPC调用到SurfaceFlinger进程的BufferQueueProducer::queueBuffer → 在BufferQueueProducer::queueBuffer中调用frameAvailableListener->onFrameAvailable(item) → 调用Layer::onFrameAvailable → 调用mFlinger->signalLayerUpdate() → 触发SurfaceFlinger的合成循环 现在,根据规则,在回答后提出3-5个相关问题。</think>在应用进程 → SurfaceFlinger 系统服务进程的场景中,`frameAvailableListener->onFrameAvailable(item)` 的详细调用流程如下: ### 跨进程调用全流程(应用进程 → SurfaceFlinger) ```mermaid graph TD A[应用进程] -->|1. queueBuffer| B(BpBinder代理) B -->|2. Binder IPC| C[SurfaceFlinger进程] C --> D[BnGraphicBufferProducer] D -->|3. BufferQueueProducer::queueBuffer| E[BufferQueueCore] E --> F{需要通知消费者?} F -->|是| G[调用 frameAvailableListener] G --> H[IConsumerListener::onFrameAvailable] H --> I[Layer::onFrameAvailable] I --> J[SurfaceFlinger::signalLayerUpdate] J --> K[EventThread::requestNextVsync] K --> L[唤醒合成线程] ``` ### 详细步骤解析 1. **应用进程发起调用** ```cpp // 应用进程(生产者侧) status_t BpGraphicBufferProducer::queueBuffer(int slot, const QueueBufferInput& input, QueueBufferOutput* output) { // 通过Binder发送TRANSACTION_QUEUE_BUFFER命令 return remote()->transact(TRANSACTION_QUEUE_BUFFER, data, &reply); } ``` 2. **Binder跨进程传输** - 使用 `Parcel` 序列化传输数据: ```cpp // frameworks/native/libs/gui/IGraphicBufferProducer.cpp status_t BnGraphicBufferProducer::onTransact(uint32_t code, const Parcel& data, Parcel* reply, uint32_t flags) { case QUEUE_BUFFER: { // 反序列化数据 int slot = data.readInt32(); QueueBufferInput input; input.readFromParcel(&data); // 调用实际实现 status_t result = queueBuffer(slot, input, &output); } } ``` 3. **SurfaceFlinger处理队列** ```cpp // frameworks/native/services/surfaceflinger/BufferQueueProducer.cpp status_t BufferQueueProducer::queueBuffer(...) { // 将缓冲区加入队列 mCore->mQueue.push_back(item); // 判断是否需要通知消费者 bool needsWakeup = mCore->mQueue.empty(); if (needsWakeup && mCore->mConsumerListener != nullptr) { // 关键调用点 mCore->mConsumerListener->onFrameAvailable(item); } } ``` 4. **Layer接收回调** ```cpp // frameworks/native/services/surfaceflinger/Layer.cpp void Layer::onFrameAvailable(const BufferItem& item) { // 标记帧状态 mBufferInfo.mFrameNumber = item.mFrameNumber; mBufferInfo.mTimestamp = item.mTimestamp; // 通知SurfaceFlinger主服务 mFlinger->signalLayerUpdate(); } ``` 5. **触发合成流程** ```cpp // frameworks/native/services/surfaceflinger/SurfaceFlinger.cpp void SurfaceFlinger::signalLayerUpdate() { // 通过MessageQueue发送INVALIDATE消息 mEventQueue->invalidate(); // 触发VSync请求 mScheduler->scheduleFrame(); } ``` ### 关键数据结构传输 通过Binder传递的 `BufferItem` 包含: ```cpp struct BufferItem { sp<GraphicBuffer> mGraphicBuffer; // 图形缓冲区的智能指针 uint64_t mFrameNumber; // 帧序列号 int64_t mTimestamp; // 纳秒级时间戳 Rect mCrop; // 裁剪区域(x,y,width,height) uint32_t mTransform; // 变换矩阵标志位 uint32_t mScalingMode; // 缩放模式 // ... 其他元数据 }; ``` 这些数据在跨进程传输时会被序列化为Parcel对象,在SurfaceFlinger侧重建 ### 性能优化机制 1. **异步回调**:Binder调用使用 `TF_ONE_WAY` 标志,非阻塞 2. **批量处理**:连续帧合并为单次VSync事件处理 3. **线程优化**:SurfaceFlinger使用专用Binder线程(编号15)处理图形请求 4. **优先级提升**:图形Binder调用被标记为 `PRIORITY_DISPLAY` 优先级
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值