Android显示系统(13)- 向SurfaceFlinger提交Buffer-三、unlockAndPost:

时间:2024-12-18 07:32:41

3.1、总体思路:

  • Surface->lock被调用获取Buffer之后,生产者的dequeueBuffer调用。
  • 获得buffer之后,App侧通过Surface->unlockAndPost提交填充数据的Buffer,也就是调用queueBuffer。
  • 那么queueBuffer调用之后,主要做两件事入队列,并且通知消费者取数据,通知顺序是:
    • 通知Layer的消费者;
    • 通知SurfaceFlinger;

3.2、代码走读:

入口在这儿:

status_t Surface::unlockAndPost()
{
    if (mLockedBuffer == nullptr) {
        ALOGE("Surface::unlockAndPost failed, no locked buffer");
        return INVALID_OPERATION;
    }

    int fd = -1;
    // 解锁当前被锁的缓冲区(异步)
    status_t err = mLockedBuffer->unlockAsync(&fd);
    ALOGE_IF(err, "failed unlocking buffer (%p)", mLockedBuffer->handle);
    // 提交缓冲区
    err = queueBuffer(mLockedBuffer.get(), fd);
    ALOGE_IF(err, "queueBuffer (handle=%p) failed (%s)",
            mLockedBuffer->handle, strerror(-err));

    mPostedBuffer = mLockedBuffer;
    mLockedBuffer = nullptr;
    return err;
}

3.3、Layer的消费者:

1)为Layer创建消费者:

看代码之前,我们先看下这个Layer第一次被引用时候:

void BufferQueueLayer::onFirstRef() {
    BufferLayer::onFirstRef();

    // Creates a custom BufferQueue for SurfaceFlingerConsumer to use
    sp<IGraphicBufferProducer> producer;
    sp<IGraphicBufferConsumer> consumer;
    // 创建BufferQueue的时候,里面会创建生产者和消费者
    BufferQueue::createBufferQueue(&producer, &consumer, true);
    // 将消费者做一次封装
    mProducer = new MonitoredProducer(producer, mFlinger, this);
    {
        // Grab the SF state lock during this since it's the only safe way to access RenderEngine
        // 同样,将生产者做一次封装
        Mutex::Autolock lock(mFlinger->mStateLock);
        mConsumer =
                new BufferLayerConsumer(consumer, mFlinger->getRenderEngine(), mTextureName, this);
    }
  // 。。。
}

看在这里面创建了生产者和消费者。我们看下这个消费者BufferLayerConsumer

BufferLayerConsumer::BufferLayerConsumer(const sp<IGraphicBufferConsumer>& bq,
                                         renderengine::RenderEngine& engine, uint32_t tex,
                                         Layer* layer)
      : ConsumerBase(bq, false), // 调用了父类构造函数
		//。。。
        mCurrentTexture(BufferQueue::INVALID_BUFFER_SLOT) {
        // 。。。
}

发现构造函数中首先调用了父类构造函数:

ConsumerBase::ConsumerBase(const sp<IGraphicBufferConsumer>& bufferQueue, bool controlledByApp) :
        mAbandoned(false),
        mConsumer(bufferQueue),
        mPrevFinalReleaseFence(Fence::NO_FENCE) {
    // Choose a name using the PID and a process-unique ID.
    mName = String8::format("unnamed-%d-%d", getpid(), createProcessUniqueId());

    // Note that we can't create an sp<...>(this) in a ctor that will not keep a
    // reference once the ctor ends, as that would cause the refcount of 'this'
    // dropping to 0 at the end of the ctor.  Since all we need is a wp<...>
    // that's what we create.
    wp<ConsumerListener> listener = static_cast<ConsumerListener*>(this);
    sp<IConsumerListener> proxy = new BufferQueue::ProxyConsumerListener(listener);

    status_t err = mConsumer->consumerConnect(proxy, controlledByApp);
    if (err != NO_ERROR) {
        CB_LOGE("ConsumerBase: error connecting to BufferQueue: %s (%d)",
                strerror(-err), err);
    } else {
        mConsumer->setConsumerName(mName);
    }
}

构造函数主要完成以下工作:

  1. 接受一个指向 IGraphicBufferConsumer 类型的缓冲队列接口和一个控制标志(是否由应用程序控制)。
  2. 初始化成员变量,例如放弃状态、消费者句柄等。
  3. 创建并绑定 ConsumerListener,监听缓冲区的操作事件。
  4. 通过 BufferQueueconsumerConnect 方法,将当前消费端与缓冲队列连接。
  5. 设置消费端名称,以便开发时调试和跟踪。

进去看看consumerConnect:

// 代码路径:native\libs\gui\include\gui\BufferQueueConsumer.h
    virtual status_t consumerConnect(const sp<IConsumerListener>& consumer,
            bool controlledByApp) {
        return connect(consumer, controlledByApp);
    }

调用这个connect就将consumer保存到Layer当中了:

status_t BufferQueueConsumer::connect(
        const sp<IConsumerListener>& consumerListener, bool controlledByApp) {
    ATRACE_CALL();

    if (consumerListener == nullptr) {
        BQ_LOGE("connect: consumerListener may not be NULL");
        return BAD_VALUE;
    }

    BQ_LOGV("connect: controlledByApp=%s",
            controlledByApp ? "true" : "false");

    std::lock_guard<std::mutex> lock(mCore->mMutex);

    if (mCore->mIsAbandoned) {
        BQ_LOGE("connect: BufferQueue has been abandoned");
        return NO_INIT;
    }
    // 将Consumer赋值给mCore
    mCore->mConsumerListener = consumerListener;
    mCore->mConsumerControlledByApp = controlledByApp;

    return NO_ERROR;
}

其中sp<BufferQueueCore> mCore;

2)给Consumer设置监听者:

void BufferQueueLayer::onFirstRef() {
    // ...
    // 给Consumer设置一个Listener
    mConsumer->setContentsChangedListener(this);
    mConsumer->setName(mName);
	// ...
}

稍微进去看看:

void BufferLayerConsumer::setContentsChangedListener(const wp<ContentsChangedListener>& listener) {
    setFrameAvailableListener(listener);
    Mutex::Autolock lock(mMutex);
    mContentsChangedListener = listener;
}

这个会走到父类:

void ConsumerBase::setFrameAvailableListener(
        const wp<FrameAvailableListener>& listener) {
    CB_LOGV("setFrameAvailableListener");
    Mutex::Autolock lock(mFrameAvailableMutex);
    mFrameAvailableListener = listener;
}

发现Listener最终保存到父类的成员变量mFrameAvailableListener以及BufferLayerConsumermContentsChangedListener,以后Consumer有变化,就通过这个通知给监听者。

3.3、queueBuffer

入口函数:

int Surface::queueBuffer(android_native_buffer_t* buffer, int fenceFd) {
    // ...
    nsecs_t now = systemTime();
    // 调用生产者代理的queueBuffer,导致Binder调用
    status_t err = mGraphicBufferProducer->queueBuffer(i, input, &output);
    mLastQueueDuration = systemTime() - now;
    if (err != OK)  {
        ALOGE("queueBuffer: error queuing buffer to SurfaceTexture, %d", err);
    }
    // ... 
}

调用代理对象的函数:

然后就是调用了QueueBuffer的生产者代理提交buffer。中间一堆binder调用我们省略了,直接看子类BufferQueueProducer

status_t BufferQueueProducer::queueBuffer(int slot,
        const QueueBufferInput &input, QueueBufferOutput *output) { 
    
	    BufferItem item;
    	// 。。。
		// 取出要提交的那一项,用取出的项构造一个BufferItem对象;
        item.mAcquireCalled = mSlots[slot].mAcquireCalled;
        item.mGraphicBuffer = mSlots[slot].mGraphicBuffer;
        item.mCrop = crop;
        item.mTransform = transform &
                ~static_cast<uint32_t>(NATIVE_WINDOW_TRANSFORM_INVERSE_DISPLAY);
        item.mTransformToDisplayInverse =
                (transform & NATIVE_WINDOW_TRANSFORM_INVERSE_DISPLAY) != 0;
        item.mScalingMode = static_cast<uint32_t>(scalingMode);
        item.mTimestamp = requestedPresentTimestamp;
        item.mIsAutoTimestamp = isAutoTimestamp;
        item.mDataSpace = dataSpace;
        item.mHdrMetadata = hdrMetadata;
        item.mFrameNumber = currentFrameNumber;
        item.mSlot = slot;
        item.mFence = acquireFence;
        item.mFenceTime = acquireFenceTime;
        item.mIsDroppable = mCore->mAsyncMode ||
                (mConsumerIsSurfaceFlinger && mCore->mQueueBufferCanDrop) ||
                (mCore->mLegacyBufferDrop && mCore->mQueueBufferCanDrop) ||
                (mCore->mSharedBufferMode && mCore->mSharedBufferSlot == slot);
        item.mSurfaceDamage = surfaceDamage;
        item.mQueuedBuffer = true;
        item.mAutoRefresh = mCore->mSharedBufferMode && mCore->mAutoRefresh;
        item.mApi = mCore->mConnectedApi;
    
    	// 。。。
    
    	output->bufferReplaced = false;
        if (mCore->mQueue.empty()) {
            // When the queue is empty, we can ignore mDequeueBufferCannotBlock
            // and simply queue this buffer
            mCore->mQueue.push_back(item);
            frameAvailableListener = mCore->mConsumerListener;
        } else {
            // ...
            mCore->mQueue.push_back(item);
            frameAvailableListener = mCore->mConsumerListener;
        }
}

其实不管队列空不空,最终都会push_back进去;

同时,记录了一下listener,这个listener前面已经分析过了,是一个proxy,也就是BufferQueue::ProxyConsumerListener对象。

通知观察者:

status_t BufferQueueProducer::queueBuffer(int slot,
        const QueueBufferInput &input, QueueBufferOutput *output) { 
    // ...
    { // scope for the lock
        std::unique_lock<std::mutex> lock(mCallbackMutex);
        while (callbackTicket != mCurrentCallbackTicket) {
            mCallbackCondition.wait(lock);
        }
        // 通知监听者,有数据了
        if (frameAvailableListener != nullptr) {
            frameAvailableListener->onFrameAvailable(item);
        } else if (frameReplacedListener != nullptr) {
            frameReplacedListener->onFrameReplaced(item);
        }
		// ...
    }
    // ...
}

就是通知监听者有数据了,这个监听者是谁呢?上面我们说了,是Queue的消费者,以及SurfaceFlinger。所以,我们到了消费者的代理类:

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

这个listener是ConsumerBase,于是我们看看消费者的onFrameAvailable函数:

void ConsumerBase::onFrameAvailable(const BufferItem& item) {
    CB_LOGV("onFrameAvailable");

    sp<FrameAvailableListener> listener;
    { // scope for the lock
        Mutex::Autolock lock(mFrameAvailableMutex);
        // 通过调用 promote() 方法,将弱引用 mFrameAvailableListener 提升为强引用 listener
        listener = mFrameAvailableListener.promote();
    }

    if (listener != nullptr) {
        CB_LOGV("actually calling onFrameAvailable");
        listener->onFrameAvailable(item);
    }
}

当然,mFrameAvailableListener 这个就是Layer:

void BufferQueueLayer::onFrameAvailable(const BufferItem& item) {
    // ...
    // If this layer is orphaned, then we run a fake vsync pulse so that
    // dequeueBuffer doesn't block indefinitely.
    if (isRemovedFromCurrentState()) {
        fakeVsync();
    } else {
        // 通知Layer已经更新
        mFlinger->signalLayerUpdate();
    }
    mConsumer->onBufferAvailable(item);
}

通过SurfaceFlinger来通知Layer已经更新:

// 通知Layer已经更新
void SurfaceFlinger::signalLayerUpdate() {
    mScheduler->resetIdleTimer();
    mEventQueue->invalidate();
}

这个invalidate() 会导致另外一个很重要的线程被唤醒,后面文章再分析。