• Android 12(S) 图像显示系统 - SurfaceFlinger 之 VSync - 中篇(十七)



    必读:

    Android 12(S) 图像显示系统 - 开篇


     

    1 前言

    这一篇文章,将继续讲解有关VSync的知识,前一篇文章 Android 12(S) 图像显示系统 - SurfaceFlinger之VSync-上篇(十六)中,主要是分析了SurfaceFlinger启动后VSync的一些初始化流程,以及vsync events的分发逻辑。

    vsync events汇集到了两个地方:

    1. MessageQueue::vsyncCallback  ==> VSYNC-sf

    2. EventThread::onVSyncEvent  ==> VSYNC-app  & VSYNC-appSf

    本篇中,将从一个简单的demo出发,来具体分析,vsync events是如何传递到  ==> 真正需要的地方

     

    2 可以监测vsync event的应用

    2.1 代码位置

    代码存放到了GitHub,自取哦

    https://github.com/yrzroger/DisplayEventTracker

     

    2.2 如何使用

    1. 下载代码放到android源码目录下

    2. 执行 mm 编译得到可执行档 DisplayEventTracker

    3. 将 DisplayEventTracker,adb push 到测试板的 /system/bin/ 目录下

    4. 在console下执行 DisplayEventTracker -h,可以查看简单的命令说明

    usage: DisplayEventTracker [options]
    ------------------------------------ options ---------------------------------------------
    [-i] vsync rate(default:1)
    [-h] help
    input 'r' to call requestNextVsync or input 'q' to exit when running
    ------------------------------------------------------------------------------------------

    5. 示例命令

    DisplayEventTracker          // 默认vsync rate = 1, 每个vsync到来时都会收到该event
    DisplayEventTracker -i 3     //表示vsync rate = 3, 每3个vsync才会通知一次
    DisplayEventTracker -i 0     //除非调用requestNextVsync,否则不会收到vsync event,此时可以输入‘r’来调用requestNextVsync

     

    2.3 执行结果展示

    我的测试板默认的屏幕刷新率是60Hz,一个VSync间隔是16.67ms

    结果一:默认setVsyncRate(1),每一个vsync event都会都到,可以看结果Vsync period大约是16.68ms

    root:/ $ DisplayEventTracker
    Vsync received: count=149
    Vsync received: count=150       16.687281 ms (59.925879 Hz)
    Vsync received: count=151       16.687281 ms (59.925879 Hz)
    Vsync received: count=152       16.687281 ms (59.925879 Hz)
    Vsync received: count=153       16.687281 ms (59.925879 Hz)
    Vsync received: count=154       16.687281 ms (59.925879 Hz)
    Vsync received: count=155       16.687281 ms (59.925879 Hz)

    结果二:setVsyncRate(6),每间隔6个vsync events才投递一次

    root:/ $ DisplayEventTracker -i 6
    Vsync received: count=540
    Vsync received: count=546       100.102455 ms (9.989765 Hz)
    Vsync received: count=552       100.102455 ms (9.989765 Hz)
    Vsync received: count=558       100.102455 ms (9.989765 Hz)
    Vsync received: count=564       100.102455 ms (9.989765 Hz)
    Vsync received: count=570       100.102455 ms (9.989765 Hz)
    Vsync received: count=576       100.102455 ms (9.989765 Hz)
    Vsync received: count=582       100.102455 ms (9.989765 Hz)

    结果三:setVsyncRate(0),每次调用requestNextVsync()后才收到一次vsync event

    root:/ $ DisplayEventTracker -i 6
    130|RealtekStark:/ $ DisplayEventTracker -i 0
    r
    Vsync received: count=797
    r
    Vsync received: count=801       583.896606 ms (1.712632 Hz)
    r
    Vsync received: count=803       583.900635 ms (1.712620 Hz)
    r
    Vsync received: count=805       633.949219 ms (1.577413 Hz)
    r
    Vsync received: count=807       2002.051880 ms (0.499488 Hz)
    r
    Vsync received: count=809       1951.946533 ms (0.512309 Hz)

     

    3 示例Demo源码解析

    3.1 DisplayEventTracker类的定义

    DisplayEventTracker定义很简单,继承自Thread,这意味着它可以开启一个独立的新线程,并在新线程中执行threadLoop()中的处理逻辑。

    class DisplayEventTracker : public Thread
    {
    public:
        explicit DisplayEventTracker(int vsyncRate); // 构造函数
        virtual ~DisplayEventTracker(); // 析构函数
    
        void requestNextVsync(); // 请求下一个 vsync event
    
    private:
        virtual bool        threadLoop();
        virtual status_t    readyToRun();
        void processDisplayEvents(); 
    
        // Display event handling
        class DisplayEventCallback; // LooperCallback的实现类
    
        std::unique_ptr<DisplayEventReceiver> mDisplayEventReceiver; // 接收 display events的核心成员
        sp<Looper> mLooper;
        int mVsyncRate; // 投递 vsync events的间隔、频率
    };

     

    3.2 DisplayEventTracker::readyToRun完成一些初始化设置,设置监听和回调

    status_t DisplayEventTracker::readyToRun() {
        // Register a display event receiver
        // To receive ModeChanged and/or FrameRateOverrides events specify this in the constructor.
        mDisplayEventReceiver = std::make_unique<DisplayEventReceiver>(); // 创建 DisplayEventReceiver 对象
        status_t status = mDisplayEventReceiver->initCheck(); // 检查 DisplayEventReceiver 初始化成功
        if(status != NO_ERROR)
            printf("Initialization of DisplayEventReceiver failed with status: %d", status);
    
        mLooper->addFd(mDisplayEventReceiver->getFd(), 0, Looper::EVENT_INPUT, // 添加待监测的fd,并设置回调 DisplayEventCallback()
                new DisplayEventCallback(), mDisplayEventReceiver.get()); //mDisplayEventReceiver.get()指针作为回调时传递给回调方法的数据 
        // setVsyncRate() sets the Event::VSync delivery rate. 
        // A value of 1 returns every Event::VSync.
        // A value of 2 returns every other event, etc...
        // a value of 0 returns no event unless  requestNextVsync() has been called.
        mDisplayEventReceiver->setVsyncRate(mVsyncRate); // 设置投递 vsync event的频率
        
        return NO_ERROR;
    }

     

    3.3 新线程开启,DisplayEventTracker::threadLoop中等待事件发生

    bool DisplayEventTracker::threadLoop() {
        processDisplayEvents();
        return true;
    }
    
    void DisplayEventTracker::processDisplayEvents() {
        // This will poll mDisplayEventReceiver and if there are new events it'll call
        // displayEventCallback synchronously.
        mLooper->pollOnce(-1);// 阻塞等待事件发生
    }

    threadLooper返回true,所以会反复执行。

     


    上面的逻辑就是典型的 Android Native Looper 机制,不熟悉的可以参见文章:

    Android Native -- Message/Handler/Looper机制(原理篇)

    Android Native -- Message/Handler/Looper机制(应用篇)


     

    3.4 vsync event到来时,回调 handleEvent

    class DisplayEventTracker::DisplayEventCallback : public LooperCallback {
        nsecs_t oldTimeStamp; // 记录前一个vsync的时间
    public:
        DisplayEventCallback(): oldTimeStamp(0) {}
    
        int handleEvent(int /* fd */, int /*events*/, void* data) {
            DisplayEventReceiver* displayEventReceiver = (DisplayEventReceiver*)data;
            constexpr int kBufferSize = 100;
            DisplayEventReceiver::Event buffer[kBufferSize];
            ssize_t numEvents;
            do {
                numEvents = displayEventReceiver->getEvents(buffer, kBufferSize); // 获取事件
                for (size_t i = 0; i < static_cast<size_t>(numEvents); i++) {
                    const auto& event = buffer[i];
                    if (event.header.type == DisplayEventReceiver::DISPLAY_EVENT_HOTPLUG) { // 热插拔事件
                        printf("Hotplug received: %s\n", event.hotplug.connected?"connected":"disconnected");
                    }
    
                    if(event.header.type == DisplayEventReceiver::DISPLAY_EVENT_VSYNC) { // vsync 事件
                        printf("Vsync received: count=%d\t", event.vsync.count); // 打印计数
                        if (oldTimeStamp) {
                            float t = float(event.header.timestamp - oldTimeStamp) / s2ns(1);
                            printf("%f ms (%f Hz)\n", t*1000, 1.0/t); //打印 vsync 事件间隔
                        } else {
                            printf("\n");
                        }
                        oldTimeStamp = event.header.timestamp; // 记录事件
                    }
    
                    if(event.header.type == DisplayEventReceiver::DISPLAY_EVENT_MODE_CHANGE) { // 模式变化事件
                        printf("Mode change received\n");
                    }
                    
                }
            } while (numEvents > 0);
    
            return 1;  // keep the callback
        }
    };

     


    小结:

    demo的整体流程是非常简单的,本质就是通过Looper去监测DisplayEventReceiver::getFd()中的fd,当fd上有事件发生时,就会回调到我们设置的函数。然后就可以从DisplayEventReceiver中getEvents获取事件,判断事件类型进行对应处理了

    DisplayEventReceiver由是个啥东东?它为什么可以收到vsync event呢?莫急,稍后分析


     

    4 DisplayEventReceiver相关原理分析

    DisplayEventReceiver创建并注册与SurfaceFlinger的事件连接。可用来监测VSync、HotPlug、ModeChange、FrameRateOverride事件。

    4.1 类定义

    4.2 主要方法解释

    DisplayEventReceiver构造函数

    可以根据需求来指定VsyncSource,并设置EventRegistrationFlags来决定是否接收ModeChanged和FrameRateOverrides事件。

    [/frameworks/native/libs/gui/include/gui/ISurfaceComposer.h]
    enum VsyncSource {
        eVsyncSourceApp = 0,
        eVsyncSourceSurfaceFlinger = 1
    };
    
    enum class EventRegistration {
        modeChanged = 1 << 0,
        frameRateOverride = 1 << 1,
    };

     

    status_t setVsyncRate(uint32_t count)

    设置投递vsync events的频率,设置1代表每个vsync event均被投递,设置2代表每隔一个投递一次,依次类推 ...

    设置0代表只有调用requestNextVsync()后才会投递一次vsync event

     

    status_t requestNextVsync()

    请求下一个vsync event,在vsync rate大于0的时候,这个函数调用无效

     

    int getFd() const

    获取用于接收事件的文件描述符

     

    ssize_t getEvents(Event* events, size_t count)

    当监测到有事件发生时,通过它获取具体的事件列表,函数返回值就是事件的数量

     

    ssize_t sendEvents(Event const* events, size_t count)

    发送事件,函数返回值就是事件的数量

    本文作者@二的次方  2022-04-27 发布于博客园

    4.3 DisplayEventReceiver工作原理,事件是怎么传递过来的?

    先看看它的构造函数的具体实现

    [/frameworks/native/libs/gui/DisplayEventReceiver.cpp]
    DisplayEventReceiver::DisplayEventReceiver(
            ISurfaceComposer::VsyncSource vsyncSource,
            ISurfaceComposer::EventRegistrationFlags eventRegistration) {
        sp<ISurfaceComposer> sf(ComposerService::getComposerService()); // 获取SurfaceFLinger服务
        if (sf != nullptr) {
            mEventConnection = sf->createDisplayEventConnection(vsyncSource, eventRegistration); // 创建远程事件连接
            if (mEventConnection != nullptr) {
                mDataChannel = std::make_unique<gui::BitTube>();
                mEventConnection->stealReceiveChannel(mDataChannel.get()); // 传递 BitTube
            }
        }
    }

    核心的处理应该是createDisplayEventConnectionstealReceiveChannel,下面分别看看这两个操作具体做了啥子

     

    4.3.1 SurfaceFlinger::createDisplayEventConnection

    这个方法通过Binder IPC跨进程,一路飞奔,直到SurfaceFlinger核心服务 SurfaceFlinger::createDisplayEventConnection

    [/frameworks/native/services/surfaceflinger/SurfaceFlinger.cpp]
    sp<IDisplayEventConnection> SurfaceFlinger::createDisplayEventConnection(
            ISurfaceComposer::VsyncSource vsyncSource,
            ISurfaceComposer::EventRegistrationFlags eventRegistration) {
        const auto& handle = // 判断选哪个 vsyncSource
                vsyncSource == eVsyncSourceSurfaceFlinger ? mSfConnectionHandle : mAppConnectionHandle;
        // 创建 DisplayEventConnection
        return mScheduler->createDisplayEventConnection(handle, eventRegistration);
    }

     

    mSfConnectionHandlemAppConnectionHandle是在initScheduler时创建的scheduler::ConnectionHandle对象,前一篇文章中有分析过。

    通过这两个handle可以在Scheduler::mConnections中找到和他们分别对应的Connection,即

        // Stores EventThread associated with a given VSyncSource, and an initial EventThreadConnection.
        struct Connection {
            sp<EventThreadConnection> connection;
            std::unique_ptr<EventThread> thread;
        };

     

    4.3.2 Scheduler::createDisplayEventConnection

    先看代码

    [/frameworks/native/services/surfaceflinger/Scheduler/Scheduler.cpp]
    sp<IDisplayEventConnection> Scheduler::createDisplayEventConnection(
            ConnectionHandle handle, ISurfaceComposer::EventRegistrationFlags eventRegistration) {
        std::lock_guard<std::mutex> lock(mConnectionsLock);
        RETURN_IF_INVALID_HANDLE(handle, nullptr);
        return createConnectionInternal(mConnections[handle].thread.get(), eventRegistration);
    }

    根据handle,从Scheduler::mConnections取出对应的EventThread对象,继续调用 Scheduler::createConnectionInternal

    [/frameworks/native/services/surfaceflinger/Scheduler/Scheduler.cpp]
    sp<EventThreadConnection> Scheduler::createConnectionInternal(
            EventThread* eventThread, ISurfaceComposer::EventRegistrationFlags eventRegistration) {
        return eventThread->createEventConnection([&] { resync(); }, eventRegistration);
    }

    继续去调用了 EventThread::createEventConnection

    [/frameworks/native/services/surfaceflinger/Scheduler/EventThread.cpp]
    sp<EventThreadConnection> EventThread::createEventConnection(
            ResyncCallback resyncCallback,
            ISurfaceComposer::EventRegistrationFlags eventRegistration) const {
        return new EventThreadConnection(const_cast<EventThread*>(this),
                                         IPCThreadState::self()->getCallingUid(),
                                         std::move(resyncCallback), eventRegistration);
    }

    创建了一个EventThreadConnection对象,并返回给调用者。如下图继承关系,保证了DisplayEventReceiver可以取得EventThreadConnection对象的远程代理,保存在成员sp<IDisplayEventConnection> mEventConnection

    流程继续,创建EventThreadConnection对象,第一次被引用时会进到onFirstRef中进行注册

    void EventThreadConnection::onFirstRef() {
        // NOTE: mEventThread doesn't hold a strong reference on us
        mEventThread->registerDisplayEventConnection(this);
    }

    再转到EventThread::registerDisplayEventConnection中,就是把这个connecttion保存到EventThread::mDisplayEventConnections

    status_t EventThread::registerDisplayEventConnection(const sp<EventThreadConnection>& connection) {
        std::lock_guard<std::mutex> lock(mMutex);
    
        // this should never happen
        auto it = std::find(mDisplayEventConnections.cbegin(),
                mDisplayEventConnections.cend(), connection);
        if (it != mDisplayEventConnections.cend()) {  // 判断是否已经存在
            ALOGW("DisplayEventConnection %p already exists", connection.get());
            mCondition.notify_all();
            return ALREADY_EXISTS;
        }
    
        mDisplayEventConnections.push_back(connection);// 保存到 mDisplayEventConnections 这个vector数组中
        mCondition.notify_all();
        return NO_ERROR;
    }

     

    DisplayEventReceiver已经和SurfaceFlinger服务端的Scheduler建立了关系,再回到DisplayEventReceiver的构造函数接着分析下面的操作

     

    [/frameworks/native/libs/gui/DisplayEventReceiver.cpp]
    // DisplayEventReceiver构造函数
    mDataChannel = std::make_unique<gui::BitTube>();
    mEventConnection->stealReceiveChannel(mDataChannel.get()); // 传递跨进程数据传递的对象 BitTube

     

    下一步创建了一个BitTube对象,然后调用了mEventConnection->stealReceiveChannel这个方法会走到

    [/frameworks/native/services/surfaceflinger/Scheduler/EventThread.cpp ]
    status_t EventThreadConnection::stealReceiveChannel(gui::BitTube* outChannel) {
        outChannel->setReceiveFd(mChannel.moveReceiveFd());// resets this BitTube's receive file descriptor to receiveFd
        outChannel->setSendFd(base::unique_fd(dup(mChannel.getSendFd()))); // resets this BitTube's send file descriptor to sendFd
        return NO_ERROR;
    }

     

    这使用到BitTube的跨进程传递数据的方式,基本原理可以参考:Android 12(S) 图像显示系统 - 基础知识之 BitTube

     


    到这里,我们可以清晰的看到,DisplayEventReceiver与SurfaceFlinger建立起来了一条跨进程传递事件的通道:BitTube中封装的socketpair (receive fd  & send fd)


     

    4.4 事件的传递、分发

    通信线路已建立,接下来就要把事件经过这条道路向外传递了。

    上一篇文章中曾讲到过

    收到vsync events的汇集到了两个地方:

    1. MessageQueue::vsyncCallback  ==> VSYNC-sf

    2. EventThread::onVSyncEvent  ==> VSYNC-app  & VSYNC-appSf

    我们这里只看EventThread::onVSyncEvent

    [/frameworks/native/services/surfaceflinger/Scheduler/EventThread.cpp]
    void EventThread::onVSyncEvent(nsecs_t timestamp, nsecs_t expectedVSyncTimestamp,
                                   nsecs_t deadlineTimestamp) {
        ...
        // 包装为 DisplayEventReceiver::Event对象,存入 mPendingEvents 尾部
        mPendingEvents.push_back(makeVSync(mVSyncState->displayId, timestamp, ++mVSyncState->count,
                                           expectedVSyncTimestamp, deadlineTimestamp, vsyncId));
        mCondition.notify_all();
    }

    EventThread收到 vsync event回调事件后,放入mPendingEvents这个待处理的事件队列中,然后唤醒等待的处理线程,即在EventThread::threadMain

    [/frameworks/native/services/surfaceflinger/Scheduler/EventThread.cpp]
    void EventThread::threadMain(std::unique_lock<std::mutex>& lock) {
        // using DisplayEventConsumers = std::vector<sp<EventThreadConnection>>;
        DisplayEventConsumers consumers; // consumers是一个EventThreadConnection数组
    
        while (mState != State::Quit) {
            std::optional<DisplayEventReceiver::Event> event;
    
            // Determine next event to dispatch.
            if (!mPendingEvents.empty()) {
                event = mPendingEvents.front(); // 取出 mPendingEvents 头部第一个待处理的 event
                mPendingEvents.pop_front();     // 删除开头元素
    
                switch (event->header.type) { // 判断是什么类型的事件
                    case DisplayEventReceiver::DISPLAY_EVENT_HOTPLUG: // 热插拔事件
                        if (event->hotplug.connected && !mVSyncState) {
                            mVSyncState.emplace(event->header.displayId);
                        } else if (!event->hotplug.connected && mVSyncState &&
                                   mVSyncState->displayId == event->header.displayId) {
                            mVSyncState.reset();
                        }
                        break;
    
                    case DisplayEventReceiver::DISPLAY_EVENT_VSYNC: // VSYNC 事件
                        if (mInterceptVSyncsCallback) { 
                            // mInterceptVSyncsCallback 是在SurfaceFlinger::initScheduler中createConnection时一路传递过来的
                            // 这个回调会通知到SurfaceFlinger
                            mInterceptVSyncsCallback(event->header.timestamp);
                        }
                        break;
                }
            }
    
            bool vsyncRequested = false;
    
            // Find connections that should consume this event.
            auto it = mDisplayEventConnections.begin(); // mDisplayEventConnections 中保存了所有与这个EventThread建立的连接
            while (it != mDisplayEventConnections.end()) { // 遍历所有Connection
                if (const auto connection = it->promote()) {
                    vsyncRequested |= connection->vsyncRequest != VSyncRequest::None;//是否请求vsync
    
                    if (event && shouldConsumeEvent(*event, connection)) { // 判断是否需要分发事件通知这个connection
                        consumers.push_back(connection);
                    }
    
                    ++it;
                } else {
                    it = mDisplayEventConnections.erase(it);
                }
            }
    
            if (!consumers.empty()) {
                dispatchEvent(*event, consumers);// 分发事件,最终是使用BitTube发送数据,通知connection
                consumers.clear();
            }
    
            State nextState;
            if (mVSyncState && vsyncRequested) {
                // synthetic = True if VSYNC should be faked, e.g. when display is off. 屏幕关闭产生虚假的VSYNC
                nextState = mVSyncState->synthetic ? State::SyntheticVSync : State::VSync;
            } else {
                ALOGW_IF(!mVSyncState, "Ignoring VSYNC request while display is disconnected");
                nextState = State::Idle; // 进入Idle阻塞等待
            }
    
            if (mState != nextState) {
                if (mState == State::VSync) {
                    mVSyncSource->setVSyncEnabled(false); // 关闭 vsync
                } else if (nextState == State::VSync) {
                    mVSyncSource->setVSyncEnabled(true);  // 开启 vysnc ,作用于CallbackRepeater,循环去schedule next vsync
                }
    
                mState = nextState;
            }
    
            if (event) {
                continue;
            }
    
            // Wait for event or client registration/request.
            if (mState == State::Idle) {
                mCondition.wait(lock);
            } else {
                // Generate a fake VSYNC after a long timeout in case the driver stalls. When the
                // display is off, keep feeding clients at 60 Hz.
                const std::chrono::nanoseconds timeout =
                        mState == State::SyntheticVSync ? 16ms : 1000ms;
                if (mCondition.wait_for(lock, timeout) == std::cv_status::timeout) {
                    if (mState == State::VSync) {
                        ALOGW("Faking VSYNC due to driver stall for thread %s", mThreadName);
                        std::string debugInfo = "VsyncSource debug info:\n";
                        mVSyncSource->dump(debugInfo);
                        // Log the debug info line-by-line to avoid logcat overflow
                        auto pos = debugInfo.find('\n');
                        while (pos != std::string::npos) {
                            ALOGW("%s", debugInfo.substr(0, pos).c_str());
                            debugInfo = debugInfo.substr(pos + 1);
                            pos = debugInfo.find('\n');
                        }
                    }
    
                    LOG_FATAL_IF(!mVSyncState);
                    const auto now = systemTime(SYSTEM_TIME_MONOTONIC);
                    const auto deadlineTimestamp = now + timeout.count();
                    const auto expectedVSyncTime = deadlineTimestamp + timeout.count();
                    const int64_t vsyncId = [&] {
                        if (mTokenManager != nullptr) {
                            return mTokenManager->generateTokenForPredictions(
                                    {now, deadlineTimestamp, expectedVSyncTime});
                        }
                        return FrameTimelineInfo::INVALID_VSYNC_ID;
                    }();
                    mPendingEvents.push_back(makeVSync(mVSyncState->displayId, now,
                                                       ++mVSyncState->count, expectedVSyncTime,
                                                       deadlineTimestamp, vsyncId));
                }
            }
        }
    }

    EventThread::threadMain代码逻辑上也比较清晰,主体就是从mPendingEvents这个待处理的事件队列中取出event,让后经过判断处理后通知到对应的connections

    本文作者@二的次方  2022-04-27 发布于博客园

    简单说说

     

    EventThread::shouldConsumeEvent

    这个方法就如同它的名字,判断是否去消费这个事件,说白了就是判断这个事件是否要分发通知给指定的connection。

    参数event就是当前发生的,准备分发的事件

    参数connection就是客户端注册到EventThread中的connection,其中就包装了用于跨进程通信的BitTube对象

    对于VSYNC事件,在这个函数中实现了setVsyncRate中设置的分发频率

    [ /frameworks/native/services/surfaceflinger/Scheduler/EventThread.cpp]
    bool EventThread::shouldConsumeEvent(const DisplayEventReceiver::Event& event,
                                         const sp<EventThreadConnection>& connection) const {
        const auto throttleVsync = [&] {
            return mThrottleVsyncCallback &&
                    mThrottleVsyncCallback(event.vsync.expectedVSyncTimestamp, connection->mOwnerUid);
        };
    
        switch (event.header.type) {
            case DisplayEventReceiver::DISPLAY_EVENT_HOTPLUG: // 热插拔事件
                return true;
    
            case DisplayEventReceiver::DISPLAY_EVENT_MODE_CHANGE: {// mode change事件
                return connection->mEventRegistration.test( //接收者设置了modeChanged标志才会分发
                        ISurfaceComposer::EventRegistration::modeChanged);
            }
    
            case DisplayEventReceiver::DISPLAY_EVENT_VSYNC: // VSYNC事件
                switch (connection->vsyncRequest) { // setVsyncRate设置分发的频率
                    case VSyncRequest::None: // rate==0,不分发
                        return false;
                    case VSyncRequest::SingleSuppressCallback:// requestNextVsync 有请求时case
                        connection->vsyncRequest = VSyncRequest::None;
                        return false;
                    case VSyncRequest::Single: { // requestNextVsync 有请求时case
                        if (throttleVsync()) {
                            return false;
                        }
                        connection->vsyncRequest = VSyncRequest::SingleSuppressCallback;
                        return true;
                    }
                    case VSyncRequest::Periodic: // rate==1,周期性,每个VSYNC事件都分发通知
                        if (throttleVsync()) {
                            return false;
                        }
                        return true;
                    default:
                        // We don't throttle vsync if the app set a vsync request rate
                        // since there is no easy way to do that and this is a very
                        // rare case
                        // 根据setVsyncRate设置分发的频率,周期性的计数,每connection->vsyncRequest个分发一个
                        return event.vsync.count % vsyncPeriod(connection->vsyncRequest) == 0;
                }
    
            case DisplayEventReceiver::DISPLAY_EVENT_FRAME_RATE_OVERRIDE:
                [[fallthrough]];
            case DisplayEventReceiver::DISPLAY_EVENT_FRAME_RATE_OVERRIDE_FLUSH: // frame rate override flush事件
                return connection->mEventRegistration.test(// 判断接收者设置了frameRateOverride标志才会分发
                        ISurfaceComposer::EventRegistration::frameRateOverride);
    
            default:
                return false;
        }
    }

     

    EventThread::dispatchEvent

    当前面判断某一个事件应该分发出去后,接下来就是去实际把事件分发出去,通知到接收者了

    最终的事件是通过调用EventThreadConnection::postEvent==> DisplayEventReceiver::sendEvents ==> gui::BitTube::sendObjects

    BitTube跨进程通知到接收者

    void EventThread::dispatchEvent(const DisplayEventReceiver::Event& event,
                                    const DisplayEventConsumers& consumers) {
        // 注意:using DisplayEventConsumers = std::vector<sp<EventThreadConnection>>; 
        // 从consumers数组中遍历EventThreadConnection
        for (const auto& consumer : consumers) {
            DisplayEventReceiver::Event copy = event;
            if (event.header.type == DisplayEventReceiver::DISPLAY_EVENT_VSYNC) {
                copy.vsync.frameInterval = mGetVsyncPeriodFunction(consumer->mOwnerUid);
            }
            switch (consumer->postEvent(copy)) { // postEvent分发事件==>EventThreadConnection::postEvent
                ...
            }
        }
    }

     

    DispSyncSource::setVSyncEnabled

    这个方法去call mRegistration.schedule  == > VSyncCallbackRegistration::schedule 去安排下一次的Vsync events

    大概如此,从而周期性的收到vsync events ,  不多讲了

     


     

    经过上面流程的分析,事件通过BitTube::sendObjects跨进程通知到接收者,接收者通过监听BitTube::mReceiveFd,并在接收到事件时调用BitTube::recvObjects就可以取出事件,做后续处理了

     

    总结一个不是很准确的图,我也不知道该咋表达了,哈

     

  • 相关阅读:
    Java之方法
    如何全面去理解通达信接口API?
    从零搭建一个vue项目
    text2sql、nl2sql框架总结
    android api 23以上 使用 httpclient
    Java中xml转javaBean
    基于PHP+MySQL汽车票订票系统的设计与实现(含论文)
    【Rust 基础篇】Rust Newtype模式:类型安全的包装器
    redis的缓存更新策略
    tensorflow内存泄漏或模型只加载不运行
  • 原文地址:https://www.cnblogs.com/roger-yu/p/16167404.html