Android P 显示流程分析--- buffer的生产消费者模式

上篇分析到了FramebufferSurface调用acquireBufferLocked()时,从mConsumer->acquireBuffer 消费者模式中获取的,这篇我们来分析下消费者模式。

  • StreamSpliter
  • ComsumerListener
  • BufferQueue
  • BufferQueueProducter
  • BufferQueueComsumer
  • BufferQueueCore
  • BufferLayer

每个BufferLayer在onFirstRef()也就是初始化时, 都会调用createBufferQueue,初始化一个BufferQueueProducer 和 一个BufferQueueConsumer,然后将这个BufferQueueProducer和surfaceFlinger 指针 封装到MonitoredProducer中。 将 BufferQueueConsumer 和 SurfaceFinger中的RenderEngine 一起封装到BufferLayerConsumer, 然后这个BufferLayerConsumer 设置监听setContentsChangedListener(this)。 同时在BufferLayer中实现了onFrameAvailable(*), 文件当contentChange时, 调用onFrameAvailable。
onFrameAvailable的被调用流程

那我们来看看谁调用了onFrameAvailable()。grep一番之后,发现BufferQueueProducer的queueBuffer里,有调用onFrameAvailable。继续跟进,发现Surface的queueBuffer中有调用mGraphicBufferProducer->queueBuffer(slot, queueInput, queueOutput), 继续往下追,发现Surface的unlockAndPost()会调用,它会被dispatchUnlockAndPost调用。 还发现另外一个地方就是ANativeWindow中 ANativeWindow_dequeueBuffer里有调用。这个就与Android里的window挂上构了。同时发现Surface里的attachAndQueueBuffer会queeuBuffer了。这个再向上追溯可以查到android.view.surface的通过jni调用attachAndQueueBuffer 以及 SurfaceControl 调用的screenShot。而Surface的attachAndQueueBuffer 更多的是被应用快照所调用。

因为现在BufferQueueProducer和BufferQueueConsumer里都有attachBuffer, detachBuffer 和 queueBuffer , dequeueBuffer 这四个函数, 那我们先来看看BufferQueueProducer是怎么获取attachBuffer里的Buffer的
BufferQueuProducer的attachBuffer调用流程
那现在看到的attachBuffer的都不是普通的调用, 一个是Camera的视频流方式,另一种是ScreenShot的截图方式。这种不是我们想要找的,那我们去看看BufferQueueProducer的requestBuffer的流程。

status_t BufferQueueProducer::requestBuffer(int slot, sp<GraphicBuffer>* buf) {
	......
    mSlots[slot].mRequestBufferCalled = true;
    *buf = mSlots[slot].mGraphicBuffer;
    return NO_ERROR;
}

就是把mSlots[slot]的mGraphicBuffer的地址赋值给参数buf。

int Surface::dequeueBuffer(android_native_buffer_t** buffer, int* fenceFd) {
	...
	  int buf = -1;
    sp<Fence> fence;
    nsecs_t startTime = systemTime();

    FrameEventHistoryDelta frameTimestamps;
    //graphicBufferProducer 调用 dequeueBuffer,获取buf 和 fence
    status_t result = mGraphicBufferProducer->dequeueBuffer(&buf, &fence, reqWidth, reqHeight,
                                                            reqFormat, reqUsage, &mBufferAge,
                                                            enableFrameTimestamps ? &frameTimestamps
                                                                                  : nullptr);
    sp<GraphicBuffer>& gbuf(mSlots[buf].buffer);
      if ((result & IGraphicBufferProducer::BUFFER_NEEDS_REALLOCATION) || gbuf == nullptr) {
        if (mReportRemovedBuffers && (gbuf != nullptr)) {
            mRemovedBuffers.push_back(gbuf);
        }//获取buf和gbuf
        result = mGraphicBufferProducer->requestBuffer(buf, &gbuf);
        if (result != NO_ERROR) {
            ALOGE("dequeueBuffer: IGraphicBufferProducer::requestBuffer failed: %d", result);
            mGraphicBufferProducer->cancelBuffer(buf, fence);
            return result;
        }
    }

    if (fence->isValid()) {
        *fenceFd = fence->dup();
        if (*fenceFd == -1) {
            ALOGE("dequeueBuffer: error duping fence: %d", errno);
            // dup() should never fail; something is badly wrong. Soldier on
            // and hope for the best; the worst that should happen is some
            // visible corruption that lasts until the next frame.
        }
    } else {
        *fenceFd = -1;
    }
	//gbuf 赋值给buffer
    *buffer = gbuf.get();
    

surface的dequeueBuffer中 会先调用mGraphicBufferProducer的dequeueBuffer , 然后再调用mGraphicBufferProducer里的requestBuffer,

Surface里的lock()函数会调用dequeueBuffer函数:
Surface里的dispatchlock() 又会调用lock(), perform() 通过NATIVE_WINDOW_LOCK 也会调用dispatchLock()。最后android_view_TextureView.cpp 中 android_view_textureView_lockCanvas() 通过native_window_lock() 又会调用到NATIVE_WINDOW_LOCK。很明显 android_view_textureView_lockCanvas() 就是TextureView 调用lockCanvas()调用到的。这样就明白了TextureView是如何画出来的了。

那我们来总结下GraphicBufferProducer的使用
GraphicBufferProducer的使用
那我们看看GraphicBufferConsumer是如何对应处理的
我们还是接之前的BufferLayer来分析,当应用快照时,会调用到BufferLayer的onFrameAvailable()

void BufferLayer::onFrameAvailable(const BufferItem& item) {
	...
		//BufferItem 加入到mQueueItem的队列中
        mQueueItems.push_back(item);
        android_atomic_inc(&mQueuedFrames);
        // Wake up any pending callbacks
        mLastFrameNumberReceived = item.mFrameNumber;
        mQueueItemCondition.broadcast();
		//surfaceFlinger 通知图层更新
        mFlinger->signalLayerUpdate();
}
void SurfaceFlinger::signalLayerUpdate() {
	//通知事件队列有可用的事件
    mEventQueue->invalidate();
}
void MessageQueue::invalidate() {
	//请示刷新
    mEvents->requestNextVsync();
}
void EventThread::Connection::requestNextVsync() {
    mEventThread->requestNextVsync(this);
}
void EventThread::requestNextVsync(const sp<EventThread::Connection>& connection) {
    std::lock_guard<std::mutex> lock(mMutex);

    if (mResyncWithRateLimitCallback) {
    	//异步刷新的回调,会调用到SurfaceFlinger-> resyncWithRateLimit()
        mResyncWithRateLimitCallback();
    }

    if (connection->count < 0) {
        connection->count = 0;
        mCondition.notify_all();
    }
}
void SurfaceFlinger::resyncWithRateLimit() {
    static constexpr nsecs_t kIgnoreDelay = ms2ns(500);

    // No explicit locking is needed here since EventThread holds a lock while calling this method
    static nsecs_t sLastResyncAttempted = 0;
    const nsecs_t now = systemTime();
    if (now - sLastResyncAttempted > kIgnoreDelay) {
    	//请求硬件fence刷新
        resyncToHardwareVsync(false);
    }
    sLastResyncAttempted = now;
}

到这一步,将bufferItem 的加入到bufferQueue中,然后再那异步请求界面刷新,硬件刷新,同时请求VsyncEvent。

status_t EventThread::Connection::postEvent(const DisplayEventReceiver::Event& event) {
    ssize_t size = DisplayEventReceiver::sendEvents(&mChannel, &event, 1);
    return size < 0 ? status_t(size) : status_t(NO_ERROR);
}
ssize_t DisplayEventReceiver::sendEvents(gui::BitTube* dataChannel,
        Event const* events, size_t count)
{
    return gui::BitTube::sendObjects(dataChannel, events, count);
}

BitTube 是一个消息传输机制,类似PIPE管道。其实也就是一对socket, 一边是sendObject,用于发送事件,另一端也就对应着recvObject。在MessageQueue里的setEventThread里 有设置EventTube的事件监听回调,MessageQueue::cb_eventReceiver.

void MessageQueue::setEventThread(android::EventThread* eventThread) {
....
    mEvents->stealReceiveChannel(&mEventTube);
    mLooper->addFd(mEventTube.getFd(), 0, Looper::EVENT_INPUT, MessageQueue::cb_eventReceiver,
                   this);
}
int MessageQueue::cb_eventReceiver(int fd, int events, void* data) {
    MessageQueue* queue = reinterpret_cast<MessageQueue*>(data);
    return queue->eventReceiver(fd, events);
}

int MessageQueue::eventReceiver(int /*fd*/, int /*events*/) {
    ssize_t n;
    DisplayEventReceiver::Event buffer[8];
    //getEvents 就是通过EventTube 来调用recvObject来获取
    while ((n = DisplayEventReceiver::getEvents(&mEventTube, buffer, 8)) > 0) {
        for (int i = 0; i < n; i++) {
        	//VSYNC事件的处理
            if (buffer[i].header.type == DisplayEventReceiver::DISPLAY_EVENT_VSYNC) {
                mHandler->dispatchInvalidate();
                break;
            }
        }
    }
    return 1;
}
ssize_t DisplayEventReceiver::getEvents(gui::BitTube* dataChannel,
        Event* events, size_t count)
{
    return gui::BitTube::recvObjects(dataChannel, events, count);
}

在这里就和前面的sendOjects 连接起来了。这里获取事件后,判断是DISPLAY_EVENT_VSYNC事件后,就做下一步处理:

void MessageQueue::Handler::dispatchInvalidate() {
    if ((android_atomic_or(eventMaskInvalidate, &mEventMask) & eventMaskInvalidate) == 0) {
        mQueue.mLooper->sendMessage(this, Message(MessageQueue::INVALIDATE));
    }
}

void MessageQueue::Handler::handleMessage(const Message& message) {
    switch (message.what) {
        case INVALIDATE:
            android_atomic_and(~eventMaskInvalidate, &mEventMask);
            mQueue.mFlinger->onMessageReceived(message.what);
            break;
        case REFRESH:
            android_atomic_and(~eventMaskRefresh, &mEventMask);
            mQueue.mFlinger->onMessageReceived(message.what);
            break;
    }
}
void SurfaceFlinger::onMessageReceived(int32_t what) {
    ATRACE_CALL();
    switch (what) {
        case MessageQueue::INVALIDATE: {
            bool frameMissed = !mHadClientComposition &&
                    mPreviousPresentFence != Fence::NO_FENCE &&
                    (mPreviousPresentFence->getSignalTime() ==
                            Fence::SIGNAL_TIME_PENDING);
            ATRACE_INT("FrameMissed", static_cast<int>(frameMissed));
            if (frameMissed) {
                mTimeStats.incrementMissedFrames();
                if (mPropagateBackpressure) {
                    signalLayerUpdate();
                    break;
                }
            }

            // Now that we're going to make it to the handleMessageTransaction()
            // call below it's safe to call updateVrFlinger(), which will
            // potentially trigger a display handoff.
            updateVrFlinger();

			//处理消息的传递
            bool refreshNeeded = handleMessageTransaction();
            //处理不可用的消息
            refreshNeeded |= handleMessageInvalidate();
            refreshNeeded |= mRepaintEverything;
            if (refreshNeeded) {
                // Signal a refresh if a transaction modified the window state,
                // a new buffer was latched, or if HWC has requested a full
                // repaint
                signalRefresh();
            }
            break;
        }
        case MessageQueue::REFRESH: {
             handleMessageRefresh();
            break;
        }
    }
}
bool SurfaceFlinger::handleMessageInvalidate() {
    ATRACE_CALL();
    //3buffer 轮换
    return handlePageFlip();
}
bool SurfaceFlinger::handlePageFlip()
{
    ALOGV("handlePageFlip");

    nsecs_t latchTime = systemTime();

    bool visibleRegions = false;
    bool frameQueued = false;
    bool newDataLatched = false;

    // Store the set of layers that need updates. This set must not change as
    // buffers are being latched, as this could result in a deadlock.
    // Example: Two producers share the same command stream and:
    // 1.) Layer 0 is latched
    // 2.) Layer 0 gets a new frame
    // 2.) Layer 1 gets a new frame
    // 3.) Layer 1 is latched.
    // Display is now waiting on Layer 1's frame, which is behind layer 0's
    // second frame. But layer 0's second frame could be waiting on display.
    //遍历Z轴的图层,然后加入到图层队列
    mDrawingState.traverseInZOrder([&](Layer* layer) {
        if (layer->hasQueuedFrame()) {
            frameQueued = true;
            if (layer->shouldPresentNow(mPrimaryDispSync)) {
                mLayersWithQueuedFrames.push_back(layer);
            } else {
                layer->useEmptyDamage();
            }
        } else {
            layer->useEmptyDamage();
        }
    });

    for (auto& layer : mLayersWithQueuedFrames) {
    	//绑定图层buffer的区域
        const Region dirty(layer->latchBuffer(visibleRegions, latchTime));
        layer->useSurfaceDamage();
        invalidateLayerStack(layer, dirty);
        if (layer->isBufferLatched()) {
            newDataLatched = true;
        }
    }

    mVisibleRegionsDirty |= visibleRegions;

    // If we will need to wake up at some time in the future to deal with a
    // queued frame that shouldn't be displayed during this vsync period, wake
    // up during the next vsync period to check again.
    if (frameQueued && (mLayersWithQueuedFrames.empty() || !newDataLatched)) {
        signalLayerUpdate();
    }

    // Only continue with the refresh if there is actually new work to do
    return !mLayersWithQueuedFrames.empty() && newDataLatched;
}

Region BufferLayer::latchBuffer(bool& recomputeVisibleRegions, nsecs_t latchTime) {
    ...
    // This boolean is used to make sure that SurfaceFlinger's shadow copy
    // of the buffer queue isn't modified when the buffer queue is returning
    // BufferItem's that weren't actually queued. This can happen in shared
    // buffer mode.
    bool queuedBuffer = false;
    LayerRejecter r(mDrawingState, getCurrentState(), recomputeVisibleRegions,
                    getProducerStickyTransform() != 0, mName.string(),
                    mOverrideScalingMode, mFreezeGeometryUpdates);
    //BufferLayerConsumer 更新buffer图层                    
    status_t updateResult =
            mConsumer->updateTexImage(&r, mFlinger->mPrimaryDispSync,
                                                    &mAutoRefresh, &queuedBuffer,
                                                    mLastFrameNumberReceived);
    if (updateResult == BufferQueue::PRESENT_LATER) {
        // Producer doesn't want buffer to be displayed yet.  Signal a
        // layer update so we check again at the next opportunity.
        mFlinger->signalLayerUpdate();
        return outDirtyRegion;
    } else if (updateResult == BufferLayerConsumer::BUFFER_REJECTED) {
        // If the buffer has been rejected, remove it from the shadow queue
        // and return early
        if (queuedBuffer) {
            Mutex::Autolock lock(mQueueItemLock);
            mTimeStats.removeTimeRecord(getName().c_str(), mQueueItems[0].mFrameNumber);
            mQueueItems.removeAt(0);
            android_atomic_dec(&mQueuedFrames);
        }
        return outDirtyRegion;
    } else if (updateResult != NO_ERROR || mUpdateTexImageFailed) {
        //错误处理
        return outDirtyRegion;
    }
	......
    // Decrement the queued-frames count.  Signal another event if we
    // have more frames pending.
    if ((queuedBuffer && android_atomic_dec(&mQueuedFrames) > 1) ||
        mAutoRefresh) {
        mFlinger->signalLayerUpdate();
    }

	//更新当前帧
    // update the active buffer
    getBE().compositionInfo.mBuffer =
            mConsumer->getCurrentBuffer(&getBE().compositionInfo.mBufferSlot);
    // replicated in LayerBE until FE/BE is ready to be synchronized
    mActiveBuffer = getBE().compositionInfo.mBuffer;
    if (getBE().compositionInfo.mBuffer == nullptr) {
        // this can only happen if the very first buffer was rejected.
        return outDirtyRegion;
    }

	//处理当前buffer的帧的数量
    mBufferLatched = true;
    mPreviousFrameNumber = mCurrentFrameNumber;
    mCurrentFrameNumber = mConsumer->getFrameNumber();
    {
        Mutex::Autolock lock(mFrameEventHistoryMutex);
        mFrameEventHistory.addLatch(mCurrentFrameNumber, latchTime);
    }

    mRefreshPending = true;
    mFrameLatencyNeeded = true;
    ......
    ui::Dataspace dataSpace = mConsumer->getCurrentDataSpace();
    // treat modern dataspaces as legacy dataspaces whenever possible, until
    // we can trust the buffer producers
    switch (dataSpace) {
       ....
       //处理数据格式
    }
    mCurrentDataSpace = dataSpace;
	.....
    return outDirtyRegion;
}

从MessageQueue里的dispatchInvalidate,然后调用到SurfaceFlinger里的onMessageReceived(), 之后调用到handlePageFlip(), 遍历了所有图层之后,调用layer的latchBuffer,去轮换android里的3buffer里其它的buffer。latchBuffer里会调用BufferLayerConsumer里updateTexImage,这里就和Consumer里关联起来。那继续看看updateTexImage里代码:

status_t BufferLayerConsumer::updateTexImage(BufferRejecter* rejecter, const DispSync& dispSync,
                                             bool* autoRefresh, bool* queuedBuffer,
                                             uint64_t maxFrameNumber) {
...
	//获取下一个buffer
	status_t err = acquireBufferLocked(&item, computeExpectedPresent(dispSync), maxFrameNumber); 
    int slot = item.mSlot;
    if (rejecter && rejecter->reject(mSlots[slot].mGraphicBuffer, item)) {
        releaseBufferLocked(slot, mSlots[slot].mGraphicBuffer);
        return BUFFER_REJECTED;
    }
	//释放之前的buffer
    // Release the previous buffer.
    err = updateAndReleaseLocked(item, &mPendingRelease);      
    if (!SyncFeatures::getInstance().useNativeFenceSync()) {
        // Bind the new buffer to the GL texture.
        //
        // Older devices require the "implicit" synchronization provided
        // by glEGLImageTargetTexture2DOES, which this method calls.  Newer
        // devices will either call this in Layer::onDraw, or (if it's not
        // a GL-composited layer) not at all.
        //绑定Buffer到渲染器上
        err = bindTextureImageLocked();
    }
status_t BufferLayerConsumer::acquireBufferLocked(BufferItem* item, nsecs_t presentWhen,uint64_t maxFrameNumber) {
    status_t err = ConsumerBase::acquireBufferLocked(item, presentWhen, maxFrameNumber);
    // If item->mGraphicBuffer is not null, this buffer has not been acquired
    // before, so any prior EglImage created is using a stale buffer. This
    // replaces any old EglImage with a new one (using the new buffer).
    if (item->mGraphicBuffer != nullptr) {
        mImages[item->mSlot] = new Image(item->mGraphicBuffer, mRE);
    }

    return NO_ERROR;
}
    	                                      

updateTexImage()会获取buffer, 调用acquireBufferLocked(), 这个同步会调用ConsumerBase::acqureBufferLocked里,同时将获取到的Buffer,替换成mImage[slot]。ConsumerBase里的acquireBufferLocked 会通过Binder调用到BufferQueueConsumer里的acquireBuffer。最后从BufferQueueCore的mQueue队列里获取到BufferItem。
最后总结一张UML图:
生产消费者UML图

到这里buffer的生产消费者模式的分析完了。

  • 1
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值