查看原文
其他

Android14 VSync 机制深入解读

鸿洋
2024-09-26

The following article is from 阿豪讲Framework Author 阿豪

如果你玩过 PC 上的大型游戏,应该知道游戏中通常有一个叫做垂直同步的选项,如果不开这个选项,游戏过程中可能有画面撕裂的情况。

画面撕裂 VS 画面不撕裂

图片来自 https://sspai.com/post/63440

左侧是画面撕裂的情况,右侧是正常情况。

这种情况出现的主要原因是屏幕的刷新和主机的渲染不同步,假如,你是富哥,买了一张 4090 显卡,主机渲染图形非常快,但是你的显示器还是创业初期闲鱼捡的垃圾,刷新很慢(60hz),你游戏的时候,没有开垂直同步,当一帧还没全部刷新到屏幕上,下一帧数据又来了,显示器通常会中断当前帧的刷新,去刷新下一帧,这个时候,显示器上显示的就是当前帧和上一帧组合的图像,如果显示内容变化较大,你就能察觉到画面的撕裂。

这个问题最初是在 PC 上被重视和解决的,GPU 厂商开发出了一种防止屏幕被撕裂的技术方案,全称 Vertical Synchronization(中文名垂直同步,简称 VSync)。基本思路就是显示器在屏幕刷新之前向外提供一个信号,主机端根据此信号选择合适的策略完成画面的刷新,避免数据刷新和屏幕扫描不匹配(撕裂)的情况发生。

1VSync 基本框架

从硬件视角来看 VSync 其实就是一个电平信号,显示器的驱动板上有一个单独的引脚,这个引脚会根据显示器的刷新率定时的改变其高低电平。主机端需要有一个单独的 GPIO 与之相连,获取其信号变化;软件视角中的 VSync 其实就是一个 GPIO 的中断,一般是上升沿的中断。

当 Vsync 信号到来时,linux 内核就会收到一个中断,内核会根据对应的中断号去调用对应的中断处理函数。VSync 的中断处理函数会调用到 DRM 模块中,DRM 模块进一步又会调用到 HWComposor Hal 模块,HWComposor HAL 最终会回调到 SurfaceFlinger 中注册的 Vsync 硬件信号回调函数。

SurfaceFlinger 中的回调函数收到硬件传递来的 Vsync 信号后,会使用 VsyncSchedule 将 Vsync 信号到达时间和 Vsync 信号周期等信息记录下来并完成一些计算工作。当 App 需要绘制图像时, Choreographer 通过 Binder 向 VsyncSchedule 发起一个请求信号,VsyncSchedule 收到请求后会通过刚才记录的信息计算出软件 Vsync 信号,然后通过 socket 将该信号传递给 App,App 收到信号后开始绘制工作。


所以,我们并没有直接使用硬件 Vsync 信号,而是处理计算后的软件 Vsync 信号,在 Android14 中,软件 Vsync 信号有三类:

  • app-vsync:控制 app 上帧的 vsync,触发 app 进行绘制
  • appsf-vsync: 控制 app 上帧的 vsync,触发 app 进行绘制 和 app-vsync相位上有一定的偏差,使用较少
  • sf-vsync:控制 SurfaceFliner 进行合成的 vsync

那么这里就有一个问题,为什么 App 不直接使用硬件 Vsync 信号,要计算一个软件 Vsync 信号给 App 用?我觉得主要有以下几个原因:

  • 直接使用硬件 Vsync 更费电,Vsync 是一个周期性的信号,容易通过软件定时器模拟。通过软件模拟,可以关闭硬件 Vsync,达到省电的目的。
  • 让每个使用的 App 和 Surfacefliner 去直接监听硬件 vsync 会导致上层直接连接到硬件,这样的耦合性太高了,不利于软件的迭代。
  • App 获取硬件 Vsync 信号涉及到内核态与用户态的转换,周期性的信号会导致频繁的用户态内核态转换,造成较高的 cpu 资源占用。
  • 软件 Vsync 信号之间合理的相位差,会使得图形的绘制与合成效率更高,这是单个硬件 Vsync 信号做不到的。

2Vsync 相关初始化

2.1 CompositionEngine 初始化

SurfaceFlinger 有一个重要成员 mCompositionEngine,CompositionEngine 充当了 SurfaceFlinger 与 RenderEngine(渲染引擎,主要用于图层 GPU 合成)和 HWComposer(硬件混合渲染器,主要用于图层硬件合成)之间的桥梁。

mCompositionEngine 在 SurfaceFlinger 的构造函数中初始化:

SurfaceFlinger::SurfaceFlinger(Factory& factory, SkipInitializationTag)
      : mFactory(factory),
        mPid(getpid()),
        mTimeStats(std::make_shared<impl::TimeStats>()),
        mFrameTracer(mFactory.createFrameTracer()),
        mFrameTimeline(mFactory.createFrameTimeline(mTimeStats, mPid)),
        // 关注点
        mCompositionEngine(mFactory.createCompositionEngine()),
        mHwcServiceName(base::GetProperty("debug.sf.hwc_service_name"s, "default"s)),
        mTunnelModeEnabledReporter(sp<TunnelModeEnabledReporter>::make()),
        mEmulatedDisplayDensity(getDensityFromProperty("qemu.sf.lcd_density"false)),
        mInternalDisplayDensity(
                getDensityFromProperty("ro.sf.lcd_density", !mEmulatedDisplayDensity)),
        mPowerAdvisor(std::make_unique<Hwc2::impl::PowerAdvisor>(*this)),
        mWindowInfosListenerInvoker(sp<WindowInfosListenerInvoker>::make()) {
    ALOGI("Using HWComposer service: %s", mHwcServiceName.c_str());
}

mCompositionEngine 通过 mFactory.createCompositionEngine() 初始化,前面分析过 mFactory 的实际类型是 DefaultFactory。具体实现如下:

// /frameworks/native/services/surfaceflinger/SurfaceFlingerDefaultFactory.cpp
std::unique_ptr<compositionengine::CompositionEngine> DefaultFactory::createCompositionEngine() {
    return compositionengine::impl::createCompositionEngine();
}

// /frameworks/native/services/surfaceflinger/CompositionEngine/src/CompositionEngine.cpp
std::unique_ptr<compositionengine::CompositionEngine> createCompositionEngine() {
    return std::make_unique<CompositionEngine>();
}

实际就是 new 了一个 CompositionEngine 对象,CompositionEngine 构造函数是默认实现,我们就不再看了。

2.2 RenderEngine 初始化

在 SurfaceFlinger 的启动过程中会执行到 SurfaceFlinger::init() 函数,在该函数中会初始化 Vsync 相关的对象。

// /frameworks/native/services/surfaceflinger/SurfaceFlinger.cpp

void SurfaceFlinger::init() FTL_FAKE_GUARD(kMainThreadContext) {
    // .....

    // 关注点 1
    // 构建 RenderEngine,用于 Client 合成
    auto builder = renderengine::RenderEngineCreationArgs::Builder()
                           .    1`(static_cast<int32_t>(defaultCompositionPixelFormat))
                           .setImageCacheSize(maxFrameBufferAcquiredBuffers)
                           .setUseColorManagerment(useColorManagement)
                           .setEnableProtectedContext(enable_protected_contents(false))
                           .setPrecacheToneMapperShaderOnly(false)
                           .setSupportsBackgroundBlur(mSupportsBlur)
                           .setContextPriority(
                                   useContextPriority
                                           ? renderengine::RenderEngine::ContextPriority::REALTIME
                                           : renderengine::RenderEngine::ContextPriority::MEDIUM);
    
    if (auto type = chooseRenderEngineTypeViaSysProp()) {
        builder.setRenderEngineType(type.value());
    }

    mRenderEngine = renderengine::RenderEngine::create(builder.build());
    mCompositionEngine->setRenderEngine(mRenderEngine.get());

    // ......
    
    // 关注点2
    // 创建HWComposer对象并传入一个name属性,再通过mCompositionEngine->setHwComposer设置对象属性。
    mCompositionEngine->setHwComposer(getFactory().createHWComposer(mHwcServiceName));
    // 这里的this就是SurfaceFlinger对象本身,因为它实现了HWC2::ComposerCallback回调接口
    mCompositionEngine->getHwComposer().setCallback(*this);
    // ......


    // Commit primary display.
    sp<const DisplayDevice> display;
    if (const auto indexOpt = mCurrentState.getDisplayIndex(getPrimaryDisplayIdLocked())) {
        const auto& displays = mCurrentState.displays;

        const auto& token = displays.keyAt(*indexOpt);
        const auto& state = displays.valueAt(*indexOpt);
         // 关注点3
        processDisplayAdded(token, state);

        mDrawingState.displays.add(token, state);

        //
        display = getDefaultDisplayDeviceLocked();
    }

    //......
    // 关注点4
    initScheduler(display);
    // ......
}

关注点 1,初始化了一个 renderengine::RenderEngineCreationArgs::Builder 对象,接着将 builder 对象传入 create 函数构建一个 RenderEngine 对象,create 函数的实现如下:

std::unique_ptr<RenderEngine> RenderEngine::create(const RenderEngineCreationArgs& args) {

    // 构建 builder 时,没有配置 renderEngineType 参数
    // 使用默认值 RenderEngine::RenderEngineType::SKIA_GL_THREADED
    switch (args.renderEngineType) {
        case RenderEngineType::THREADED:
            ALOGD("Threaded RenderEngine with GLES Backend");
            return renderengine::threaded::RenderEngineThreaded::create(
                    [args]() { return android::renderengine::gl::GLESRenderEngine::create(args); },
                    args.renderEngineType);
        case RenderEngineType::SKIA_GL:
            ALOGD("RenderEngine with SkiaGL Backend");
            return renderengine::skia::SkiaGLRenderEngine::create(args);
        case RenderEngineType::SKIA_VK:
            ALOGD("RenderEngine with SkiaVK Backend");
            return renderengine::skia::SkiaVkRenderEngine::create(args);
        case RenderEngineType::SKIA_GL_THREADED: { // 走这个分支
            ALOGD("Threaded RenderEngine with SkiaGL Backend");
            return renderengine::threaded::RenderEngineThreaded::create(
                    [args]() {
                        return android::renderengine::skia::SkiaGLRenderEngine::create(args);
                    },
                    args.renderEngineType);
        }
        case RenderEngineType::SKIA_VK_THREADED:
            ALOGD("Threaded RenderEngine with SkiaVK Backend");
            return renderengine::threaded::RenderEngineThreaded::create(
                    [args]() {
                        return android::renderengine::skia::SkiaVkRenderEngine::create(args);
                    },
                    args.renderEngineType);
        case RenderEngineType::GLES:
        default:
            ALOGD("RenderEngine with GLES Backend");
            return renderengine::gl::GLESRenderEngine::create(args);
    }
}

create 函数会走到 SKIA_GL_THREADED 这个 case, create 一个 RenderEngineThreaded 对象返回:

std::unique_ptr<RenderEngineThreaded> RenderEngineThreaded::create(CreateInstanceFactory factory,
                                                                   RenderEngineType type) 
{
    return std::make_unique<RenderEngineThreaded>(std::move(factory), type);
}

实际就是 new 一个 RenderEngineThreaded,其构造函数如下:

RenderEngineThreaded::RenderEngineThreaded(CreateInstanceFactory factory, RenderEngineType type)
      : RenderEngine(type) {
    ATRACE_CALL();

    std::lock_guard lockThread(mThreadMutex);
    mThread = std::thread(&RenderEngineThreaded::threadMain, this, factory);
}

在构造函数中会启动一个线程,线程的主函数是 RenderEngineThreaded::threadMain:

void RenderEngineThreaded::threadMain(CreateInstanceFactory factory) NO_THREAD_SAFETY_ANALYSIS {
    ATRACE_CALL();

    if (!SetTaskProfiles(0, {"SFRenderEnginePolicy"})) {
        ALOGW("Failed to set render-engine task profile!");
    }

    if (setSchedFifo(true) != NO_ERROR) {
        ALOGW("Couldn't set SCHED_FIFO");
    }

    // SkiaGLRenderEngine 类型
    mRenderEngine = factory();

    pthread_setname_np(pthread_self(), mThreadName);

    {
        std::scoped_lock lock(mInitializedMutex);
        mIsInitialized = true;
    }
    mInitializedCondition.notify_all();

    while (mRunning) {
        const auto getNextTask = [this]() -> std::optional<Work> {
            std::scoped_lock lock(mThreadMutex);
            if (!mFunctionCalls.empty()) {
                Work task = mFunctionCalls.front();
                mFunctionCalls.pop();
                return std::make_optional<Work>(task);
            }
            return std::nullopt;
        };

        const auto task = getNextTask();

        if (task) {
            (*task)(*mRenderEngine);
        }

        std::unique_lock<std::mutex> lock(mThreadMutex);
        mCondition.wait(lock, [this]() REQUIRES(mThreadMutex) {
            return !mRunning || !mFunctionCalls.empty();
        });
    }

    // we must release the RenderEngine on the thread that created it
    mRenderEngine.reset();
}

完成基本的初始化,主要是使用传入的 factory(create 的时候传入的 lamda 表达式) 构建一个 SkiaGLRenderEngine 对象,然后进入一个无线循环,取 task,执行 task,然后 lock 到锁对象上,等待唤醒。

容易猜到,这里的 Task 应该就是图层的 GPU 合成工作。

最后会调用到 mCompositionEngine->setRenderEngine(mRenderEngine.get()); 把构建好的 RenderEngine 对象给到 CompositionEngine 的 mRenderEngine 成员.

// /frameworks/native/services/surfaceflinger/ClientCache.h
void setRenderEngine(renderengine::RenderEngine* renderEngine) { mRenderEngine = renderEngine; }

相关类的关系如下图所示:

20240730215021

2.3 HWComposer 初始化

接着回到 init 函数中,我们来看看关注点 2 处:

    // 关注点2
    // 创建HWComposer对象并传入一个name属性,再通过mCompositionEngine->setHwComposer设置对象属性。
    mCompositionEngine->setHwComposer(getFactory().createHWComposer(mHwcServiceName));
    // 这里的this就是SurfaceFlinger对象本身,因为它实现了HWC2::ComposerCallback回调接口
    mCompositionEngine->getHwComposer().setCallback(*this);

首先,明确一点,HardWare Composor hal  是以 Binder 服务的形式存在于系统中的,这里通过 DefaultFactory 构建一个 HwComposer 对象,根据我们以往的分析源码的经验,HwComposer 大概率是一个 Binder 代理端类的包装类。

接下来我们来分析 HwComposer 的初始化过程。

// /frameworks/native/services/surfaceflinger/SurfaceFlingerDefaultFactory.cpp
std::unique_ptr<HWComposer> DefaultFactory::createHWComposer(const std::string& serviceName) {
    return std::make_unique<android::impl::HWComposer>(serviceName);
}

直接 new 一个 android::impl::HWComposer,其构造函数实现如下:

// /frameworks/native/services/surfaceflinger/DisplayHardware/HWComposer.cpp
HWComposer::HWComposer(const std::string& composerServiceName)
      : HWComposer(Hwc2::Composer::create(composerServiceName)) {}

HWComposer::HWComposer(std::unique_ptr<Hwc2::Composer> composer)
      : mComposer(std::move(composer)),
        mMaxVirtualDisplayDimension(static_cast<size_t>(sysprop::max_virtual_display_dimension(0))),
        mUpdateDeviceProductInfoOnHotplugReconnect(
                sysprop::update_device_product_info_on_hotplug_reconnect(false)) {}

接着会调用 create 函数构造一个 AidlComposer 对象,然后调用另一个构造函数重载:

std::unique_ptr<Composer> Composer::create(const std::string& serviceName) {
    if (AidlComposer::isDeclared(serviceName)) { // 新版本都会走该分支,使用 aidl hal
        return std::make_unique<AidlComposer>(serviceName);
    }

    return std::make_unique<HidlComposer>(serviceName);
}

AidlComposer 是 IComposer 的包装类,IComposer 实际就是 HWComposer Hal Binder 服务的代理端对象,用于发起 Binder 远程过程调用。构造函数实现如下:

// /frameworks/native/services/surfaceflinger/DisplayHardware/AidlComposerHal.h
    std::shared_ptr<AidlIComposer> mAidlComposer;
    std::shared_ptr<AidlIComposerClient> mAidlComposerClient;

// /frameworks/native/services/surfaceflinger/DisplayHardware/AidlComposerHal.cpp
AidlComposer::AidlComposer(const std::string& serviceName) {
    // This only waits if the service is actually declared
    // 拿到代理端对象
    mAidlComposer = AidlIComposer::fromBinder(
            ndk::SpAIBinder(AServiceManager_waitForService(instance(serviceName).c_str())));
    if (!mAidlComposer) {
        LOG_ALWAYS_FATAL("Failed to get AIDL composer service");
        return;
    }

    // 拿到匿名 Binder 服务的代理端对象 mAidlComposerClient
    if (!mAidlComposer->createClient(&mAidlComposerClient).isOk()) {
        LOG_ALWAYS_FATAL("Can't create AidlComposerClient, fallback to HIDL");
        return;
    }

    addReader(translate<Display>(kSingleReaderKey));

    // If unable to read interface version, then become backwards compatible.
    int32_t version = 1;
    const auto status = mAidlComposerClient->getInterfaceVersion(&version);
    if (!status.isOk()) {
        ALOGE("getInterfaceVersion for AidlComposer constructor failed %s",
              status.getDescription().c_str());
    }
    mSupportsBufferSlotsToClear = version > 1;
    if (!mSupportsBufferSlotsToClear) {
        if (sysprop::clear_slots_with_set_layer_buffer(false)) {
            mClearSlotBuffer = sp<GraphicBuffer>::make(11, PIXEL_FORMAT_RGBX_8888,
                                                       GraphicBuffer::USAGE_HW_COMPOSER |
                                                               GraphicBuffer::USAGE_SW_READ_OFTEN |
                                                               GraphicBuffer::USAGE_SW_WRITE_OFTEN,
                                                       "AidlComposer");
            if (!mClearSlotBuffer || mClearSlotBuffer->initCheck() != ::android::OK) {
                LOG_ALWAYS_FATAL("Failed to allocate a buffer for clearing layer buffer slots");
                return;
            }
        }
    }

    ALOGI("Loaded AIDL composer3 HAL service");
}

在构造函数中,首先通过 ServiceManager 获取到 HWComposer Hal 的代理端对象 mAidlComposer,接着通过 mAidlComposer 发起远程调用获取到匿名 Binder 服务的代理端对象 mAidlComposerClient。都是 Binder 的基本操作了。不在细说了。总而言之,AidlComposer 类包装了与 HWC Hal 交互的接口,让使用方更为方便地操作 HWC Hal。

到这里呢,我们就梳理出了 CompositionEngine 相关类的关系图:

20240730215128

总之,CompositionEngine 是 SurfaceFlinger 与 RenderEngine 和 HWComposer 沟通的桥梁,RenderEngine 负责图层的GPU 合成,HWComposer 负责图层的硬件合成。

2.4 HWComposer 回调注册

SurfaceFlinger::init 中接下来会给 HwComposer 注册一个回调对象:

 // 这里的this就是SurfaceFlinger对象本身,因为它实现了HWC2::ComposerCallback回调接口
    mCompositionEngine->getHwComposer().setCallback(*this);

给 HwComposor 对象注册了回调对象 this,也就是 SurfaceFlinger 对象,SurfaceFlinger 继承了 HWC2::ComposerCallback 接口,HWC2::ComposerCallback 中定义了 VSYNC信号、插拔显示器等的回调事件函数:

// /frameworks/native/services/surfaceflinger/DisplayHardware/HWC2.h
struct ComposerCallback {
    // 显示器热插拔事件
    virtual void onComposerHalHotplug(hal::HWDisplayId, hal::Connection) 0;
    // 显示器 refresh 刷新事件
    virtual void onComposerHalRefresh(hal::HWDisplayId) 0;
    // VSYNC 信号事件
    virtual void onComposerHalVsync(hal::HWDisplayId, nsecs_t timestamp,
                                    std::optional<hal::VsyncPeriodNanos>) 
0;
    //......
};

我们主要关心 onComposerHalVsync 函数,当硬件 Vsync 信号发生时,经过层层调用,最终会调用到这个函数,这部分会在后续的 Vsync 信号分发部分讲解。

2.5 DisplayDevice 初始化

SurfaceFlinger init 函数中的关注点 3,processDisplayAdded 会进行 Display 相关的初始化工作.

    sp<const DisplayDevice> display;

    if (const auto indexOpt = mCurrentState.getDisplayIndex(getPrimaryDisplayIdLocked())) {

        // 返回类型为 DefaultKeyedVector<wp<IBinder>, DisplayDeviceState>
        const auto& displays = mCurrentState.displays;

        const auto& token = displays.keyAt(*indexOpt);
        const auto& state = displays.valueAt(*indexOpt);
         // 关注点3
        processDisplayAdded(token, state);

        mDrawingState.displays.add(token, state);

        //
        display = getDefaultDisplayDeviceLocked();
    }
  • 拿到主显示器的 index
  • 这里从 mCurrentState 获取到 DefaultKeyedVector<wp<IBinder>, DisplayDeviceState>
  • DefaultKeyedVector<wp<IBinder>, DisplayDeviceState> 中获取到显示器的 Token 和 DisplayDeviceState,然后传递给 processDisplayAdded 函数处理

processDisplayAdded 函数的实现如下:

// /frameworks/native/services/surfaceflinger/SurfaceFlinger.h
display::DisplayMap<wp<IBinder>, const sp<DisplayDevice>> mDisplays GUARDED_BY(mStateLock);

// /frameworks/native/services/surfaceflinger/SurfaceFlinger.cpp

void SurfaceFlinger::processDisplayAdded(const wp<IBinder>& displayToken,
                                         const DisplayDeviceState& state) 
{
     // ......


     auto display = setupNewDisplayDeviceInternal(displayToken, std::move(compositionDisplay), state,
                                                 displaySurface, producer);
     // ....

     mDisplays.try_emplace(displayToken, std::move(display));
 }

processDisplayAdded 中会进一步调用 setupNewDisplayDeviceInternal 函数:

 sp<DisplayDevice> SurfaceFlinger::setupNewDisplayDeviceInternal(
        const wp<IBinder>& displayToken,
        std::shared_ptr<compositionengine::Display> compositionDisplay,
        const DisplayDeviceState& state,
        const sp<compositionengine::DisplaySurface>& displaySurface,
        const sp<IGraphicBufferProducer>& producer) 
{
        // ......

        // creationArgs 用于构建 DisplayDevice 对象
         creationArgs.refreshRateSelector =
                mPhysicalDisplays.get(physical->id)
                        .transform(&PhysicalDisplay::snapshotRef)
                        .transform([&](const display::DisplaySnapshot& snapshot) {
                            // 构建了一个 RefreshRateSelector 对象
                            return std::make_shared<
                                    scheduler::RefreshRateSelector>(snapshot.displayModes(),
                                                                    creationArgs.activeModeId,
                                                                    config);
                        })
                        .value_or(nullptr);
        // .....
        
        // 利用前面构建的  creationArgs 初始化一个 DisplayDevice 对象
        // factory 就是 DefaultFactory
        // 实际就是简单 new 一个 DisplayDevice
        sp<DisplayDevice> display = getFactory().createDisplayDevice(creationArgs);
 
 }                                          

这里通过 creationArgs 中的参数来构建一个 DisplayDevice 对象,creationArgs 中的参数来自前面传入的 DisplayDeviceState对象,构建出的 DisplayDevice 对象代表了一个屏幕相关的配置信息。

creationArgs 中有一个成员 RefreshRateSelector。每个 DisplayDevice 对应一个 RefreshRateSelector 对象,该对象用于基于屏幕支持的刷新率范围,选择一个合适的 Refresh Rate 和 Frame Rate,并会传递给 VSyncSchedule 作为软件 VSync 生成的重要因素。

接着将 DisplayDevice 对象插入 mDisplays 中,后续会调用 getDefaultDisplayDeviceLocked 函数取出这个 DisplayDevice 对象。

2.6 initScheduler 函数实现分析

我们接着看 init 函数中的关注点 4, initScheduler 函数:

    std::unique_ptr<scheduler::Scheduler> mScheduler;
    scheduler::ConnectionHandle mAppConnectionHandle;
    scheduler::ConnectionHandle mSfConnectionHandle;

// /frameworks/native/services/surfaceflinger/SurfaceFlinger.cpp

// 参数就是前面构建的 DisplayDevice 对象
void SurfaceFlinger::initScheduler(const sp<const DisplayDevice>& display) {
    using namespace scheduler;

    LOG_ALWAYS_FATAL_IF(mScheduler);

    // 从前面构建的 RefreshRateSelector 获取 RefreshRate
    // activeMode 就是当前屏幕的刷新率
    const auto activeMode = display->refreshRateSelector().getActiveMode();
    const Fps activeRefreshRate = activeMode.fps;
    // new 一个 RefreshRateStats
    mRefreshRateStats =
            std::make_unique<RefreshRateStats>(*mTimeStats, activeRefreshRate, hal::PowerMode::OFF);

    // 构建一个 VsyncConfiguration 对象
    mVsyncConfiguration = getFactory().createVsyncConfiguration(activeRefreshRate);

    // 配置 FeatureFlags
    FeatureFlags features;

    if (sysprop::use_content_detection_for_refresh_rate(false)) {
        features |= Feature::kContentDetection;
    }
    if (base::GetBoolProperty("debug.sf.show_predicted_vsync"s, false)) {
        features |= Feature::kTracePredictedVsync;
    }
    if (!base::GetBoolProperty("debug.sf.vsync_reactor_ignore_present_fences"s, false) &&
        !getHwComposer().hasCapability(Capability::PRESENT_FENCE_IS_NOT_RELIABLE)) {
        features |= Feature::kPresentFences;
    }
    if (display->refreshRateSelector().kernelIdleTimerController()) {
        features |= Feature::kKernelIdleTimer;
    }
    
    // 构建一个 VsyncModulator 对象
    // 根据事务调度和刷新率的变化调整 Vsync。
    auto modulatorPtr = sp<VsyncModulator>::make(mVsyncConfiguration->getCurrentConfigs());

    // 关注点1 
    // this + 前面构造的对象,初始化 Scheduler 对象
    mScheduler = std::make_unique<Scheduler>(static_cast<ICompositor&>(*this),
                                             static_cast<ISchedulerCallback&>(*this), features,
                                             std::move(modulatorPtr));

    // 关注点2                              
    mScheduler->registerDisplay(display->getPhysicalId(), display->holdRefreshRateSelector());

    // 关闭硬件 Vsync
    setVsyncEnabled(display->getPhysicalId(), false);

    // ?
    mScheduler->startTimers();

    const auto configs = mVsyncConfiguration->getCurrentConfigs();
    
    // 关注点3
    // 创建 VSYNC-app 对应的 EventThread
    mAppConnectionHandle =
            mScheduler->createEventThread(Scheduler::Cycle::Render,
                                          mFrameTimeline->getTokenManager(),
                                          /* workDuration */ configs.l ate.appWorkDuration,
                                          /* readyDuration */ configs.late.sfWorkDuration);

    // 创建 VSYNC-appSf 对应的 EventThread
    mSfConnectionHandle =
            mScheduler->createEventThread(Scheduler::Cycle::LastComposite,
                                          mFrameTimeline->getTokenManager(),
                                          /* workDuration */ activeRefreshRate.getPeriod(),
                                          /* readyDuration */ configs.late.sfWorkDuration);

    // 关注点4
    // 创建 VSYNC-sf 对应的调度器
    mScheduler->initVsync(mScheduler->getVsyncSchedule()->getDispatch(),
                        *mFrameTimeline->getTokenManager(), configs.late.sfWorkDuration);

    mRegionSamplingThread =
            sp<RegionSamplingThread>::make(*this,
                                           RegionSamplingThread::EnvironmentTimingTunables());

    mFpsReporter = sp<FpsReporter>::make(*mFrameTimeline, *this);
}

关注点 1,new 了一个 Scheduler 对象:

class Scheduler : android::impl::MessageQueue {
    // ......
}

Scheduler 是生成和派发 VSync 的整体调度器,继承自 MessageQueue。构造函数实现如下:

// /frameworks/native/services/surfaceflinger/Scheduler/Scheduler.cpp
Scheduler::Scheduler(ICompositor& compositor, ISchedulerCallback& callback, FeatureFlags features,
                     sp<VsyncModulator> modulatorPtr)
      : impl::MessageQueue(compositor),
        mFeatures(features),
        mVsyncModulator(std::move(modulatorPtr)),
        mSchedulerCallback(callback) {}

// /frameworks/native/services/surfaceflinger/Scheduler/MessageQueue.cpp
MessageQueue::MessageQueue(ICompositor& compositor)
      : MessageQueue(compositor, sp<Handler>::make(*this)) {}


MessageQueue::MessageQueue(ICompositor& compositor, sp<Handler> handler)
      : mCompositor(compositor),
        mLooper(sp<Looper>::make(kAllowNonCallbacks)),
        mHandler(std::move(handler)) {}

Scheduler 的构造函数对内部的几个成员做了初始化:

  • mCompositor,传入的是 Surfaceflinger 对象
  • mFeatures,前面获取的一些 flags
  • mVsyncModulator,根据事务调度和刷新率的变化调整 Vsync
  • mSchedulerCallback,传入的是 Surfaceflinger 对象
  • mLooper mHandler:事件循环相关类

这些类的关系如下图所示:

20240710121944

关注点2 Scheduler::registerDisplay

Scheduler::registerDisplay 实现如下:

// /frameworks/native/services/surfaceflinger/Scheduler/Scheduler.cpp
void Scheduler::registerDisplay(PhysicalDisplayId displayId, RefreshRateSelectorPtr selectorPtr) {
    registerDisplayInternal(displayId, std::move(selectorPtr),
                            // new 一个 VsyncSchedule 对象
                            std::make_shared<VsyncSchedule>(displayId, mFeatures));
}

先 new 一个 VsyncSchedule 对象,再调用 registerDisplayInternal 函数。

先看 new VsyncSchedule 的过程:

// /frameworks/native/services/surfaceflinger/Scheduler/VsyncSchedule.cpp
VsyncSchedule::VsyncSchedule(PhysicalDisplayId id, FeatureFlags features)
      : mId(id),
        mTracker(createTracker(id)),
        mDispatch(createDispatch(mTracker)),
        mController(createController(id, *mTracker, features)),
        mTracer(features.test(Feature::kTracePredictedVsync)
                        ? std::make_unique<PredictedVsyncTracer>(mDispatch)
                        : nullptr) {}

在构造函数中初始化了以下几个重要成员:

  • mTracker
  • mDispatch
  • mController

我们一个个看:

// /frameworks/native/services/surfaceflinger/Scheduler/VsyncSchedule.cpp
VsyncSchedule::TrackerPtr VsyncSchedule::createTracker(PhysicalDisplayId id) {
    // TODO(b/144707443): Tune constants.
    constexpr nsecs_t kInitialPeriod = (60_Hz).getPeriodNsecs();
    constexpr size_t kHistorySize = 20;
    constexpr size_t kMinSamplesForPrediction = 6;
    constexpr uint32_t kDiscardOutlierPercent = 20;

    return std::make_unique<VSyncPredictor>(id, kInitialPeriod, kHistorySize,
                                            kMinSamplesForPrediction, kDiscardOutlierPercent);
}

就是 new 一个 VSyncPredictor 对象,VSyncPredictor 在 VsyncSchedule 的语境中为一个 Tracker,是负责综合各方因素根据算法由硬件 VSync 计算出软件 VSync 周期的工具类。

VSyncPredictor 的构造函数实现如下:

    // /frameworks/native/services/surfaceflinger/Scheduler/VSyncPredictor.h
    std::unordered_map<nsecs_t, Model> mutable mRateMap GUARDED_BY(mMutex);

// /frameworks/native/services/surfaceflinger/Scheduler/VSyncPredictor.cpp
VSyncPredictor::VSyncPredictor(PhysicalDisplayId id, nsecs_t idealPeriod, size_t historySize,
                               size_t minimumSamplesForPrediction, uint32_t outlierTolerancePercent)
      : mId(id),
        mTraceOn(property_get_bool("debug.sf.vsp_trace"false)),
        kHistorySize(historySize),
        kMinimumSamplesForPrediction(minimumSamplesForPrediction),
        kOutlierTolerancePercent(std::min(outlierTolerancePercent, kMaxPercent)),
        mIdealPeriod(idealPeriod) {
    resetModel();
}

void VSyncPredictor::resetModel() {
    std::lock_guard lock(mMutex);
    mRateMap[mIdealPeriod] = {mIdealPeriod, 0};
    clearTimestamps();
}

构造函数中,初始化了很多参数值。这些参数都是用于后续计算软件 VSync 的。接着调用 resetModel(),给 mRateMap 插入一组初始化数据,mRateMap 是一个 unordered_map 类型的 数据,用于保存硬件 Vsync 相关的数据。

关于这些数据的作用以及软件 Vsync 的计算过程,会在本节后续相关章节详细讲解。

mDispatch 成员通过 createDispatch 初始化:

VsyncSchedule::DispatchPtr VsyncSchedule::createDispatch(TrackerPtr tracker) {
    using namespace std::chrono_literals;

    // TODO(b/144707443): Tune constants.
    constexpr std::chrono::nanoseconds kGroupDispatchWithin = 500us;
    constexpr std::chrono::nanoseconds kSnapToSameVsyncWithin = 3ms;

    return std::make_unique<VSyncDispatchTimerQueue>(std::make_unique<Timer>(), std::move(tracker),
                                                     kGroupDispatchWithin.count(),
                                                     kSnapToSameVsyncWithin.count());
}

mDispatch 的实际类型是 VsyncDispatch,createDispatch 函数中会 new 一个 VSyncDispatchTimerQueue 对象(VsyncDispatch 的子类)并返回,该对象在 VsyncSchedule 的语境中为一个 Dispather,负责将 VSync 分发到使用者。

mController 成员通过 createController 函数初始化:

// /frameworks/native/services/surfaceflinger/Scheduler/VsyncSchedule.cpp
VsyncSchedule::ControllerPtr VsyncSchedule::createController(PhysicalDisplayId id,
                                                             VsyncTracker& tracker,
                                                             FeatureFlags features) 
{
    // TODO(b/144707443): Tune constants.
    constexpr size_t kMaxPendingFences = 20;
    const bool hasKernelIdleTimer = features.test(Feature::kKernelIdleTimer);

    auto reactor = std::make_unique<VSyncReactor>(id, std::make_unique<SystemClock>(), tracker,
                                                  kMaxPendingFences, hasKernelIdleTimer);

    reactor->setIgnorePresentFences(!features.test(Feature::kPresentFences));
    return reactor;
}

mController 的实际类型是 VsyncController。在 createController 函数中会 new 一个 VSyncReactor 对象(VsyncController 的子类)并返回。这个对象的主要作用是负责传递 HWVsync,presentFence 信号

到这里,VsyncSchedule 就初始化完成了,相关类的关系如下图所示:

20240730215531

接着看 registerDisplayInternal 的实现:

display::PhysicalDisplayMap<PhysicalDisplayId, Display> mDisplays

void Scheduler::registerDisplayInternal(PhysicalDisplayId displayId,
                                        RefreshRateSelectorPtr selectorPtr,
                                        VsyncSchedulePtr schedulePtr) 
{
    demotePacesetterDisplay();

    std::shared_ptr<VsyncSchedule> pacesetterVsyncSchedule;
    {
        std::scoped_lock lock(mDisplayLock);
        // 把 display RefreshRateSelectorPtr VsyncSchedule 三个对象关联起来
        mDisplays.emplace_or_replace(displayId, std::move(selectorPtr), std::move(schedulePtr));
        
        // 应该就是刚才初始化的 VsyncSchedule 对象
        pacesetterVsyncSchedule = promotePacesetterDisplayLocked();
    }
    applyNewVsyncSchedule(std::move(pacesetterVsyncSchedule));
}

把 display RefreshRateSelectorPtr VsyncSchedule 三个对象插入 mDisplays 成员中关联起来,实际后两个参数会构建一个 Display 对象再插入

接着调用 applyNewVsyncSchedule 函数:

void Scheduler::applyNewVsyncSchedule(std::shared_ptr<VsyncSchedule> vsyncSchedule) {

    onNewVsyncSchedule(vsyncSchedule->getDispatch());

    // mConnections 还是 empty 的,后续代码实际都不会执行
    std::vector<android::EventThread*> threads;
    {
        std::lock_guard<std::mutex> lock(mConnectionsLock);
        threads.reserve(mConnections.size());
        for (auto& [_, connection] : mConnections) {
            threads.push_back(connection.thread.get());
        }
    }
    for (auto* thread : threads) {
        thread->onNewVsyncSchedule(vsyncSchedule);
    }
}

这里会接着调用 onNewVsyncSchedule 函数:

void MessageQueue::onNewVsyncSchedule(std::shared_ptr<scheduler::VSyncDispatch> dispatch) {
    std::unique_ptr<scheduler::VSyncCallbackRegistration> oldRegistration;
    {
        std::lock_guard lock(mVsync.mutex);
        oldRegistration = onNewVsyncScheduleLocked(std::move(dispatch));
    }

    // The old registration needs to be deleted after releasing mVsync.mutex to
    // avoid deadlock. This is because the callback may be running on the timer
    // thread. In that case, timerCallback sets
    // VSyncDispatchTimerQueueEntry::mRunning to true, then attempts to lock
    // mVsync.mutex. But if it's already locked, the VSyncCallbackRegistration's
    // destructor has to wait until VSyncDispatchTimerQueueEntry::mRunning is
    // set back to false, but it won't be until mVsync.mutex is released.
    oldRegistration.reset();
}

接着调用 onNewVsyncScheduleLocked 函数:

    struct Vsync {
        frametimeline::TokenManager* tokenManager = nullptr;

        mutable std::mutex mutex;
        std::unique_ptr<scheduler::VSyncCallbackRegistration> registration GUARDED_BY(mutex);
        TracedOrdinal<std::chrono::nanoseconds> workDuration
                GUARDED_BY(mutex) 
= {"VsyncWorkDuration-sf"std::chrono::nanoseconds(0)};
        TimePoint lastCallbackTime GUARDED_BY(mutex);
        std::optional<nsecs_t> scheduledFrameTime GUARDED_BY(mutex);
        TracedOrdinal<int> value = {"VSYNC-sf"0};
    };


Vsync mVsync;

std::unique_ptr<scheduler::VSyncCallbackRegistration> MessageQueue::onNewVsyncScheduleLocked(
        std::shared_ptr<scheduler::VSyncDispatch> dispatch) 
{

    // 这个时候 mVsync.registration 为空,reschedule 是 false
    const bool reschedule = mVsync.registration &&
            mVsync.registration->cancel() == scheduler::CancelResult::Cancelled;
    auto oldRegistration = std::move(mVsync.registration);
    // 关键点
    mVsync.registration = std::make_unique<
            scheduler::VSyncCallbackRegistration>(std::move(dispatch),
                                                  std::bind(&MessageQueue::vsyncCallback, this,
                                                            std::placeholders::_1,
                                                            std::placeholders::_2,
                                                            std::placeholders::_3),
                                                  "sf");
    // 不进入
    if (reschedule) {
        mVsync.scheduledFrameTime =
                mVsync.registration->schedule({.workDuration = mVsync.workDuration.get().count(),
                                               .readyDuration = 0,
                                               .earliestVsync = mVsync.lastCallbackTime.ns()});
    }
    return oldRegistration;
}

这里核心点就是 new 一个 VSyncCallbackRegistration 对象并保存在 mVsync 的 registration 成员中。

VSyncCallbackRegistration::VSyncCallbackRegistration(std::shared_ptr<VSyncDispatch> dispatch,
                                                     VSyncDispatch::Callback callback,
                                                     std::string callbackName)
      : mDispatch(std::move(dispatch)),
        mToken(mDispatch->registerCallback(std::move(callback), std::move(callbackName))) {}

VSyncCallbackRegistration 的构造函数中,会将 callback 注册到 mDispatch,这里的 callback 就是 MessageQueue::vsyncCallback。

VSyncDispatchTimerQueue::CallbackToken VSyncDispatchTimerQueue::registerCallback(
        Callback callback, std::string callbackName) 
{
    std::lock_guard lock(mMutex);
    return CallbackToken{
            mCallbacks
                    .emplace(++mCallbackToken,
                             std::make_shared<VSyncDispatchTimerQueueEntry>(std::move(callbackName),
                                                                            std::move(callback),
                                                                            mMinVsyncDistance))
                    .first->first};
}

这里把回调函数包装为 VSyncDispatchTimerQueueEntry 对象,并插入 mCallbacks 中。

后续会通过 VSyncCallbackRegistration 去申请 Vsync 信号,申请过程中会调用到这个回调函数来分发软件 Vsync 信号,这个我们会在本节后续章节详细分析。

到这里,我们 Scheduler 相关的类图就增加了两个类:

20240710181631

回到 SurfaceFlinger::initScheduler 的关注点3:

    // 创建 VSYNC-app 对应的 EventThread
    mAppConnectionHandle =
            mScheduler->createEventThread(Scheduler::Cycle::Render,
                                          mFrameTimeline->getTokenManager(),
                                          /* workDuration */ configs.l ate.appWorkDuration,
                                          /* readyDuration */ configs.late.sfWorkDuration);

    // 创建 VSYNC-appSf 对应的 EventThread
    mSfConnectionHandle =
            mScheduler->createEventThread(Scheduler::Cycle::LastComposite,
                                          mFrameTimeline->getTokenManager(),
                                          /* workDuration */ activeRefreshRate.getPeriod(),
                                          /* readyDuration */ configs.late.sfWorkDuration);

这里通过 createEventThread 函数构建了两个 EventThread 对象。

// /frameworks/native/services/surfaceflinger/Scheduler/Scheduler.cpp
ConnectionHandle Scheduler::createEventThread(Cycle cycle,
                                              frametimeline::TokenManager* tokenManager,
                                              std::chrono::nanoseconds workDuration,
                                              std::chrono::nanoseconds readyDuration) 
{

    auto eventThread = std::make_unique<impl::EventThread>(cycle == Cycle::Render ? "app" : "appSf",
                                                           getVsyncSchedule(), tokenManager,
                                                           makeThrottleVsyncCallback(),
                                                           makeGetVsyncPeriodFunction(),
                                                           workDuration, readyDuration);

    auto& handle = cycle == Cycle::Render ? mAppConnectionHandle : mSfConnectionHandle;
    handle = createConnection(std::move(eventThread));
    return handle;
}

构建一个 EventThread 对象并创建对应的 Connection 对象,EventThread 是用处理 VSYNC 的一个独立线程。内部维护一个 while 无限循环。

  • 一方面,通过 VSyncCallbackRegistration 去申请下一次 VSYNC,
  • 另一方面,当 VSYNC 生成,通过 Connection 将 VSYNC 发送给 DisplayEventReceiver,也就是 VSYNC 的终端接收者。
  • 一般情况下有两个 EventThread,一个是针对客户端应用侧的 VSYNC-app,另一个是客户端想使用 SF 同步信号的 VSYNC-appSf。

在初始化 SurfaceFlinger 时,创建了两个子线程(EventThread)用来分别向客户端派 app-vsync 事件和 appsf-vsync 事件,这两个 EventThread 最重要的区别是对应的 workduration,readyduration 不同。

workduration:代表自身工作的理论耗时 readyduration:代表自身工作完成后,传递给下一模块处理的等待时间

以 sf 和 app 举例:app 的 workduration 代表 app 绘制渲染一帧的理论耗时,app 的 readyduration 代表 app 绘制渲染一帧完成后交给 surfaceflinger 处理的理耗时,sf 的 workduration 代表 sf 处理这一帧的理论耗时,readyduration代表传递给下一模块处理的等待时间。

可见 app 的 readyduration== sf 的 workduration,且 sf 的 readyduration=0

接着看 EventThread 的构造函数:

// /frameworks/native/services/surfaceflinger/Scheduler/EventThread.h
    State mState GUARDED_BY(mMutex) = State::Idle;

// /frameworks/native/services/surfaceflinger/Scheduler/EventThread.cpp
EventThread::EventThread(const char* name, std::shared_ptr<scheduler::VsyncSchedule> vsyncSchedule,
                         android::frametimeline::TokenManager* tokenManager,
                         ThrottleVsyncCallback throttleVsyncCallback,
                         GetVsyncPeriodFunction getVsyncPeriodFunction,
                         std::chrono::nanoseconds workDuration,
                         std::chrono::nanoseconds readyDuration)
      : mThreadName(name),
        mVsyncTracer(base::StringPrintf("VSYNC-%s", name), 0),
        mWorkDuration(base::StringPrintf("VsyncWorkDuration-%s", name), workDuration),
        mReadyDuration(readyDuration),
        mVsyncSchedule(std::move(vsyncSchedule)),
        mVsyncRegistration(mVsyncSchedule->getDispatch(), createDispatchCallback(), name),
        mTokenManager(tokenManager),
        mThrottleVsyncCallback(std::move(throttleVsyncCallback)),
        mGetVsyncPeriodFunction(std::move(getVsyncPeriodFunction)) {
    LOG_ALWAYS_FATAL_IF(getVsyncPeriodFunction == nullptr,
            "getVsyncPeriodFunction must not be null");

    // 构建一个线程对象
    // 执行 threadMain 函数
    mThread = std::thread([this]() NO_THREAD_SAFETY_ANALYSIS {
        std::unique_lock<std::mutex> lock(mMutex);
        threadMain(lock);
    });

    pthread_setname_np(mThread.native_handle(), mThreadName);

    pid_t tid = pthread_gettid_np(mThread.native_handle());

    // Use SCHED_FIFO to minimize jitter
    constexpr int EVENT_THREAD_PRIORITY = 2;
    struct sched_param param = {0};
    param.sched_priority = EVENT_THREAD_PRIORITY;
    if (pthread_setschedparam(mThread.native_handle(), SCHED_FIFO, &param) != 0) {
        ALOGE("Couldn't set SCHED_FIFO for EventThread");
    }

    set_sched_policy(tid, SP_FOREGROUND);
}

EventThread::~EventThread() {
    {
        std::lock_guard<std::mutex> lock(mMutex);
        mState = State::Quit;
        mCondition.notify_all();
    }
    // 等待线程结束
    mThread.join();
}

在 EventThread 的初始化过程中会,会启动一个线程,在该线程中会执行 EventThread::threaMain(),该函数是会执行一个 while 循环,该循环的运行受状态机控制:

// /frameworks/native/services/surfaceflinger/Scheduler/EventThread.h
enum class State {
        Idle,
        Quit,
        SyntheticVSync,
        VSync,
    };
  • Idle:表示当前处于空闲状态,等待客户端注册或请求 Vsync 信号;
  • Quit:退出循环,EventThread 被析构掉时。
  • SyntheticVSync:表示由 EventThread 来提供虚假的 Vsync 信号(灭屏、虚拟屏时会是这种状态,以 60Hz 的速度提供)。
  • VSync:表示正常亮屏时请求 Vsync 信号。

threaMain 的实现细节留在后续的 Vsync 信号分发章节来讲。

接着创建 Connection 对象:

// /frameworks/native/services/surfaceflinger/Scheduler/Scheduler.cpp
ConnectionHandle Scheduler::createConnection(std::unique_ptr<EventThread> eventThread) {
    const ConnectionHandle handle = ConnectionHandle{mNextConnectionHandleId++};
    ALOGV("Creating a connection handle with ID %" PRIuPTR, handle.id);

    auto connection = createConnectionInternal(eventThread.get());

    std::lock_guard<std::mutex> lock(mConnectionsLock);
    mConnections.emplace(handle, Connection{connection, std::move(eventThread)});
    return handle;
}

sp<EventThreadConnection> Scheduler::createConnectionInternal(
        EventThread* eventThread, EventRegistrationFlags eventRegistration,
        const sp<IBinder>& layerHandle) 
{
    int32_t layerId = static_cast<int32_t>(LayerHandle::getLayerId(layerHandle));
    auto connection = eventThread->createEventConnection([&] { resync(); }, eventRegistration);
    mLayerHistory.attachChoreographer(layerId, connection);
    return connection;
}

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

其实就是 new 一个 EventThreadConnection 对象:

EventThreadConnection::EventThreadConnection(EventThread* eventThread, uid_t callingUid,
                                             ResyncCallback resyncCallback,
                                             EventRegistrationFlags eventRegistration)
      : resyncCallback(std::move(resyncCallback)),
        mOwnerUid(callingUid),
        mEventRegistration(eventRegistration),
        mEventThread(eventThread),
        mChannel(gui::BitTube::DefaultSize) {}

mChannel 的类型是 BitTube ,包装了 socket ,用于与 app 通讯。

EventThreadConnection 中有几个重要的方法:

class EventThreadConnection : public gui::BnDisplayEventConnection {
public:
 // 当vsync信号来临时,通过sockt-pair将信号发送给app
    virtual status_t postEvent(const DisplayEventReceiver::Event& event);
    // app通过binder跨进程调用此方法,将建立的socketpair返回给应用
    binder::Status stealReceiveChannel(gui::BitTube* outChannel) override;
    // binder跨进程方法跨进程调用此方法,将会向surfaceflinger请求一个vsync信号
    binder::Status requestNextVsync() override// asynchronous

    VSyncRequest vsyncRequest = VSyncRequest::None;
    // .....
}

app 会向 surfaceflinger binder 建立连接,该连接就是 EventThreadConnection,是一个匿名 Binder。连接建立后会把该连接保存在 EventThread 的 mDisplayEventConnections 列表中。如上文代码所展示 EventThreadConnection 继承自 BnDisplayEventConnection,故 EventThreadConnection 具有使用 binder 跨进程的能力,且是 binder 的服务端类。建立连接后,app 端会调用 stealReceiveChannel 方法将 socketpair 返回给 app,后续的 vsync 信号将会使用该 socketpair 不断分发给 app。

在 EventThreadConnection 中除了代码中注释的三个重要的方法外,还有一个变量 vsyncRequest ,类型为 VSyncRequest :

enum class VSyncRequest {
    None = -2,
    // Single wakes up for the next two frames to avoid scheduler overhead
    Single = -1,
    // SingleSuppressCallback only wakes up for the next frame
    SingleSuppressCallback = 0,
    Periodic = 1,
    // Subsequent values are periods.
};

vsyncRequest 保存着对应 EventThreadConnection 申请 vsync 的状态

  • None:不请求
  • Single :该状态下会得到两次软件 vsync 回调
  • SingleSuppressCallback :该状态下会得到一次vsync回调
  • Periodic:亮屏下不使用该状态

需要注意的是 Single 状态下会收到两次 vsync 信号,能避免额外的唤醒循环。

Connection 用于与 DisplayEventReceiver 通信,发送 VSync 信号。

接着看关注点4

    // 创建 VSYNC-sf 对应的调度器
    mScheduler->initVsync(mScheduler->getVsyncSchedule()->getDispatch(),
                        *mFrameTimeline->getTokenManager(), configs.late.sfWorkDuration);

这里会初始化 VSYNC-sf 对应的调度器,initVsync 的实现如下:

void MessageQueue::initVsync(std::shared_ptr<scheduler::VSyncDispatch> dispatch,
                             frametimeline::TokenManager& tokenManager,
                             std::chrono::nanoseconds workDuration) 
{
    std::unique_ptr<scheduler::VSyncCallbackRegistration> oldRegistration;
    {
        std::lock_guard lock(mVsync.mutex);
        mVsync.workDuration = workDuration;
        mVsync.tokenManager = &tokenManager;
        oldRegistration = onNewVsyncScheduleLocked(std::move(dispatch));
    }

    // See comments in onNewVsyncSchedule. Today, oldRegistration should be
    // empty, but nothing prevents us from calling initVsync multiple times, so
    // go ahead and destruct it outside the lock for safety.
    oldRegistration.reset();
}

这里会去执行 onNewVsyncScheduleLocked 函数,不过在前面的 registerDisplay 中已经执行过了,好像有点重复,我们就不在分析了。

分析到这里,相关类的类图如下图所示:

20240730220538

图片太大了,应该看不清,原图可以看:

https://boardmix.cn/app/share/CAE.CMLx1wwgASoQAwZm0kipbusPGafdxHYZ1zAGQAE/hxtUlY

3HwComposer 分发硬件 VSync 信号

在 surfaceflinger::init 中调用了 HwComposer 的 setCallback 方法,传入的参数是 surfaceflinger 对象。

mCompositionEngine->getHwComposer().setCallback(*this);

surfaceflinger 实现了 HWC2::ComposerCallback 回调接口。

HWC2::ComposerCallback 中定义了 VSYNC信号、插拔显示器等的回调事件函数:

// /frameworks/native/services/surfaceflinger/DisplayHardware/HWC2.h
struct ComposerCallback {
    // 热插拔事件
    virtual void onComposerHalHotplug(hal::HWDisplayId, hal::Connection) 0;
    // refresh 刷新事件
    virtual void onComposerHalRefresh(hal::HWDisplayId) 0;
    // VSYNC 信号事件
    virtual void onComposerHalVsync(hal::HWDisplayId, nsecs_t timestamp,
                                    std::optional<hal::VsyncPeriodNanos>) 
0;
    //......
};

当硬件 Vsync 信号(一般是上升沿)到来时,会回调到 SurfaceFlinger::onComposerHalVsync 函数。

// /android-14.0.0_r15/frameworks/native/services/surfaceflinger/SurfaceFlinger.cpp
void SurfaceFlinger::onComposerHalVsync(hal::HWDisplayId hwcDisplayId, int64_t timestamp,
                                        std::optional<hal::VsyncPeriodNanos> vsyncPeriod) 
{
    ATRACE_NAME(vsyncPeriod
                        ? ftl::Concat(__func__, ' ', hwcDisplayId, ' ', *vsyncPeriod, "ns").c_str()
                        : ftl::Concat(__func__, ' ', hwcDisplayId).c_str());

    Mutex::Autolock lock(mStateLock);
    // 关注点1
    if (const auto displayIdOpt = getHwComposer().onVsync(hwcDisplayId, timestamp)) {
        // 关注点 2
        if (mScheduler->addResyncSample(*displayIdOpt, timestamp, vsyncPeriod)) {
            // 关注点 3
            // period flushed
            mScheduler->modulateVsync(displayIdOpt, &VsyncModulator::onRefreshRateChangeCompleted);
        }
    }
}

传入的三个参数:

  • hwcDisplayId 表示显示器的 ID,意思是当前的 Vysnc 信号来自哪个显示器
  • 参数 timestamp 表示 Vsync 信号的时间点
  • vsyncPeriod 表示连续两个 Vsync 信号的时间间隔

关注点1 onVsync 的实现如下:

// /frameworks/native/services/surfaceflinger/DisplayHardware/HWComposer.cpp

// ID 类型转换外加一些特殊情况判断
std::optional<PhysicalDisplayId> HWComposer::onVsync(hal::HWDisplayId hwcDisplayId,
                                                     nsecs_t timestamp) 
{
    const auto displayIdOpt = toPhysicalDisplayId(hwcDisplayId);
    if (!displayIdOpt) {
        LOG_HWC_DISPLAY_ERROR(hwcDisplayId, "Invalid HWC display");
        return {};
    }

    RETURN_IF_INVALID_DISPLAY(*displayIdOpt, {});

    auto& displayData = mDisplayData[*displayIdOpt];

    {
        // There have been reports of HWCs that signal several vsync events
        // with the same timestamp when turning the display off and on. This
        // is a bug in the HWC implementation, but filter the extra events
        // out here so they don't cause havoc downstream.
        if (timestamp == displayData.lastPresentTimestamp) {
            ALOGW("Ignoring duplicate VSYNC event from HWC for display %s (t=%" PRId64 ")",
                  to_string(*displayIdOpt).c_str(), timestamp);
            return {};
        }

        displayData.lastPresentTimestamp = timestamp;
    }

    ATRACE_INT(ftl::Concat("HW_VSYNC_", displayIdOpt->value).c_str(),
               displayData.vsyncTraceToggle);
    displayData.vsyncTraceToggle = !displayData.vsyncTraceToggle;

    return displayIdOpt;
}

onVsync 中主要是 ID 类型的转换。

接着会调用 mScheduler->addResyncSample 添加的一个采样时间数据,这个采样数据经过一些算法处理后,会决定这个硬件的 vsync 是否需要上报到 app,以及是否需要打开和关闭硬件的 Vsync.

bool Scheduler::addResyncSample(PhysicalDisplayId id, nsecs_t timestamp,
                                std::optional<nsecs_t> hwcVsyncPeriodIn) 
{
    
    // 转换一下格式
    const auto hwcVsyncPeriod = ftl::Optional(hwcVsyncPeriodIn).transform([](nsecs_t nanos) {
        return Period::fromNs(nanos);
    });

    // 拿到 VsyncSchedule 对象
    auto schedule = getVsyncSchedule(id);
    if (!schedule) {
        ALOGW("%s: Invalid display %s!", __func__, to_string(id).c_str());
        return false;
    }

    // 返回值表示硬件的 vsync 是否需要上报到 app
    return schedule->addResyncSample(mSchedulerCallback, TimePoint::fromNs(timestamp),
                                     hwcVsyncPeriod);
}

getVsyncSchedule 的实现如下:

auto Scheduler::getVsyncSchedule(std::optional<PhysicalDisplayId> idOpt) const
        -> ConstVsyncSchedulePtr 
{
    std::scoped_lock lock(mDisplayLock);
    return getVsyncScheduleLocked(idOpt);
}

auto Scheduler::getVsyncScheduleLocked(std::optional<PhysicalDisplayId> idOpt) const
        -> ConstVsyncSchedulePtr 
{
    ftl::FakeGuard guard(kMainThreadContext);

    if (!idOpt) {
        LOG_ALWAYS_FATAL_IF(!mPacesetterDisplayId, "Missing a pacesetter!");
        idOpt = mPacesetterDisplayId;
    }

    const auto displayOpt = mDisplays.get(*idOpt);
    if (!displayOpt) {
        return nullptr;
    }
    return displayOpt->get().schedulePtr;
}

就是从成员变量 mDisplays 中拿到 VsyncSchedule 对象。

接着调用 VsyncSchedule 的 addResyncSample 函数:


// 类型是 VsyncController 指针
const ControllerPtr mController;

// /frameworks/native/services/surfaceflinger/Scheduler/VsyncSchedule.cpp
bool VsyncSchedule::addResyncSample(ISchedulerCallback& callback, TimePoint timestamp,
                                    ftl::Optional<Period> hwcVsyncPeriod) 
{
    bool needsHwVsync = false;
    bool periodFlushed = false;
    {
        std::lock_guard<std::mutex> lock(mHwVsyncLock);
        if (mHwVsyncState == HwVsyncState::Enabled) {
            needsHwVsync = mController->addHwVsyncTimestamp(timestamp.ns(),
                                                            hwcVsyncPeriod.transform(&Period::ns),
                                                            &periodFlushed);
        }
    }
    if (needsHwVsync) {
        enableHardwareVsync(callback);
    } else {
        disableHardwareVsync(callback, false /* disallow */);
    }
    return periodFlushed;
}

接着调用 mController->addHwVsyncTimestamp

mController 的实际类型是 VsyncController 指针,VsyncController 内部均为纯虚函数,是一个接口类,具体的实现类是 VSyncReactor。

VsyncReactor 用于将硬件 Vsync 信号转换为软件 Vsync 信号。一般需要两个输入,第一是硬件 Vsync 到达的时间点,第二就是 Vsync 信号的周期。

接着调用到 VSyncReactor 的 addHwVsyncTimestamp 函数记录着两个数据:

addHwVsyncTimestamp 函数给 VsyncReactor 的计算模型加一组数据

    /*
     * Adds a hw sync timestamp to the model. The controller will use the timestamp
     * time as a vsync signal.
     *
     * \param [in] timestamp       The HW Vsync timestamp
     * \param [in] hwcVsyncPeriod  The Vsync period reported by composer, if available
     * \param [out] periodFlushed  True if the vsync period changed is completed
     * \return                     True if the model needs more vsync signals to make
     *                             an accurate prediction,
     *                             False otherwise
     */


bool VSyncReactor::addHwVsyncTimestamp(nsecs_t timestamp, std::optional<nsecs_t> hwcVsyncPeriod,
                                       bool* periodFlushed) 
{
    assert(periodFlushed);

    std::lock_guard lock(mMutex);
    if (periodConfirmed(timestamp, hwcVsyncPeriod)) {
        ATRACE_FORMAT("VSR %" PRIu64 ": period confirmed", mId.value);
        if (mPeriodTransitioningTo) {
            mTracker.setPeriod(*mPeriodTransitioningTo);
            *periodFlushed = true;
        }

        if (mLastHwVsync) {
            mTracker.addVsyncTimestamp(*mLastHwVsync);
        }
        mTracker.addVsyncTimestamp(timestamp);

        endPeriodTransition();
        mMoreSamplesNeeded = mTracker.needsMoreSamples();
    } else if (mPeriodConfirmationInProgress) {
        ATRACE_FORMAT("VSR %" PRIu64 ": still confirming period", mId.value);
        mLastHwVsync = timestamp;
        mMoreSamplesNeeded = true;
        *periodFlushed = false;
    } else {
        ATRACE_FORMAT("VSR %" PRIu64 ": adding sample", mId.value);
        *periodFlushed = false;
        mTracker.addVsyncTimestamp(timestamp);
        mMoreSamplesNeeded = mTracker.needsMoreSamples();
    }

    if (!mMoreSamplesNeeded) {
        setIgnorePresentFencesInternal(false);
    }
    return mMoreSamplesNeeded;
}

mTracker.setPeriod 添加周期

mTracker.addVsyncTimestamp 添加信号到达时间

实际就是根据参数去配置 mTracker,mTracker 的实际类型是 VSyncPredictor,是负责综合各方因素根据算法由硬件 VSync 计算出软件 VSync 周期的工具类。

接着调用 addVsyncTimestamp 向 VSyncPredictor 添加一组硬件 VSync 数据。

如果数据不少于 6 个,就会做计算

std::vector<nsecs_t> mTimestamps GUARDED_BY(mMutex);

bool VSyncPredictor::addVsyncTimestamp(nsecs_t timestamp) {
    std::lock_guard lock(mMutex);

    // ......
    

    if (mTimestamps.size() != kHistorySize) {
        mTimestamps.push_back(timestamp);
        mLastTimestampIndex = next(mLastTimestampIndex);
    } else {
        mLastTimestampIndex = next(mLastTimestampIndex);
        mTimestamps[mLastTimestampIndex] = timestamp;
    }

    traceInt64If("VSP-ts", timestamp);

    // kMinimumSamplesForPrediction 的值为 6
    // 少于 6 个数据,直接返回
    // mIdealPeriod 是 16.6,也就是 60hz 
    const size_t numSamples = mTimestamps.size();
    if (numSamples < kMinimumSamplesForPrediction) {
        mRateMap[mIdealPeriod] = {mIdealPeriod, 0};
        return true;
    }

    // 有六个数据后,往后走

    // This is a 'simple linear regression' calculation of Y over X, with Y being the
    // vsync timestamps, and X being the ordinal of vsync count.
    // The calculated slope is the vsync period.
    // Formula for reference:
    // Sigma_i: means sum over all timestamps.
    // mean(variable): statistical mean of variable.
    // X: snapped ordinal of the timestamp
    // Y: vsync timestamp
    //
    //         Sigma_i( (X_i - mean(X)) * (Y_i - mean(Y) )
    // slope = -------------------------------------------
    //         Sigma_i ( X_i - mean(X) ) ^ 2
    //
    // intercept = mean(Y) - slope * mean(X)
    //

    std::vector<nsecs_t> vsyncTS(numSamples)//搜集 Vsync 信号时间 y轴
    std::vector<nsecs_t> ordinals(numSamples)// 搜集 Vsycn 信号顺序 x轴

    // Normalizing to the oldest timestamp cuts down on error in calculating the intercept.
    const auto oldestTS = *std::min_element(mTimestamps.begin(), mTimestamps.end());
    auto it = mRateMap.find(mIdealPeriod);
    auto const currentPeriod = it->second.slope; // 默认值是 16.6,也就是 60hz

    // The mean of the ordinals must be precise for the intercept calculation, so scale them up for
    // fixed-point arithmetic.
    constexpr int64_t kScalingFactor = 1000;  // 顺序值相比时间值太小了,做发大处理,发大的倍数就是 1000

    nsecs_t meanTS = 0// Vsync 信号时间平均值
    nsecs_t meanOrdinal = 0// Vsync 信号顺序平均值

    for (size_t i = 0; i < numSamples; i++) {
        // 时间使用相对值
        const auto timestamp = mTimestamps[i] - oldestTS;
        vsyncTS[i] = timestamp;
        meanTS += timestamp;

        // 计算顺序的方法
        const auto ordinal = currentPeriod == 0
                ? 0
                : (vsyncTS[i] + currentPeriod / 2) / currentPeriod * kScalingFactor;
        ordinals[i] = ordinal;
        meanOrdinal += ordinal;
    }

    // 计算出平均值
    meanTS /= numSamples;  
    meanOrdinal /= numSamples;


    for (size_t i = 0; i < numSamples; i++) {
        vsyncTS[i] -= meanTS;
        ordinals[i] -= meanOrdinal;
    }

    nsecs_t top = 0;
    nsecs_t bottom = 0;
    for (size_t i = 0; i < numSamples; i++) {
        top += vsyncTS[i] * ordinals[i]; 
        bottom += ordinals[i] * ordinals[i];
    }

    if (CC_UNLIKELY(bottom == 0)) { // 特殊情况处理
        it->second = {mIdealPeriod, 0};
        clearTimestamps();
        return false;
    }

    nsecs_t const anticipatedPeriod = top * kScalingFactor / bottom;  //截距
    nsecs_t const intercept = meanTS - (anticipatedPeriod * meanOrdinal / kScalingFactor); // 斜率

    auto const percent = std::abs(anticipatedPeriod - mIdealPeriod) * kMaxPercent / mIdealPeriod;
    if (percent >= kOutlierTolerancePercent) {
        it->second = {mIdealPeriod, 0};
        clearTimestamps();
        return false;
    }

    traceInt64If("VSP-period", anticipatedPeriod);
    traceInt64If("VSP-intercept", intercept);

    // 计算出的结果保存在 mRateMap 中
    // anticipatedPeriod 就是 斜率
    // intercept 就是截距
    // 后续就可以根据这两个数据模拟出软件 VSync
    it->second = {anticipatedPeriod, intercept}; // 数据记录到 mRateMap 中

    ALOGV("model update ts %" PRIu64 ": %" PRId64 " slope: %" PRId64 " intercept: %" PRId64,
          mId.value, timestamp, anticipatedPeriod, intercept);
    return true;
}

函数的参数,也就是 Vsync 信号时间,会保存在 mTimestamps 中。

这里会根据硬件 Vysnc 计算出软件 Vysnc 的模型,使用的方法是 'simple linear regression',也就是简单线性回归。

工作几年后,我想大多数人都忘了,大一大二学习的数学知识了。这里我们就来回顾一下简单线性回归。

20240711112038

图片来自:https://www.bilibili.com/video/BV11Y4y1z7Ah/?spm_id_from=333.337.search-card.all.click&vd_source=dc959648d92fce190c8461996c134681

在当前的模型中,x 是 Vsync 信号的顺序值(1,2,3,4,5.....),y 是 Vsync 信号到来的时间。

通过简单线性回归的公式,就可以求出 y 与 x 之间的一元一次关系。

计算出的结果保存在 mRateMap 中,后续会根据这里的数据来模拟软件 Vysnc 信号。

// /frameworks/native/services/surfaceflinger/Scheduler/VSyncPredictor.h
    // Map between ideal vsync period and the calculated model
    std::unordered_map<nsecs_t, Model> mutable mRateMap GUARDED_BY(mMutex);

setPeriod 的实现:

void VSyncPredictor::setPeriod(nsecs_t period) {
    ATRACE_FORMAT("%s %s", __func__, to_string(mId).c_str());
    traceInt64("VSP-setPeriod", period);

    std::lock_guard lock(mMutex);
    static constexpr size_t kSizeLimit = 30;
    if (CC_UNLIKELY(mRateMap.size() == kSizeLimit)) {
        mRateMap.erase(mRateMap.begin());
    }

    mIdealPeriod = period;
    if (mRateMap.find(period) == mRateMap.end()) {
        mRateMap[mIdealPeriod] = {period, 0};
    }

    clearTimestamps();
}

也就是更新一下 mIdealPeriod 和 mRateMap 的值。

enableHardwareVsync 的实现如下:

void VsyncSchedule::enableHardwareVsync(ISchedulerCallback& callback) {
    std::lock_guard<std::mutex> lock(mHwVsyncLock);
    enableHardwareVsyncLocked(callback);
}
void VsyncSchedule::enableHardwareVsyncLocked(ISchedulerCallback& callback) {
    if (mHwVsyncState == HwVsyncState::Disabled) {
        getTracker().resetModel();
        callback.setVsyncEnabled(mId, true);
        mHwVsyncState = HwVsyncState::Enabled;
    }
}

disableHardwareVsync 实现如下:

void VsyncSchedule::disableHardwareVsync(ISchedulerCallback& callback, bool disallow) {
    std::lock_guard<std::mutex> lock(mHwVsyncLock);
    switch (mHwVsyncState) {
        case HwVsyncState::Enabled:
            callback.setVsyncEnabled(mId, false);
            [[fallthrough]];
        case HwVsyncState::Disabled:
            mHwVsyncState = disallow ? HwVsyncState::Disallowed : HwVsyncState::Disabled;
            break;
        case HwVsyncState::Disallowed:
            break;
    }
}

callback 就是前面传入的 mSchedulerCallback,该成员在 Scheduler 构造函数中初始化,实际类型是 SurfaceFlinger。

这里就会调用到 SurfaceFlinger 的 setVsyncEnabled 函数:

// /frameworks/native/services/surfaceflinger/SurfaceFlinger.cpp
void SurfaceFlinger::setVsyncEnabled(PhysicalDisplayId id, bool enabled) {
    const charconst whence = __func__;
    ATRACE_FORMAT("%s (%d) for %" PRIu64, whence, enabled, id.value);

    // On main thread to avoid race conditions with display power state.
    // 这个应该是发一个消息给 Looper
    static_cast<void>(mScheduler->schedule([=]() FTL_FAKE_GUARD(mStateLock) {
        {
            ftl::FakeGuard guard(kMainThreadContext);
            if (auto schedule = mScheduler->getVsyncSchedule(id)) {
                // 关注点2
                schedule->setPendingHardwareVsyncState(enabled);
            }
        }

        ATRACE_FORMAT("%s (%d) for %" PRIu64 " (main thread)", whence, enabled, id.value);
        if (const auto display = getDisplayDeviceLocked(id); display && display->isPoweredOn()) {
            // 关注点1
            setHWCVsyncEnabled(id, enabled);
        }
    }));
}

关注点 1:

// /frameworks/native/services/surfaceflinger/Scheduler/VsyncSchedule.cpp
    void setHWCVsyncEnabled(PhysicalDisplayId id, bool enabled) {
        hal::Vsync halState = enabled ? hal::Vsync::ENABLE : hal::Vsync::DISABLE;
        getHwComposer().setVsyncEnabled(id, halState);
    }

关注点 2:

// /frameworks/native/services/surfaceflinger/Scheduler/VsyncSchedule.cpp
void VsyncSchedule::setPendingHardwareVsyncState(bool enabled) {
    mPendingHwVsyncState = enabled ? HwVsyncState::Enabled : HwVsyncState::Disabled;
}

接着看 关注点3 modulateVsync 的实现:

// /frameworks/native/services/surfaceflinger/Scheduler/Scheduler.h
    template <typename... Args,
              typename Handler = std::optional<VsyncConfig> (VsyncModulator::*)(Args...)>
    void modulateVsync(std::optional<PhysicalDisplayId> id, Handler handler, Args... args) {
        if (id) {
            std::scoped_lock lock(mDisplayLock);
            ftl::FakeGuard guard(kMainThreadContext);
            if (id != mPacesetterDisplayId) {
                return;
            }
        }
        // handler 回调获取到 config
        if (const auto config = (*mVsyncModulator.*handler)(args...)) {
            setVsyncConfig(*config, getPacesetterVsyncPeriod());
        }
    }

handler 回调获取到 config,handler 实际类型是 VsyncModulator::onRefreshRateChangeCompleted:

// /frameworks/native/services/surfaceflinger/Scheduler/VsyncModulator.cpp
VsyncModulator::VsyncConfigOpt VsyncModulator::onRefreshRateChangeCompleted() {
    if (!mRefreshRateChangePending) return std::nullopt;
    mRefreshRateChangePending = false;
    return updateVsyncConfig();
}

VsyncConfig VsyncModulator::updateVsyncConfig() {
    std::lock_guard<std::mutex> lock(mMutex);
    return updateVsyncConfigLocked();
}

VsyncConfig VsyncModulator::updateVsyncConfigLocked() {
    const VsyncConfig& offsets = getNextVsyncConfig();
    mVsyncConfig = offsets;

    if (mTraceDetailedInfo) {
        const bool isEarly = &offsets == &mVsyncConfigSet.early;
        const bool isEarlyGpu = &offsets == &mVsyncConfigSet.earlyGpu;
        const bool isLate = &offsets == &mVsyncConfigSet.late;

        ATRACE_INT("Vsync-EarlyOffsetsOn", isEarly);
        ATRACE_INT("Vsync-EarlyGpuOffsetsOn", isEarlyGpu);
        ATRACE_INT("Vsync-LateOffsetsOn", isLate);
    }

    return offsets;
}

const VsyncConfig& VsyncModulator::getNextVsyncConfig() const {
    switch (getNextVsyncConfigType()) {
        case VsyncConfigType::Early:
            return mVsyncConfigSet.early;
        case VsyncConfigType::EarlyGpu:
            return mVsyncConfigSet.earlyGpu;
        case VsyncConfigType::Late:
            return mVsyncConfigSet.late;
    }
}

auto VsyncModulator::getNextVsyncConfigType() const -> VsyncConfigType {
    // Early offsets are used if we're in the middle of a refresh rate
    // change, or if we recently begin a transaction.
    if (!mEarlyWakeupRequests.empty() || mTransactionSchedule == Schedule::EarlyEnd ||
        mEarlyTransactionFrames > 0 || mRefreshRateChangePending) {
        return VsyncConfigType::Early;
    } else if (mEarlyGpuFrames > 0) {
        return VsyncConfigType::EarlyGpu;
    } else {
        return VsyncConfigType::Late;
    }
}

接着调用 setVsyncConfig

// /frameworks/native/services/surfaceflinger/Scheduler/Scheduler.cpp
void Scheduler::setVsyncConfig(const VsyncConfig& config, Period vsyncPeriod) {
    setDuration(mAppConnectionHandle,
                /* workDuration */ config.appWorkDuration,
                /* readyDuration */ config.sfWorkDuration);
    setDuration(mSfConnectionHandle,
                /* workDuration */ vsyncPeriod,
                /* readyDuration */ config.sfWorkDuration);
    setDuration(config.sfWorkDuration);
}

void Scheduler::setDuration(ConnectionHandle handle, std::chrono::nanoseconds workDuration,
                            std::chrono::nanoseconds readyDuration) 
{
    android::EventThread* thread;
    {
        std::lock_guard<std::mutex> lock(mConnectionsLock);
        RETURN_IF_INVALID_HANDLE(handle);
        thread = mConnections[handle].thread.get();
    }
    thread->setDuration(workDuration, readyDuration);
}

void EventThread::setDuration(std::chrono::nanoseconds workDuration,
                              std::chrono::nanoseconds readyDuration) 
{
    std::lock_guard<std::mutex> lock(mMutex);
    mWorkDuration = workDuration;
    mReadyDuration = readyDuration;

    mVsyncRegistration.update({.workDuration = mWorkDuration.get().count(),
                               .readyDuration = mReadyDuration.count(),
                               .earliestVsync = mLastVsyncCallbackTime.ns()});
}

modulateVsync 实际就是给 EventThread 配置 workDuration readyDuration 参数。这些参数会用于计算 软件 Vsync 信号。

总结一下,收到硬件 Vsync 后,就是做一些计算和配置

4VSYNC-app 的请求流程

应用端通过 Choreographer 向 SurfaceFlinger 请求一个 app-Vsync,首先会建立匿名 Binder 连接 EventThreadConnection,EventThreadConnection 是一个 binder 服务端对象,所有的 EventThreadConnection 都会保存在 EventThread 的 mDisplayEventConnections 成员中。当 App 需要绘制时,就会调用到 EventThreadConnection::requestNextVsync() 申请一个 VSync-app 信号。

// /frameworks/native/services/surfaceflinger/Scheduler/EventThread.cpp

binder::Status EventThreadConnection::requestNextVsync() {
    ATRACE_CALL();
    mEventThread->requestNextVsync(sp<EventThreadConnection>::fromExisting(this));
    return binder::Status::ok();
}

void EventThread::requestNextVsync(const sp<EventThreadConnection>& connection) {
    if (connection->resyncCallback) {
        connection->resyncCallback();
    }

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

    // 第一次请求的时候 connection->vsyncRequest == VSyncRequest::None,进入如下逻辑,使得该连接的 vsyncRequest = VSyncRequest::Single
    if (connection->vsyncRequest == VSyncRequest::None) {
        connection->vsyncRequest = VSyncRequest::Single;
        mCondition.notify_all();
    } else if (connection->vsyncRequest == VSyncRequest::SingleSuppressCallback) {
        connection->vsyncRequest = VSyncRequest::Single;
    }
}

目前相关变量的情况如下:

  • mPendingEvents.isEmpty() = true
  • mState = State::IDLE
  • connection->vsyncRequest = VSyncRequest::Single
std::deque<DisplayEventReceiver::Event> mPendingEvents GUARDED_BY(mMutex);

void EventThread::threadMain(std::unique_lock<std::mutex>& lock) {
    DisplayEventConsumers consumers;

    while (mState != State::Quit) {
        std::optional<DisplayEventReceiver::Event> event;

        // 取 event
        // mPendingEvents,存放着定时器唤醒后发给该EventThread的事件,
        // Determine next event to dispatch.
        if (!mPendingEvents.empty()) {
            event = mPendingEvents.front();
            mPendingEvents.pop_front();

            if (event->header.type == 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();
                }
            }
        }

        bool vsyncRequested = false;

        // 遍历所有连接
        // 找到 consumer
        // Find connections that should consume this event.
        auto it = mDisplayEventConnections.begin();
        while (it != mDisplayEventConnections.end()) {
            if (const auto connection = it->promote()) {
                if (event && shouldConsumeEvent(*event, connection)) {
                    consumers.push_back(connection);
                }

                vsyncRequested |= connection->vsyncRequest != VSyncRequest::None;

                ++it;
            } else {
                it = mDisplayEventConnections.erase(it);
            }
        }

        // 分发 event 给 consumer
        if (!consumers.empty()) {
            dispatchEvent(*event, consumers);
            consumers.clear();
        }

        if (mVSyncState && vsyncRequested) {
            mState = mVSyncState->synthetic ? State::SyntheticVSync : State::VSync;
        } else {
            ALOGW_IF(!mVSyncState, "Ignoring VSYNC request while display is disconnected");
            mState = State::Idle;
        }

        if (mState == State::VSync) {
            // 请求 VSync 信号
            // 实际就是向 mPendingEvents 添加 event
            const auto scheduleResult =
                    mVsyncRegistration.schedule({.workDuration = mWorkDuration.get().count(),
                                                 .readyDuration = mReadyDuration.count(),
                                                 .earliestVsync = mLastVsyncCallbackTime.ns()});
                                                 
            LOG_ALWAYS_FATAL_IF(!scheduleResult, "Error scheduling callback");
        } else {
            mVsyncRegistration.cancel();
        }

        if (!mPendingEvents.empty()) {
            continue;
        }
        
        // 等待 app 唤醒
        // 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);
                }

                LOG_FATAL_IF(!mVSyncState);
                const auto now = systemTime(SYSTEM_TIME_MONOTONIC);
                const auto deadlineTimestamp = now + timeout.count();
                const auto expectedVSyncTime = deadlineTimestamp + timeout.count();
                mPendingEvents.push_back(makeVSync(mVSyncState->displayId, now,
                                                   ++mVSyncState->count, expectedVSyncTime,
                                                   deadlineTimestamp));
            }
        }
    }
    // cancel any pending vsync event before exiting
    mVsyncRegistration.cancel();
}

调用 mVsyncRegistration.schedule 请求 VSync 信号。

// frameworks/native/services/surfaceflinger/Scheduler/VSyncDispatchTimerQueue.cpp
 
ScheduleResult VSyncCallbackRegistration::schedule(VSyncDispatch::ScheduleTiming scheduleTiming) {
    if (!mToken) {
        return std::nullopt;
    }
    return mDispatch->schedule(*mToken, scheduleTiming);
}
// /frameworks/native/services/surfaceflinger/Scheduler/VSyncDispatchTimerQueue.cpp
 
ScheduleResult VSyncDispatchTimerQueue::schedule(CallbackToken token,
                                                 ScheduleTiming scheduleTiming) 
{
    std::lock_guard lock(mMutex);
    return scheduleLocked(token, scheduleTiming);
}

ScheduleResult VSyncDispatchTimerQueue::scheduleLocked(CallbackToken token,
                                                       ScheduleTiming scheduleTiming) 
{
    auto it = mCallbacks.find(token);
    if (it == mCallbacks.end()) {
        return {};
    }
    auto& callback = it->second;
    auto const now = mTimeKeeper->now();
 
    /* If the timer thread will run soon, we'll apply this work update via the callback
     * timer recalculation to avoid cancelling a callback that is about to fire. */

    auto const rearmImminent = now > mIntendedWakeupTime;
    if (CC_UNLIKELY(rearmImminent)) {
        callback->addPendingWorkloadUpdate(scheduleTiming);
        return getExpectedCallbackTime(*mTracker, now, scheduleTiming);
    }
    
    // 关注点
    const ScheduleResult result = callback->schedule(scheduleTiming, *mTracker, now);
    if (!result.has_value()) {
        return {};
    }
 
    if (callback->wakeupTime() < mIntendedWakeupTime - mTimerSlack) {
        rearmTimerSkippingUpdateFor(now, it);
    }
 
    return result;
}

拿到回调对象 callback 然后调用 schedule。

callback 是什么时候初始化的呢?

在构建 EventThread 的时候,会初始化 mVsyncRegistration 成员。

// /frameworks/native/services/surfaceflinger/Scheduler/EventThread.cpp
EventThread::EventThread(const char* name, std::shared_ptr<scheduler::VsyncSchedule> vsyncSchedule,
                         android::frametimeline::TokenManager* tokenManager,
                         ThrottleVsyncCallback throttleVsyncCallback,
                         GetVsyncPeriodFunction getVsyncPeriodFunction,
                         std::chrono::nanoseconds workDuration,
                         std::chrono::nanoseconds readyDuration)
      : mThreadName(name),
        mVsyncTracer(base::StringPrintf("VSYNC-%s", name), 0),
        mWorkDuration(base::StringPrintf("VsyncWorkDuration-%s", name), workDuration),
        mReadyDuration(readyDuration),
        mVsyncSchedule(std::move(vsyncSchedule)),
        // 关注点 VSyncCallbackRegistration 初始化过程
        mVsyncRegistration(mVsyncSchedule->getDispatch(), createDispatchCallback(), name),
        mTokenManager(tokenManager),
        mThrottleVsyncCallback(std::move(throttleVsyncCallback)),
        mGetVsyncPeriodFunction(std::move(getVsyncPeriodFunction)) {
    LOG_ALWAYS_FATAL_IF(getVsyncPeriodFunction == nullptr,
            "getVsyncPeriodFunction must not be null");

    // 构建一个线程对象
    // 执行 threadMain 函数
    mThread = std::thread([this]() NO_THREAD_SAFETY_ANALYSIS {
        std::unique_lock<std::mutex> lock(mMutex);
        threadMain(lock);
    });

    pthread_setname_np(mThread.native_handle(), mThreadName);

    pid_t tid = pthread_gettid_np(mThread.native_handle());

    // Use SCHED_FIFO to minimize jitter
    constexpr int EVENT_THREAD_PRIORITY = 2;
    struct sched_param param = {0};
    param.sched_priority = EVENT_THREAD_PRIORITY;
    if (pthread_setschedparam(mThread.native_handle(), SCHED_FIFO, &param) != 0) {
        ALOGE("Couldn't set SCHED_FIFO for EventThread");
    }

    set_sched_policy(tid, SP_FOREGROUND);
}

这里会调用到 VsyncRegistration 的构造函数:

VSyncCallbackRegistration::VSyncCallbackRegistration(std::shared_ptr<VSyncDispatch> dispatch,
                                                     VSyncDispatch::Callback callback,
                                                     std::string callbackName)
      : mDispatch(std::move(dispatch)),
        mToken(mDispatch->registerCallback(std::move(callback), std::move(callbackName))) {}
// /frameworks/native/services/surfaceflinger/Scheduler/VSyncDispatchTimerQueue.cpp
VSyncDispatchTimerQueue::CallbackToken VSyncDispatchTimerQueue::registerCallback(
        Callback callback, std::string callbackName) 
{
    std::lock_guard lock(mMutex);
    return CallbackToken{
            mCallbacks
                    .emplace(++mCallbackToken,
                             std::make_shared<VSyncDispatchTimerQueueEntry>(std::move(callbackName),
                                                                            std::move(callback),
                                                                            mMinVsyncDistance))
                    .first->first};
}

这里把 callback 包装成 VSyncDispatchTimerQueueEntry,并添加到 mCallbacks 中。

callback 来自 createDispatchCallback 函数:

// /frameworks/native/services/surfaceflinger/Scheduler/EventThread.cpp
scheduler::VSyncDispatch::Callback EventThread::createDispatchCallback() {
    // 直接返回一个 lamda
    return [this](nsecs_t vsyncTime, nsecs_t wakeupTime, nsecs_t readyTime) {
        onVsync(vsyncTime, wakeupTime, readyTime);
    };
}

void EventThread::onVsync(nsecs_t vsyncTime, nsecs_t wakeupTime, nsecs_t readyTime) {
    std::lock_guard<std::mutex> lock(mMutex);
    mLastVsyncCallbackTime = TimePoint::fromNs(vsyncTime);

    LOG_FATAL_IF(!mVSyncState);
    mVsyncTracer = (mVsyncTracer + 1) % 2;
    // 构建一个 Event 并插入 mPendingEvents
    mPendingEvents.push_back(makeVSync(mVSyncState->displayId, wakeupTime, ++mVSyncState->count,
                                       vsyncTime, readyTime));
    mCondition.notify_all();
}

callback 的类型是 VSyncDispatchTimerQueueEntry,接着调用 callback 的 schedule 函数:

// /frameworks/native/services/surfaceflinger/Scheduler/VSyncDispatchTimerQueue.cpp
ScheduleResult VSyncDispatchTimerQueueEntry::schedule(VSyncDispatch::ScheduleTiming timing,
                                                      VSyncTracker& tracker, nsecs_t now) 
{
    // 计算出 now + timing.workDuration + timing.readyDuration 时间点开始的下一次硬件 Vsync 信号
    auto nextVsyncTime = tracker.nextAnticipatedVSyncTimeFrom(
            std::max(timing.earliestVsync, now + timing.workDuration + timing.readyDuration));
    
    // 计算出的软件 Vsync 时间点
    auto nextWakeupTime = nextVsyncTime - timing.workDuration - timing.readyDuration;
 
    bool const wouldSkipAVsyncTarget =
            mArmedInfo && (nextVsyncTime > (mArmedInfo->mActualVsyncTime + mMinVsyncDistance));
    bool const wouldSkipAWakeup =
            mArmedInfo && ((nextWakeupTime > (mArmedInfo->mActualWakeupTime + mMinVsyncDistance)));
    if (wouldSkipAVsyncTarget && wouldSkipAWakeup) {
        return getExpectedCallbackTime(nextVsyncTime, timing);
    }
 
    nextVsyncTime = adjustVsyncIfNeeded(tracker, nextVsyncTime);
    nextWakeupTime = nextVsyncTime - timing.workDuration - timing.readyDuration;
 
    auto const nextReadyTime = nextVsyncTime - timing.readyDuration;
    mScheduleTiming = timing;
    mArmedInfo = {nextWakeupTime, nextVsyncTime, nextReadyTime};
    return getExpectedCallbackTime(nextVsyncTime, timing);
}

这里就是计算下一次 VSync 的地方了。tracker 就是 VSyncPredictor,是计算 VSync 的核心类。

workduration 和 readyduration 在大多数情况下都是固定值,且对于 sync 计算来说是个固定值,是对于 app 和 sf 完成渲染和合成工作时间大概估计,vsync 时间点的计算和这两个值有关系。

如下图所示,是app-sync的时间点计算示意图:举例:app-sync:workduration:16.6ms readyduration: 15.6ms,那么 app-sync 的计算方式如下图所描述:

20240730222025

图片来自:https://blog.csdn.net/qq_41095045/article/details/136378829?spm=1001.2014.3001.5502

  • 假如应用在24.9ms时向surfaceflinger申请app-vsync信号
  • 在24.9ms基础上加上app-vsync的workduration和readyduration计算出时间点a
  • 找出a的下一个HW_VSYNC的时间点:81ms
  • 在a的的下一个HW_VSYNC的时间点上减去app-vsync的workduration和readyduration得到时间点b:48.8ms,改时间点就是未来app收到app-vsync的时间点
  • 计算出surfaceflinger申请app-vsync信号的到时间点b的时间差:23.9ms,并设置定时
  • 23.9m后app申请的app-vsync时间到,surfaceflinger向app发送app-vsync信号

以上演示的以 app-vsync 为例的 vsync 计算过程,appsf-vsync 和sf-vsync 的计算过程类似,不同的是appsf-vsync和sf-vsync的workduration,readyduration是不同的值,以使得信号之间保持一定的相位差。

在上面的 VSyncDispatchTimerQueue::scheduleLocked 中,schedule 计算完时间后,会调用 rearmTimerSkippingUpdateFor,而 rearmTimerSkippingUpdateFor 设置了一个 Alarm,定时执行 VSync 的回调:

void VSyncDispatchTimerQueue::rearmTimerSkippingUpdateFor(
        nsecs_t now, CallbackMap::iterator const& skipUpdateIt) 
{
        //...
        setTimer(*min, now);
        //...
}
 
void VSyncDispatchTimerQueue::setTimer(nsecs_t targetTime, nsecs_t /*now*/) {
    mIntendedWakeupTime = targetTime;
    // 定时回调 VSyncDispatchTimerQueue::timerCallback
    mTimeKeeper->alarmAt(std::bind(&VSyncDispatchTimerQueue::timerCallback, this),
                         mIntendedWakeupTime);
    mLastTimerSchedule = mTimeKeeper->now();
}

时间到了就会唤醒:

void VSyncDispatchTimerQueue::timerCallback() {
    struct Invocation {
        std::shared_ptr<VSyncDispatchTimerQueueEntry> callback;
        nsecs_t vsyncTimestamp;
        nsecs_t wakeupTimestamp;
        nsecs_t deadlineTimestamp;
    };
    std::vector<Invocation> invocations;
    {
        std::lock_guard lock(mMutex);
        auto const now = mTimeKeeper->now();
        mLastTimerCallback = now;
        for (auto it = mCallbacks.begin(); it != mCallbacks.end(); it++) { 
            // 遍历取出 callback
            auto& callback = it->second;
            auto const wakeupTime = callback->wakeupTime();
            if (!wakeupTime) {
                continue;
            }

            auto const readyTime = callback->readyTime();

            auto const lagAllowance = std::max(now - mIntendedWakeupTime, static_cast<nsecs_t>(0));
            if (*wakeupTime < mIntendedWakeupTime + mTimerSlack + lagAllowance) {
                callback->executing();
                // callback 包装到 Invocation 中
                invocations.emplace_back(Invocation{callback, *callback->lastExecutedVsyncTarget(),
                                                    *wakeupTime, *readyTime});
            }
        }

        mIntendedWakeupTime = kInvalidTime;
        rearmTimer(mTimeKeeper->now());
    }

    for (auto const& invocation : invocations) {
        // 回调
        invocation.callback->callback(invocation.vsyncTimestamp, invocation.wakeupTimestamp,
                                      invocation.deadlineTimestamp);
    }
}

这里的 callback 来自 createDispatchCallback 函数:

scheduler::VSyncDispatch::Callback EventThread::createDispatchCallback() {
    return [this](nsecs_t vsyncTime, nsecs_t wakeupTime, nsecs_t readyTime) {
        onVsync(vsyncTime, wakeupTime, readyTime);
    };
}

void EventThread::onVsync(nsecs_t vsyncTime, nsecs_t wakeupTime, nsecs_t readyTime) {
    std::lock_guard<std::mutex> lock(mMutex);
    mLastVsyncCallbackTime = TimePoint::fromNs(vsyncTime);
 
    LOG_FATAL_IF(!mVSyncState);
    mVsyncTracer = (mVsyncTracer + 1) % 2;
    // 构建一个 event 添加到 mPendingEvents 中
    mPendingEvents.push_back(makeVSync(mVSyncState->displayId, wakeupTime, ++mVSyncState->count,
                                    vsyncTime, readyTime));

    // 唤醒 EventThread
    mCondition.notify_all();
}
// /frameworks/native/services/surfaceflinger/Scheduler/EventThread.cpp
DisplayEventReceiver::Event makeVSync(PhysicalDisplayId displayId, nsecs_t timestamp,
                                      uint32_t count, nsecs_t expectedPresentationTime,
                                      nsecs_t deadlineTimestamp) 
{
    DisplayEventReceiver::Event event;
    event.header = {DisplayEventReceiver::DISPLAY_EVENT_VSYNC, displayId, timestamp};
    event.vsync.count = count;
    event.vsync.vsyncData.preferredFrameTimelineIndex = 0;
    // Temporarily store the current vsync information in frameTimelines[0], marked as
    // platform-preferred. When the event is dispatched later, the frame interval at that time is
    // used with this information to generate multiple frame timeline choices.
    event.vsync.vsyncData.frameTimelines[0] = {.vsyncId = FrameTimelineInfo::INVALID_VSYNC_ID,
                                               .deadlineTimestamp = deadlineTimestamp,
                                               .expectedPresentationTime =
                                                       expectedPresentationTime};
    return event;
}

Vsync 信号将会封装成 Event 放入 mPendingEvents,然后调用锁对象 mCondition 的 notify_all 通知其他wait 在这个锁对象的线程。

5VSYNC-app 的分发过程

EventThread 中的 threadmain 方法从 wait 中唤醒:

在之前的 threadMain 方法中,有代码:

if (!mPendingEvents.empty()) {
            event = mPendingEvents.front();
            mPendingEvents.pop_front();
 
            if (event->header.type == 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();
                }
            }
        }
...
if (!consumers.empty()) {
    dispatchEvent(*event, consumers);
    consumers.clear();
}

dispatchEvent 分发:

void EventThread::dispatchEvent(const DisplayEventReceiver::Event& event,
                                const DisplayEventConsumers& consumers) 
{
    for (const auto& consumer : consumers) {
        DisplayEventReceiver::Event copy = event;
        if (event.header.type == DisplayEventReceiver::DISPLAY_EVENT_VSYNC) {
            const int64_t frameInterval = mGetVsyncPeriodFunction(consumer->mOwnerUid);
            copy.vsync.vsyncData.frameInterval = frameInterval;
            generateFrameTimeline(copy.vsync.vsyncData, frameInterval, copy.header.timestamp,
                                  event.vsync.vsyncData.preferredExpectedPresentationTime(),
                                  event.vsync.vsyncData.preferredDeadlineTimestamp());
        }
        switch (consumer->postEvent(copy)) {
            case NO_ERROR:
                break;
 
            case -EAGAIN:
                // TODO: Try again if pipe is full.
                ALOGW("Failed dispatching %s for %s", toString(event).c_str(),
                      toString(*consumer).c_str());
                break;
 
            default:
                // Treat EPIPE and other errors as fatal.
                removeDisplayEventConnectionLocked(consumer);
        }
    }
}

这里的 consumer 为 EventThreadConnection:

// /frameworks/native/services/surfaceflinger/Scheduler/EventThread.cpp
 
status_t EventThreadConnection::postEvent(const DisplayEventReceiver::Event& event) {
    constexpr auto toStatus = [](ssize_t size) {
        return size < 0 ? status_t(size) : status_t(NO_ERROR);
    };
 
    if (event.header.type == DisplayEventReceiver::DISPLAY_EVENT_FRAME_RATE_OVERRIDE ||
        event.header.type == DisplayEventReceiver::DISPLAY_EVENT_FRAME_RATE_OVERRIDE_FLUSH) {
        mPendingEvents.emplace_back(event);
        if (event.header.type == DisplayEventReceiver::DISPLAY_EVENT_FRAME_RATE_OVERRIDE) {
            return status_t(NO_ERROR);
        }
 
        auto size = DisplayEventReceiver::sendEvents(&mChannel, mPendingEvents.data(),
                                                     mPendingEvents.size());
        mPendingEvents.clear();
        return toStatus(size);
    }
 
    auto size = DisplayEventReceiver::sendEvents(&mChannel, &event, 1);
    return toStatus(size);
}

DisplayEventReceiver::sendEvents 最终发给客户端:

ssize_t DisplayEventReceiver::sendEvents(gui::BitTube* dataChannel,
        Event const* events, size_t count)
{
    return gui::BitTube::sendObjects(dataChannel, events, count);
}

BitTube 通过 socket 将事件分发到客户端的 Choreographer。

6VSYNC-sf 的请求和分发

VSYNC-sf 初始化 MessageQueue::initVsync:

// /frameworks/native/services/surfaceflinger/Scheduler/MessageQueue.cpp
void MessageQueue::initVsync(std::shared_ptr<scheduler::VSyncDispatch> dispatch,
                             frametimeline::TokenManager& tokenManager,
                             std::chrono::nanoseconds workDuration) 
{
    std::unique_ptr<scheduler::VSyncCallbackRegistration> oldRegistration;
    {
        std::lock_guard lock(mVsync.mutex);
        mVsync.workDuration = workDuration;
        mVsync.tokenManager = &tokenManager;
        oldRegistration = onNewVsyncScheduleLocked(std::move(dispatch));
    }

    // See comments in onNewVsyncSchedule. Today, oldRegistration should be
    // empty, but nothing prevents us from calling initVsync multiple times, so
    // go ahead and destruct it outside the lock for safety.
    oldRegistration.reset();
}

接着调用 onNewVsyncScheduleLocked 函数:

// /frameworks/native/services/surfaceflinger/Scheduler/MessageQueue.cpp
 
std::unique_ptr<scheduler::VSyncCallbackRegistration> MessageQueue::onNewVsyncScheduleLocked(
        std::shared_ptr<scheduler::VSyncDispatch> dispatch) 
{
    const bool reschedule = mVsync.registration &&
            mVsync.registration->cancel() == scheduler::CancelResult::Cancelled;
    auto oldRegistration = std::move(mVsync.registration);
    mVsync.registration = std::make_unique<
            scheduler::VSyncCallbackRegistration>(std::move(dispatch),
                                                  std::bind(&MessageQueue::vsyncCallback, this,
                                                            std::placeholders::_1,
                                                            std::placeholders::_2,
                                                            std::placeholders::_3),
                                                  "sf");
    if (reschedule) {
        mVsync.scheduledFrameTime =
                mVsync.registration->schedule({.workDuration = mVsync.workDuration.get().count(),
                                               .readyDuration = 0,
                                               .earliestVsync = mVsync.lastCallbackTime.ns()});
    }
    return oldRegistration;
}

构建一个 VSyncCallbackRegistration 对象,VSyncCallbackRegistration 代表一个 VSync 使用者的注册。比如常见的针对上层应用的 VSYNC-app、针对 SurfaceFlinger 合成的VSYNC-sf,都对应一个 VSyncCallbackRegistration。另外在客户端,还有一个VSYNC-appSf。

当sf需要请求刷新时,会调用MessageQueue中的scheduleFrame函数

void MessageQueue::scheduleFrame() {
    ATRACE_CALL();

    std::lock_guard lock(mVsync.mutex);
    mVsync.scheduledFrameTime =
            mVsync.registration->schedule({.workDuration = mVsync.workDuration.get().count(),
                                           .readyDuration = 0,
                                           .earliestVsync = mVsync.lastCallbackTime.ns()});
}

计算过程都是和 app 一样的,最终的回调函数不一样,这里是 MessageQueue::vsyncCallback

// /frameworks/native/services/surfaceflinger/Scheduler/MessageQueue.cpp
 
void MessageQueue::vsyncCallback(nsecs_t vsyncTime, nsecs_t targetWakeupTime, nsecs_t readyTime) {
    ATRACE_CALL();
    // Trace VSYNC-sf
    mVsync.value = (mVsync.value + 1) % 2;
 
    const auto expectedVsyncTime = TimePoint::fromNs(vsyncTime);
    {
        std::lock_guard lock(mVsync.mutex);
        mVsync.lastCallbackTime = expectedVsyncTime;
        mVsync.scheduledFrameTime.reset();
    }
 
    const auto vsyncId = VsyncId{mVsync.tokenManager->generateTokenForPredictions(
            {targetWakeupTime, readyTime, vsyncTime})};
 
    mHandler->dispatchFrame(vsyncId, expectedVsyncTime);
}

MessageQueue本身是一个消息队列的实现类。这里看到收到VSync回调后,通过mHandler->dispatchFrame抛到队列里去了。最终会执行

// /frameworks/native/services/surfaceflinger/Scheduler/MessageQueue.cpp
 
void MessageQueue::Handler::handleMessage(const Message&) {
    mFramePending.store(false);
    mQueue.onFrameSignal(mQueue.mCompositor, mVsyncId, mExpectedVsyncTime);
}
// /frameworks/native/services/surfaceflinger/Scheduler/Scheduler.cpp
 
void Scheduler::onFrameSignal(ICompositor& compositor, VsyncId vsyncId,
                              TimePoint expectedVsyncTime) 
{
          // ...
          if (!compositor.commit(pacesetterId, targets)) return;
          // ...
          const auto resultsPerDisplay = compositor.composite(pacesetterId, targeters);
  }

这里的 compositor 是 SurfaceFlinger。接下来就是由 SF 进行合成工作了即执行 commit 和 composite 两个函数。

参考资料

一文搞定Android VSync机制来龙去脉Android 13 VSYNC重学习Andoid SurfaceFlinger(二) VSYNC的开始,连续,结束Andoid SurfaceFlinger(三) VSYNC的申请,生产,下发与校准Android 14 - 绘制体系 - 概览Android 14 - 绘制体系 - VSync(1)Android-View绘制原理(03)-Vsync原理之App篇Android-View绘制原理(02)-VSync原理之SurfaceFlinger篇一文带你看懂Vsync Phase


最后推荐一下我做的网站,玩Android: wanandroid.com ,包含详尽的知识体系、好用的工具,还有本公众号文章合集,欢迎体验和收藏!


扫一扫 关注我的公众号

如果你想要跟大家分享你的文章,欢迎投稿~


┏(^0^)┛明天见!

继续滑动看下一个
鸿洋
向上滑动看下一个

您可能也对以下帖子感兴趣

文章有问题?点此查看未经处理的缓存