android屏幕刷新之七

前言

在 native DisplayEventReceiver 通过 sp< IDisplayEventConnection > mEventConnection AIDL 获取 SurfaceFlinger 服务代理,调用 IDisplayEventConnection 的函数实现。而前文分析到 class EventThreadConnection : public gui::BnDisplayEventConnection 实现了IDisplayEventConnection 的接口函数。

因此,EventThreadConnection 就是此次学习的目标,鉴于EventThreadConnection 定义在 EventThread 又是 SurfaceFlinger 进程中运行的,这又和 通过 SurfaceFlinger 服务代理获取 mEventConnection 实例可以达成闭环。

EventThread 一个类对象,其中包含class EventThreadConnection、class EventThread类对象、class EventThread内部继承者。所以,本次将依据上面的几个部分进行分开整理。路径:frameworks/native/services/surfaceflinger/Scheduler。

1 EventThreadConnection

EventThreadConnection 表示一个客户端连接,通常是 Java 层的 DisplayEventReceiver 对应到 native 实现;每个连接都有独立的 BitTube 通信管道;提供事件接收与发送接口。

1.1 关系图谱

IDisplayEventConnection.aidl (Binder接口定义)
      │ AIDL 自动生成
      ▼
BnDisplayEventConnection(Binder服务端Stub)
      ▲
      │ 服务端实现代理对象
EventThreadConnection : public BnDisplayEventConnection
      │ 调用
      ▼
EventThread : public android::EventThread

在 DisplayEventReceiver 中,通过 ISurfaceComposer 获取 SurfaceFlinger 服务代理,通过 createDisplayEventConnection 拿到 IDisplayEventConnection代理,实际指向 EventThreadConnection。EventThreadConnection又操作 EventThread。由此,完成从AP进程——>SurfaceFlinger 进程。

1.2 头文件解析

EventThreadConnection 的头文件部分是定义在EventThread.h中的,源码如下:

class EventThreadConnection : public gui::BnDisplayEventConnection {
public:
    EventThreadConnection(EventThread*, uid_t callingUid, ResyncCallback,
                          EventRegistrationFlags eventRegistration = {});
    virtual ~EventThreadConnection();

    virtual status_t postEvent(const DisplayEventReceiver::Event& event);

    // binder 指向代理端的函数
    // -----------》 start
    binder::Status stealReceiveChannel(gui::BitTube* outChannel) override;
    binder::Status setVsyncRate(int rate) override;
    binder::Status requestNextVsync() override; // asynchronous
    binder::Status getLatestVsyncEventData(ParcelableVsyncEventData* outVsyncEventData) override;
    // -----------》 end

    // Called in response to requestNextVsync.
    const ResyncCallback resyncCallback;

    VSyncRequest vsyncRequest = VSyncRequest::None; // 枚举类型:VSyncRequest
    const uid_t mOwnerUid;
    const EventRegistrationFlags mEventRegistration;

    /** The frame rate set to the attached choreographer. */
    Fps frameRate;

private:
    virtual void onFirstRef();
    EventThread* const mEventThread; // EventThread 实例
    std::mutex mLock;
    gui::BitTube mChannel GUARDED_BY(mLock); // BitTube 管道

    std::vector<DisplayEventReceiver::Event> mPendingEvents;
};
  • EventThread* const mEventThread - 事件处理线程EventThread
  • gui::BitTube mChannel - 进程间通信的管道,这里用于surfaceFlinger -> native侧ap进程的通信
  • resyncCallback - 封装函数

1.3 核心函数

1.3.1 构造函数

EventThreadConnection 是每个应用与 SurfaceFlinger 中 EventThread 通信的表示单位,封装了 VSync 接收的上下文,包括接收通道、事件类型、所有者 UID 等。

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) {}

(1)参数解释

参数名类型说明
eventThreadEventThread*当前连接所属的 EventThread 对象,用于注册、唤醒等操作
callingUiduid_t创建该连接的调用者 UID,用于权限管理、节流等用途
resyncCallbackstd::function<void()>应用调用 requestNextVsync() 后触发的回调,用于同步状态
eventRegistrationEventRegistrationFlags表示当前连接注册的事件类型(VSync、Hotplug、ModeChange等)

(2)变量初始化

成员变量含义
resyncCallback保存请求 vsync 后的回调函数(通常用于触发后续调度)
mOwnerUid当前连接所属的 UID
mEventRegistration当前连接希望订阅的事件类型
mEventThread回指所属的 EventThread,用于注册请求、回调、事件发送等
mChannel使用 BitTube 创建通信通道(socketpair),与应用侧 DisplayEventReceiver 通信

(3)BitTube 的作用
mChannel(gui::BitTube::DefaultSize)

  • BitTube 是 Android native 层的一个轻量级 socket 封装类;
  • 底层使用 socketpair(AF_UNIX, SOCK_SEQPACKET) 创建;
  • 一端留在 SF 中用于 sendObject(),一端通过 stealReceiveChannel() 传递给应用;
  • 应用层的 DisplayEventReceiver 使用 read() 接收 VSync 事件。

1.3.2 关键方法

EventThreadConnection 负责维护 App 与 SurfaceFlinger 之间的一条 VSync 事件连接。主要作用包括:

方法名作用触发方
onFirstRef()注册到 EventThread 中构造后自动
stealReceiveChannel()把 BitTube fd 给 AppJava 初始化阶段
setVsyncRate()设置 VSync 频率Java 控制
requestNextVsync()请求下一帧的 VSyncApp 调用 Choreographer::doFrame()
getLatestVsyncEventData()获取最新 VSync 时间数据App 调用时
postEvent()将事件通过 BitTube 发送给应用EventThread 调用

(1) onFirstRef
调用 EventThreadConnection 的构造方法创建实例对象的时候,在 DisplayEventReceiver 头文件中可以看到成员变量 mEventConnection 是 sp<> 修饰的(如:sp< IDisplayEventConnection > mEventConnection),这是在 Android 中 Google 实现的一种强引用的智能指针,并且 EventThreadConnection 类的最顶层父类是 RefBase 类,因此在 EventThreadConnection 初始化后将自动回调其实现的 onFirstRef() 方法。

【注】使用 fromExisting(this) 把裸指针转成 sp< T >,是 RefBase 系对象的常见技巧。

void EventThreadConnection::onFirstRef() {
    // NOTE: mEventThread doesn't hold a strong reference on us
    // 将新构建的 EventThreadConnection 也就是把自己注册到 EventThread
    mEventThread->registerDisplayEventConnection(sp<EventThreadConnection>::fromExisting(this)); 
}

(2) stealReceiveChannel
DisplayEventReceiver初始化的时候会将 SurfaceFlinger 进程中服务端创建的 gui::BitTube 对象赋值给应用进程端空的 gui::BitTube 对象,建立 app 应用进程和 SurfaceFlinger 进程之间的通道。就是通过sp< IDisplayEventConnection > mEventConnection # stealReceiveChannel函数执行设置的,其方法实现则是在此处。

binder::Status EventThreadConnection::stealReceiveChannel(gui::BitTube* outChannel) {
    std::scoped_lock lock(mLock);
    if (mChannel.initCheck() != NO_ERROR) {
        return binder::Status::fromStatusT(NAME_NOT_FOUND);
    }

    outChannel->setReceiveFd(mChannel.moveReceiveFd()); // 获取服务端gui::BitTube对象的文件描述mReceiveFd,设置到应用进程端
    outChannel->setSendFd(base::unique_fd(dup(mChannel.getSendFd()))); // 获取服务端gui::BitTube对象的文件描述mSendFd,设置到应用进程端
    return binder::Status::ok();
}

(3) setVsyncRate
设置当前连接所需的 VSync 频率(0 表示关闭、1 表示每帧触发、n 表示每 n 帧触发一次)。本质上是控制 EventThread 是否定期向该连接分发 VSync 事件。

binder::Status EventThreadConnection::setVsyncRate(int rate) {
    mEventThread->setVsyncRate(static_cast<uint32_t>(rate),
                               sp<EventThreadConnection>::fromExisting(this));
    return binder::Status::ok();
}

(4) requestNextVsync
应用调用 Choreographer::postCallback 时最终会走到这里,发起一次「异步的单次 VSync 请求」。

binder::Status EventThreadConnection::requestNextVsync() {
    ATRACE_CALL();
    mEventThread->requestNextVsync(sp<EventThreadConnection>::fromExisting(this)); // 调用 EventThread 的 requestNextVsync() 请求 VSync 信号
    return binder::Status::ok();
}

(5) postEvent
将事件通过 BitTube 发送给应用。由 EventThread 调用,用于将一个 VSync/Hotplug/ModeChange 等事件通过 BitTube 写入给对应应用。对于 FrameRateOverride 类型的事件,会临时缓存在 mPendingEvents 中直到 flush。

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);
}

1.4 VSyncRequest

描述客户端请求 VSync 的方式:

  • None:当前无请求;
  • Single:一次性唤醒,通常用于 scheduleVsync();
  • Periodic:周期性 VSync;

后续值用于自定义周期控制。

enum class VSyncRequest {
    None = -2,  // 初始值;表示当前没有 VSync 请求
    // Single wakes up for the next two frames to avoid scheduler overhead
    Single = -1,  // 接下来的两帧中单独唤醒,以避免调度程序开销太大;表示这是一次性 VSync 请求(请求一次,接收一次)
    // SingleSuppressCallback only wakes up for the next frame
    SingleSuppressCallback = 0,
    Periodic = 1,  // 后续请求的是周期性信号;表示是周期性 VSync 请求(请求一次可以一直接收)
    // Subsequent values are periods.
};

2 EventThread定义

EventThread 负责接收来自 硬件 VSync 信号调度器(VsyncSchedule) 的回调,然后遍历它所管理的多个 EventThreadConnection(一个 App 对应一个),根据 App 的设置(如是否启用、频率等)决定是否通过 BitTube 投递事件。

2.1 EventThread 类继承关系

EventThread头文件中可以看到 class EventThread : public android::EventThread,在内部分别定义两个EventThread对象,其中一个为抽象类,内部定义虚函数,命名空间为android;另一个EventThread 对象继承前述抽象类,实现其虚函数,命名空间为impl。实际上是一个 Android 自己的类,定义在同一目录下,非 POSIX 的线程类。主逻辑通过 std::thread mThread 来调度。两个namespace关系如下:

namespace android {
    class EventThread ...
    namespace impl {
        class EventThread : public android::EventThread ...
    }
}

故而,在实现逻辑定义时显示指明android::EventThread。删减后源码如下:

class EventThread {
public:
    virtual ~EventThread();

    virtual sp<EventThreadConnection> createEventConnection(
            ResyncCallback, EventRegistrationFlags eventRegistration = {}) const = 0;
    // ... 省略
    virtual void onNewVsyncSchedule(std::shared_ptr<scheduler::VsyncSchedule>) = 0;
};

2.2 EventThread 定义

EventThread 内部类定义的删减源码如下:

class EventThread : public android::EventThread {
public:
    // 内部类型别名
    using ThrottleVsyncCallback = std::function<bool(nsecs_t, uid_t)>; // 用于动态节流(如后台 App 降低 VSync 频率)
    using GetVsyncPeriodFunction = std::function<nsecs_t(uid_t)>; // 用于查询指定 UID 的期望 VSync 周期
    // ... 省略override函数定义
private:
    friend EventThreadTest;

    // 当前事件线程负责的所有连接列表(一个连接对应一个 App)
    using DisplayEventConsumers = std::vector<sp<EventThreadConnection>>;

    // 构建传入给 VSyncDispatch 的回调函数,用于注册 EventThread 的处理逻辑(vsync 到来时触发该 callback)
    scheduler::VSyncDispatch::Callback createDispatchCallback();

    // Returns the old registration so it can be destructed outside the lock to
    // avoid deadlock.
    scheduler::VSyncCallbackRegistration onNewVsyncScheduleInternal(
            std::shared_ptr<scheduler::VsyncSchedule>) EXCLUDES(mMutex);

    const char* const mThreadName;
    TracedOrdinal<int> mVsyncTracer;
    TracedOrdinal<std::chrono::nanoseconds> mWorkDuration GUARDED_BY(mMutex);
    std::chrono::nanoseconds mReadyDuration GUARDED_BY(mMutex);
    // mVsyncSchedule 表示当前线程监听的 VSync 信号源
    std::shared_ptr<scheduler::VsyncSchedule> mVsyncSchedule GUARDED_BY(mMutex);
    //
    TimePoint mLastVsyncCallbackTime GUARDED_BY(mMutex) = TimePoint::now();
    // mVsyncRegistration 是注册后的回调绑定
    scheduler::VSyncCallbackRegistration mVsyncRegistration GUARDED_BY(mMutex);
    
    frametimeline::TokenManager* const mTokenManager;

    const ThrottleVsyncCallback mThrottleVsyncCallback;
    const GetVsyncPeriodFunction mGetVsyncPeriodFunction;

    std::thread mThread; // 子线程: 真正处理 VSync 消息分发的主循环线程
    // mMutex & mCondition : 线程的休眠与唤醒控制
    mutable std::mutex mMutex;
    mutable std::condition_variable mCondition;

    // App 在初始化 DisplayEventReceiver 时,会创建一个 EventThreadConnection,通过 registerDisplayEventConnection 注册到这里
    std::vector<wp<EventThreadConnection>> mDisplayEventConnections GUARDED_BY(mMutex);
    // 当前待投递的事件队列,由 VSync 驱动后填入
    std::deque<DisplayEventReceiver::Event> mPendingEvents GUARDED_BY(mMutex);

    // VSYNC state of connected display.
    struct VSyncState {
        explicit VSyncState(PhysicalDisplayId displayId) : displayId(displayId) {}

        const PhysicalDisplayId displayId; // 当前物理显示设备 ID

        // Number of VSYNC events since display was connected.
        uint32_t count = 0; // VSync 计数

        // True if VSYNC should be faked, e.g. when display is off.
        bool synthetic = false; // 是否使用 fake VSync(如屏幕关闭时模拟)等信息
    };

    // TODO(b/74619554): Create per-display threads waiting on respective VSYNC signals,
    // and support headless mode by injecting a fake display with synthetic VSYNC.
    // 记录当前物理显示设备 ID、VSync 计数、是否使用 fake VSync(如屏幕关闭时模拟)等信息。
    std::optional<VSyncState> mVSyncState GUARDED_BY(mMutex);

    // State machine for event loop.
    enum class State {
        Idle, // 等待唤醒
        Quit, // 线程即将退出
        SyntheticVSync, // 通过定时器模拟 VSync(屏幕关闭时)
        VSync, // 正常 VSync 到来
    };

    State mState GUARDED_BY(mMutex) = State::Idle;

    static const char* toCString(State);
};

3 EventThread 初始化

3.1 构造函数

源码如下

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), // tracing 标签,供调试时识别
        mWorkDuration(base::StringPrintf("VsyncWorkDuration-%s", name), workDuration), // 初始化 work 时间
        mReadyDuration(readyDuration), // 初始化 ready 时间
        mVsyncSchedule(std::move(vsyncSchedule)), // 提供 VSync 信号的调度器
        
        //step 1: mVsyncSchedule->getDispatch() 获取当前使用的 VSync 分发器(可以是硬件,也可以是模拟的)。
        //step 2: createDispatchCallback() 创建一个绑定到该线程的 callback 函数。
        //step 3: mVsyncRegistration 会自动将 callback 注册进 VSync 调度器中。
        //step 4: 当 VSync 信号产生时,这个 callback 就会被触发,从而启动事件分发。
        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);
    });

    // 设置线程名,如 "Vsync-app",便于 systrace、调试定位
    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;
    // 设置线程调度优先级: 使用 实时调度策略 SCHED_FIFO,减少 jitter。优先级设置为 2。
    if (pthread_setschedparam(mThread.native_handle(), SCHED_FIFO, &param) != 0) {
        ALOGE("Couldn't set SCHED_FIFO for EventThread");
    }

    // 设置线程调度策略
    set_sched_policy(tid, SP_FOREGROUND);
}

参数说明

参数含义
name线程名(如 "app", "sf"
vsyncSchedule提供 VSync 信号的调度器(底层来自 HWComposer 或模拟)
tokenManager传入给 FrameTimeline 使用(用于帧同步调试)
throttleVsyncCallback可用于控制某些 app 是否限制帧率
getVsyncPeriodFunction查询当前应用的 VSync 周期函数
workDuration预计一帧处理逻辑所需时间
readyDuration预计从准备好到真正投递事件的时间

3.2 DisplayEventReceiver::Event 对象创建

在DisplayEventReceiver的头文件定义了 struct Event 结构体。

        union {
            VSync vsync;
            Hotplug hotplug;
            ModeChange modeChange;
            FrameRateOverride frameRateOverride;
        };

在 EventThread 创建 Event 各种类型的对象,并针对上述不同的属性进行赋值。定义 makeXxx 函数封装了不同类型的 DisplayEventReceiver::Event 创建逻辑,用于构造:

函数名创建的事件类型用途
makeHotplugDISPLAY_EVENT_HOTPLUG屏幕连接/断开通知
makeVSyncDISPLAY_EVENT_VSYNCVSync 信号事件(核心)
makeModeChangedDISPLAY_EVENT_MODE_CHANGE分辨率/刷新率模式变更
makeFrameRateOverrideEventDISPLAY_EVENT_FRAME_RATE_OVERRIDEFrameRate 覆盖策略事件
makeFrameRateOverrideFlushEventDISPLAY_EVENT_FRAME_RATE_OVERRIDE_FLUSH上述事件清空标记

源码如下:

DisplayEventReceiver::Event makeHotplug(PhysicalDisplayId displayId, nsecs_t timestamp,
                                        bool connected) {
    DisplayEventReceiver::Event event;
    event.header = {DisplayEventReceiver::DISPLAY_EVENT_HOTPLUG, displayId, timestamp};
    event.hotplug.connected = connected;
    return event;
}

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;
}

DisplayEventReceiver::Event makeModeChanged(const scheduler::FrameRateMode& mode) {
    DisplayEventReceiver::Event event;
    event.header = {DisplayEventReceiver::DISPLAY_EVENT_MODE_CHANGE,
                    mode.modePtr->getPhysicalDisplayId(), systemTime()};
    event.modeChange.modeId = mode.modePtr->getId().value();
    event.modeChange.vsyncPeriod = mode.fps.getPeriodNsecs();
    return event;
}

DisplayEventReceiver::Event makeFrameRateOverrideEvent(PhysicalDisplayId displayId,
                                                       FrameRateOverride frameRateOverride) {
    return DisplayEventReceiver::Event{
            .header =
                    DisplayEventReceiver::Event::Header{
                            .type = DisplayEventReceiver::DISPLAY_EVENT_FRAME_RATE_OVERRIDE,
                            .displayId = displayId,
                            .timestamp = systemTime(),
                    },
            .frameRateOverride = frameRateOverride,
    };
}

DisplayEventReceiver::Event makeFrameRateOverrideFlushEvent(PhysicalDisplayId displayId) {
    return DisplayEventReceiver::Event{
            .header = DisplayEventReceiver::Event::Header{
                    .type = DisplayEventReceiver::DISPLAY_EVENT_FRAME_RATE_OVERRIDE_FLUSH,
                    .displayId = displayId,
                    .timestamp = systemTime(),
            }};
}

(1)DisplayEventReceiver::Event makeVSync(…)
构造一个 VSYNC 信号事件,是 EventThread 分发到 app 的最常见类型。

event.header = {
    DisplayEventReceiver::DISPLAY_EVENT_VSYNC,
    displayId,
    timestamp
};
event.vsync.count = count;
event.vsync.vsyncData.frameTimelines[0] = {
    .vsyncId = FrameTimelineInfo::INVALID_VSYNC_ID,
    .deadlineTimestamp = deadline,
    .expectedPresentationTime = expectedTime
};
  • timestamp: 当前 VSync 到达时间
  • count: 自上次连接以来 VSYNC 累加计数
  • frameTimelines[0]: 当前帧的预计 deadline 和呈现时间

注意:它只是初始化 frameTimelines[0],真正填满多个 timeline 是在发送前动态完成的(由 FrameTimeline 模块处理)。

(2)DisplayEventReceiver::Event makeHotplug(…)
构建连接/断开显示器的事件:

event.header = {
    DisplayEventReceiver::DISPLAY_EVENT_HOTPLUG,
    displayId,
    timestamp
};
event.hotplug.connected = true / false;

会触发应用层 SurfaceView、GLSurfaceView 或 InputManager 做响应。

(3)DisplayEventReceiver::Event makeModeChanged(…)
用于分辨率或帧率模式变更:

event.header = {DISPLAY_EVENT_MODE_CHANGE, displayId, now};
event.modeChange.modeId = modeId;
event.modeChange.vsyncPeriod = newPeriod;

这种事件一般在:

  • 动态切换刷新率(如 60Hz ↔ 120Hz)
  • 连接 HDR 显示器自动调整模式时出现

4 关键函数

4.1 createEventConnection

创建并返回一个新的 EventThreadConnection 实例,用于客户端(如 SurfaceFlinger 的 binder 调用者,例如应用进程)注册和接收 VSYNC 等显示相关事件。

sp<EventThreadConnection> EventThread::createEventConnection(
        ResyncCallback resyncCallback, EventRegistrationFlags eventRegistration) const {
    return sp<EventThreadConnection>::make(const_cast<EventThread*>(this), // 指向当前 EventThread 的裸指针
                                           IPCThreadState::self()->getCallingUid(), // 获取调用者的 UID
                                           std::move(resyncCallback), // 移交回调函数
                                           eventRegistration); // 注册标志
}

参数说明

  • ResyncCallback - 回调函数,用于需要重新同步(resync)时调用。
  • EventRegistrationFlags - 枚举值,表示客户端希望接收的事件类型(如 VSYNC、HOTPLUG 等)。
  • const - 表示该函数不会修改 EventThread 本身的状态。

sp< EventThreadConnection >::make

参数含义
this当前 EventThread,用于 EventThreadConnection 和其建立联系
getCallingUid()获取当前 Binder 请求调用方的 UID(用于权限控制和节流)
resyncCallback当事件队列卡顿等需要重同步时调用的回调
eventRegistration表示希望注册哪些事件类型(例如 VSYNC)

调用链简图

SurfaceFlinger::createDisplayEventConnection()EventThread::createEventConnection()new EventThreadConnection(...)onFirstRef()EventThread::registerDisplayEventConnection(...) → 
          mDisplayEventConnections.push_back(...)

4.2 setVsyncRate

设置指定连接的 VSYNC 接收频率(即每 rate 次 VSYNC 接收一次),并在改变时唤醒 EventThread 的主循环以重新评估事件派发。

参数含义
rate0 表示不接收 VSYNC,1 表示每帧接收,>1 表示跳帧模式
connection目标连接对象,代表某个监听显示事件的客户端
binder::Status EventThreadConnection::setVsyncRate(int rate) {
    mEventThread->setVsyncRate(static_cast<uint32_t>(rate),
                               sp<EventThreadConnection>::fromExisting(this));
    return binder::Status::ok();
}

void EventThread::setVsyncRate(uint32_t rate, const sp<EventThreadConnection>& connection) {
    if (static_cast<std::underlying_type_t<VSyncRequest>>(rate) < 0) {
        return;
    }

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

    // 映射成内部定义的枚举类型 VSyncRequest(代表 "不接收" / "每 1 帧接收一次" / "每 n 帧接收一次")
    const auto request = rate == 0 ? VSyncRequest::None : static_cast<VSyncRequest>(rate);
    // 果请求频率有变,更新 vsyncRequest
    if (connection->vsyncRequest != request) {
        connection->vsyncRequest = request;
        mCondition.notify_all(); // 唤醒 EventThread::threadMain(...) 中阻塞等待的线程
    }
}

4.3 requestNextVsync

用于实现 客户端单次请求下一次 VSYNC 信号 的功能。让某个连接(通常是 APP 的 DisplayEventReceiver)请求下一次 VSYNC 信号:

  • 如果当前未请求 VSYNC,则切换到“单次请求”状态;
  • 如果是 suppress 模式,也恢复为正常请求;
  • 同时调用 resyncCallback() 做一些状态同步(比如通知 Choreographer 重新对齐)。
void EventThread::requestNextVsync(const sp<EventThreadConnection>& connection) {
    if (connection->resyncCallback) {
        connection->resyncCallback(); // 一个来自客户端的回调,通常传入自定义函数(如 Choreographer::resyncToVsync())。用于在重新请求 Vsync 时进行 帧同步、调度准备 的动作
    }

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

    // 如果之前根本没有监听 VSYNC(即 None),那么改为监听下 一帧(Single)
    if (connection->vsyncRequest == VSyncRequest::None) {
        connection->vsyncRequest = VSyncRequest::Single;
        mCondition.notify_all(); // 通过 notify_all() 唤醒主线程 threadMain(),使其处理一次 dispatch
    } else if (connection->vsyncRequest == VSyncRequest::SingleSuppressCallback) {
        // 如果之前是特殊状态 SingleSuppressCallback(即:下一帧监听但 suppress 了回调),现在改为 真正要处理的单帧监听
        connection->vsyncRequest = VSyncRequest::Single;
    }
}

4.4 onVsync

EventThread::onVsync(…) 是 SurfaceFlinger 中 EventThread 收到 VSYNC 信号时的响应函数,其主要职责是:

  • 记录收到的 VSYNC 时间戳;
  • 构造 VSYNC 事件(DisplayEventReceiver::Event);
  • 推入等待分发的事件队列 mPendingEvents;
  • 唤醒线程主循环 threadMain() 进行事件分发。
void EventThread::onVsync(nsecs_t vsyncTime, nsecs_t wakeupTime, nsecs_t readyTime) {
    std::lock_guard<std::mutex> lock(mMutex);
    mLastVsyncCallbackTime = TimePoint::fromNs(vsyncTime); // 记录收到 Vsync 的时间

    // 安全检查:是否设置过 VSyncState
    LOG_FATAL_IF(!mVSyncState);
    mVsyncTracer = (mVsyncTracer + 1) % 2;
    // 生成 VSYNC 事件
    mPendingEvents.push_back(makeVSync(mVSyncState->displayId, wakeupTime, ++mVSyncState->count,
                                       vsyncTime, readyTime));
    mCondition.notify_all(); // 唤醒主线程处理分发任务
}

参数说明

参数含义
vsyncTime硬件发出的 Vsync 时间(理想的呈现时间)
wakeupTime本次 wakeup 时间,用于唤醒线程准备
readyTime应该准备好渲染输出的时间 deadline

4.5 onModeChanged

EventThread::onModeChanged() 是 SurfaceFlinger 中处理显示刷新率模式(FrameRateMode)变化的关键回调函数之一。当 显示设备切换刷新率(如 60Hz → 90Hz) 时,这个函数会被调用,将变化事件封装并推入事件队列,等待 EventThread 主循环处理并分发到应用进程。

void EventThread::onModeChanged(const scheduler::FrameRateMode& mode) {
    std::lock_guard<std::mutex> lock(mMutex);

    // 构造刷新率变化事件
    mPendingEvents.push_back(makeModeChanged(mode)); // 引用 DisplayEventReceiver::Event makeModeChanged
    mCondition.notify_all(); // 通知 threadMain() 主线程唤醒
}

4.6 threadMain

EventThread::threadMain() 是 SurfaceFlinger 中 事件分发线程的主循环函数,负责:

  • 分发各种事件(VSync、Hotplug、ModeChanged…)给应用;
  • 管理连接的客户端;
  • 控制 VSyncDispatch 的调度(包括 VSYNC 注册和取消);
  • 处理显示断开和驱动卡顿时的容错机制(如合成 vsync)。

4.6.1 结构概览

while (mState != State::Quit) {
    ① 从 mPendingEvents 中取出事件
    ② 处理 HOTPLUG 事件 → 更新 mVSyncState
    ③ 查找有效连接 → 确定哪些 connection 需要消费该事件
    ④ 分发事件
    ⑤ 决定下一状态:VSync / SyntheticVSync / Idle
    ⑥ schedule or cancel vsync callback
    ⑦ 等待下一轮事件 or VSync 信号(带超时)
}

4.6.2 源码分析

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

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

        // Determine next event to dispatch.
        // 处理事件队列:mPendingEvents
        if (!mPendingEvents.empty()) {
            event = mPendingEvents.front(); // 从 mPendingEvents 事件队列中提取首个事件
            mPendingEvents.pop_front();

            // 特殊处理 HOTPLUG 事件
            if (event->header.type == DisplayEventReceiver::DISPLAY_EVENT_HOTPLUG) {
                if (event->hotplug.connected && !mVSyncState) {
                    mVSyncState.emplace(event->header.displayId); // 新建 VSYNC 状态
                } else if (!event->hotplug.connected && mVSyncState &&
                           mVSyncState->displayId == event->header.displayId) {
                    mVSyncState.reset(); // 显示断开,取消状态
                }
            }
        }

        bool vsyncRequested = false;

        // Find connections that should consume this event.
        auto it = mDisplayEventConnections.begin();
        while (it != mDisplayEventConnections.end()) {
            if (const auto connection = it->promote()) {
                // 找到需要接收事件的连接(connection)
                if (event && shouldConsumeEvent(*event, connection)) {
                    consumers.push_back(connection);
                }

                // 失效的连接(weak_ptr promote 失败)会从 mDisplayEventConnections 中移除
                vsyncRequested |= connection->vsyncRequest != VSyncRequest::None;

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

        if (!consumers.empty()) {
            dispatchEvent(*event, consumers); // 分发事件, 应用通过 DisplayEventReceiver.getEvents() 获取。
            consumers.clear();
        }

        // 计算是否需要调度 VSYNC
        if (mVSyncState && vsyncRequested) {
            // 若该显示是 "synthetic"(模拟)模式,则进入合成 VSync 模式
            mState = mVSyncState->synthetic ? State::SyntheticVSync : State::VSync;
        } else {
            ALOGW_IF(!mVSyncState, "Ignoring VSYNC request while display is disconnected");
            // 否则进入 Idle
            mState = State::Idle;
        }

        // 调度/取消 VSync 回调
        if (mState == State::VSync) {
            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();
        }

        // 等待下一事件 or 超时生成 fake VSYNC
        if (!mPendingEvents.empty()) {
            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.
            // 若超时,说明驱动卡顿了(可能没有送出 VSYNC)
            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();
                // 生成 fake VSYNC
                mPendingEvents.push_back(makeVSync(mVSyncState->displayId, now,
                                                   ++mVSyncState->count, expectedVSyncTime,
                                                   deadlineTimestamp));
            }
        }
    }
    // cancel any pending vsync event before exiting
    mVsyncRegistration.cancel();
}

函数执行过程
-> 声明即将消费事件的 connection 集合:DisplayEventConsumers consumers

-> 构建死循环,状态值不等于 State::Quit 则一直循环遍历

-> 通过mPendingEvents.empty()函数判断下一个要调度的 Event

-> 获取头部 Event:event = mPendingEvents.front(),将其存储在event对象中

-> 将头部 Event 弹出:mPendingEvents.pop_front()

-> 根据 Event 类型分别对应处理:主要分类为DisplayEventReceiver::DISPLAY_EVENT_HOTPLUG和DisplayEventReceiver::DISPLAY_EVENT_VSYNC,Event 类型为 DISPLAY_EVENT_VSYNC 即 VSync 信号

-> 在DISPLAY_EVENT_VSYNC事件中,mInterceptVSyncsCallback 不为空则执行 VSync 回调,传入事件的时间戳

-> 声明标志位:是否有 VSync 请求,默认 false

-> 循环遍历存储 EventThreadConnection 的 vector 容器 mDisplayEventConnections,查找要消费事件的连接,

-> 通过begin()函数用于返回指向向量容器的第一个元素的迭代器:auto it = mDisplayEventConnections.begin()

-> 构建while循环,it != mDisplayEventConnections.end()作为执行条件,在mDisplayEventConnections遍历完成时退出

-> 判断 const auto connection = it->promote(),获取一个mDisplayEventConnections对象,通过it->promote()获取到EventThreadConnection强引用对象。后续备注promote用法

-> 如果有一个 connection 的 vsyncRequest 不为 None 则 vsyncRequested 为 true:vsyncRequested |= connection->vsyncRequest != VSyncRequest::None

-> 通过判断 event 是否为空以及 shouldConsumeEvent() 是否返回 true 则将 connection 加入到 consumers 等待消费 event:consumers.push_back(connection)

-> 对于 shouldConsumeEvent() 方法作用:对于 VSync 类型的事件,只要 VSyncRequest 的类型不是 None 就返回 true

-> 如果获取不到 connection,则将迭代器中获取的it对象从 mDisplayEventConnections 移除:it = mDisplayEventConnections.erase(it)

-> 在上述mDisplayEventConnections遍历完成后,如果 consumers 不为空,即当前 Event 有 EventThreadConnection 来消费,去执行消费事件处理

-> 调用 dispatchEvent() 方法遍历 consumers 为其每个 EventThreadConnection 分发事件:dispatchEvent(*event, consumers)

-> 分发完清空:consumers.clear()

-> 声明State nextState,保存下一个状态值

-> 判断if (mVSyncState && vsyncRequested),来确认当前是否有 VSync 请求

-> 屏幕亮屏时 synthetic 为 false,打开硬件 VSync,分发 VSync;熄屏时为 true,关闭硬件 VSync,停止分发 VSync

-> 根据mVSyncState->synthetic的值,更新 nextState = mVSyncState->synthetic ? State::SyntheticVSync : State::VSync

-> 如果显示器熄屏或没有连接、忽略 VSync 请求,即上述判断结果为假:nextState = State::Idle,直接将nextState设置为Idle状态

-> 判断mState与 nextState 不一致,mState 值默认为 State::Idle:if (mState != nextState),要区分判定执行逻辑

-> if (mState == State::VSync) 当前状态为 State::VSync,则调用 mVSyncSource 的 setVSyncEnabled 并传入 false:mVSyncSource->setVSyncEnabled(false)

-> if (nextState == State::VSync) nextState 状态为 State::VSync,则调用 mVSyncSource 的 setVSyncEnabled 并传入 true:mVSyncSource->setVSyncEnabled(true)

-> 经过上述两个处理步骤,mState与 nextState 不一致的情况消除,同步状态mState = nextState

-> 后续如果继续存在event事件则继续循环遍历:if (event) { continue; }

-> 如果没有事件且当前状态为:State::Idle,则线程继续等待事件或客户端注册/请求

-> 如果 mState == State::Idle,则执行 mCondition.wait(lock) 进入等待

-> 如果为非Idle状态,为防止驱动程序停止,这种情况是硬件不知什么原因没有发送 VSync 上来,需要伪造 VSync 信号,频率为熄屏时 16ms,亮屏时 1000ms

-> 根据mState == State::SyntheticVSync这个条件选择频率:std::chrono::nanoseconds timeout = mState = = State::SyntheticVSync ? 16ms : 1000ms

-> 增加一个判断环节mState == State::VSync,如果为VSync状态,打印一下VSync信息

-> 将伪造的 VSync 放入 mPendingEvents 准备分发,mPendingEvents.push_back + makeVSync组合,将消息派发出去,给到DisplayEventReceiver处理


① mVSyncState 声明在 EventThread.h 头文件中,通过其 synthetic 判断 nextState 是 SyntheticVSync 还是 VSync
② promote() 是 wp 的一个函数,调用 attemptIncStrong ,返回一个对象的强引用。即通过 promote() 函数将弱引用变为强引用,强引用数+1,弱引用数+1。因为通过弱指针 wp,不能获取实际的对象,wp 并没有提供 sp 那样的存取操作 * 和 -> 的重载,由弱生强后,可以 sp 获取实际的对象。

4.6.3 逻辑总结

总结
① 声明消费 Event 的 EventThreadConnection 向量集合 consumers,开启死循环,如状态值不等于 State::Quit 则一直循环来处理 Event。
② 遍历双端队列 mPendingEvents,取出并确定下一个要调度的 Event。
③ 遍历存储 EventThreadConnection 的 vector 容器 mDisplayEventConnections,查找消费事件的连接,并将符合条件的 EventThreadConnection 添加到 consumers 中。
④ 调用 dispatchEvent(*event, consumers) 方法遍历 consumers 为其每个 EventThreadConnection 分发事件。
⑤ 没有事件且当前线程状态为:State::Idle,则线程继续等待事件或客户端注册、请求,如果没有事件且线程状态不为:State::Idle 时则需要伪造 VSync 发送给请求者,防止驱动程序停止。

问: mPendingEvents 这个队列中的 Event 是哪里来的?
回答这个问题,首先得弄清楚 VSync 信号是哪里来的?VSync 信号是由 HWC 硬件模块根据屏幕刷新率(60Hz)产生。HWC 产生硬件 VSync 信号后经由 VSyncReactor、VSyncDispatchTimerQueue 等类的包装处理,最后 VSync 事件会回调到 EventThread::onVSyncEvent() 方法中,该方法通过 makeVSync() 方法把事件封装成 Event 后存到 mPendingEvents 双端队列中,并唤醒 EventThread::threadMain() 进行下一步处理。

4.7 shouldConsumeEvent

EventThread::shouldConsumeEvent() 是 判断某个连接 (EventThreadConnection) 是否应当接收一个 DisplayEvent 事件 的核心函数。其功能对于控制 SurfaceFlinger 向应用分发事件的节奏、精度和性能优化至关重要。

函数定义

bool EventThread::shouldConsumeEvent(
    const DisplayEventReceiver::Event& event,
    const sp<EventThreadConnection>& connection) const
  • 判断 event 是否应当被 connection 消费(即是否应推送给该客户端)。
  • 如果返回 true,该连接会收到该事件(见 dispatchEvent())。
  • 在 EventThread::threadMain() 中被调用。

源码分析

bool EventThread::shouldConsumeEvent(const DisplayEventReceiver::Event& event,
                                     const sp<EventThreadConnection>& connection) const {
    // 节流逻辑 throttleVsync(内部 Lambda)
    const auto throttleVsync = [&]() REQUIRES(mMutex) {
        const auto& vsyncData = event.vsync.vsyncData;
        // 指定了 connection->frameRate
        if (connection->frameRate.isValid()) {
            // 使用 VsyncTracker::isVSyncInPhase(...) 判断当前 VSYNC 是否对齐该帧率;若未对齐,则跳过当前帧
            return !mVsyncSchedule->getTracker()
                            .isVSyncInPhase(vsyncData.preferredExpectedPresentationTime(),
                                            connection->frameRate);
        }

        // 未指定帧率,使用全局 throttle 回调(mThrottleVsyncCallback)
        return mThrottleVsyncCallback &&
                mThrottleVsyncCallback(event.vsync.vsyncData.preferredExpectedPresentationTime(),
                                       connection->mOwnerUid);
    };

    switch (event.header.type) {
        // HOTPLUG 事件:总是发送
        case DisplayEventReceiver::DISPLAY_EVENT_HOTPLUG:
            return true; // 显示连接/断开事件,无需判断是否注册,直接发给所有连接

        // MODE_CHANGE 事件:根据注册标志判断
        case DisplayEventReceiver::DISPLAY_EVENT_MODE_CHANGE: {
            // 只有当连接明确注册了 modeChanged 事件,才发
            return connection->mEventRegistration.test(
                    gui::ISurfaceComposer::EventRegistration::modeChanged);
        }

        // VSYNC 事件:逻辑最复杂
        case DisplayEventReceiver::DISPLAY_EVENT_VSYNC:
            switch (connection->vsyncRequest) {
                // VSyncRequest::None: 明确不接收 VSYNC
                case VSyncRequest::None: 
                    return false;
                // VSyncRequest::SingleSuppressCallback:伪状态,用于忽略下一帧
                case VSyncRequest::SingleSuppressCallback:
                    // 这是处理 Single 模式的一种中间态:抑制回调,只接收一次后清除请求
                    connection->vsyncRequest = VSyncRequest::None;
                    return false;
                // VSyncRequest::Single: 仅请求接收一次
                case VSyncRequest::Single: {
                    // 若需要节流,则跳过这帧;
                    if (throttleVsync()) {
                        return false;
                    }
                    // 否则允许接收,但设置状态为 SingleSuppressCallback,表示“下一帧别发了”
                    connection->vsyncRequest = VSyncRequest::SingleSuppressCallback;
                    return true;
                }
                // VSyncRequest::Periodic: 周期性接收
                case VSyncRequest::Periodic:
                    // 若当前帧被判定为“应节流”,则跳过; 否则定期分发
                    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
                    // 例如某些应用可能请求每 N 帧才接收一次 vsync;利用 vsync.count % N == 0 来实现节奏控制。
                    return event.vsync.count % vsyncPeriod(connection->vsyncRequest) == 0;
            }

        case DisplayEventReceiver::DISPLAY_EVENT_FRAME_RATE_OVERRIDE:
            [[fallthrough]];
        case DisplayEventReceiver::DISPLAY_EVENT_FRAME_RATE_OVERRIDE_FLUSH:
            return connection->mEventRegistration.test(
                    gui::ISurfaceComposer::EventRegistration::frameRateOverride);

        default:
            return false;
    }
}

4.8 generateFrameTimeline

EventThread::generateFrameTimeline(…) 函数的核心作用是:根据当前 VSync 信号,生成一组候选帧时间线(FrameTimelines)用于提交到 GPU 的时间调度与预测,供 Choreographer / RenderThread 等系统组件参考。

函数作用总结
输入:

  • timestamp: 当前 VSync 的时间戳
  • frameInterval: 一帧的时长(如 16.66ms)
  • preferredExpectedPresentationTime: 首选的帧显示时间(App 理想显示点)
  • preferredDeadlineTimestamp: 首选的帧提交 deadline(App 必须完成的时间)

输出:

  • VsyncEventData& outVsyncEventData: 写入多个候选帧的 vsync 时间线信息,每个包括 expectedPresentationTime 与 deadlineTimestamp。
void EventThread::generateFrameTimeline(VsyncEventData& outVsyncEventData, nsecs_t frameInterval,
                                        nsecs_t timestamp,
                                        nsecs_t preferredExpectedPresentationTime,
                                        nsecs_t preferredDeadlineTimestamp) const {
    uint32_t currentIndex = 0;
    // Add 1 to ensure the preferredFrameTimelineIndex entry (when multiplier == 0) is included.
    // 循环构建多个 Frame Timeline 候选项,从较早的帧(负 multiplier)开始扫描,直到找到 kFrameTimelinesCapacity 个合法时间线。
    for (int64_t multiplier = -VsyncEventData::kFrameTimelinesCapacity + 1;
         currentIndex < VsyncEventData::kFrameTimelinesCapacity; multiplier++) {
        // 计算候选帧的 deadline 与 expectedPresentationTime
        nsecs_t deadlineTimestamp = preferredDeadlineTimestamp + multiplier * frameInterval;
        // Valid possible frame timelines must have future values, so find a later frame timeline.
        // 过滤掉无效帧(如已经过去的帧)
        if (deadlineTimestamp <= timestamp) {
            continue;
        }

        nsecs_t expectedPresentationTime =
                preferredExpectedPresentationTime + multiplier * frameInterval;
        // 过滤掉时间太远的帧(提前提交帧不能太早)
        if (expectedPresentationTime >= preferredExpectedPresentationTime +
                    scheduler::VsyncConfig::kEarlyLatchMaxThreshold.count()) {
            // 记录 preferred timeline 的 index,这是 App 本次 VSync 预期使用的时间线(即当前时间点所对应的 ideal 提交时机)
            if (currentIndex == 0) {
                ALOGW("%s: Expected present time is too far in the future but no timelines are "
                      "valid. preferred EPT=%" PRId64 ", Calculated EPT=%" PRId64
                      ", multiplier=%" PRId64 ", frameInterval=%" PRId64 ", threshold=%" PRId64,
                      __func__, preferredExpectedPresentationTime, expectedPresentationTime,
                      multiplier, frameInterval,
                      static_cast<int64_t>(
                              scheduler::VsyncConfig::kEarlyLatchMaxThreshold.count()));
            }
            break;
        }

        if (multiplier == 0) {
            outVsyncEventData.preferredFrameTimelineIndex = currentIndex;
        }

        // 填写 frameTimelines[] 数组
        // 每个 timeline 对应一个 vsyncId(用于同步标识)+ deadline + 显示时间
        outVsyncEventData.frameTimelines[currentIndex] =
                {.vsyncId = generateToken(timestamp, deadlineTimestamp, expectedPresentationTime),
                 .deadlineTimestamp = deadlineTimestamp,
                 .expectedPresentationTime = expectedPresentationTime};
        currentIndex++;
    }

    // 如果一个 timeline 都无法构建,强制写入 fallback timeline
    if (currentIndex == 0) {
        ALOGW("%s: No timelines are valid. preferred EPT=%" PRId64 ", frameInterval=%" PRId64
              ", threshold=%" PRId64,
              __func__, preferredExpectedPresentationTime, frameInterval,
              static_cast<int64_t>(scheduler::VsyncConfig::kEarlyLatchMaxThreshold.count()));
        // 基于当前帧时间戳生成唯一帧 token;
        // token 用于客户端(如 Choreographer)标识某一具体 VSync
        outVsyncEventData.frameTimelines[currentIndex] =
                {.vsyncId = generateToken(timestamp, preferredDeadlineTimestamp,
                                          preferredExpectedPresentationTime),
                 .deadlineTimestamp = preferredDeadlineTimestamp,
                 .expectedPresentationTime = preferredExpectedPresentationTime};
        currentIndex++;
    }

    // 最终写入 timeline 数量
    outVsyncEventData.frameTimelinesLength = currentIndex;
}

4.9 dispatchEvent

函数 EventThread::dispatchEvent(…) 是 SurfaceFlinger 中 EventThread 向客户端(应用层)分发 DisplayEvent 的核心函数,特别关键在 VSYNC 事件传递上(会影响到应用中的 Choreographer、RenderThread 等接收帧信号的组件)。向多个 DisplayEventConnection 发送当前准备好的 DisplayEvent(如 Vsync、Hotplug、ModeChange 等)。

void EventThread::dispatchEvent(const DisplayEventReceiver::Event& event, // 要派发的事件
                                const DisplayEventConsumers& consumers) { // 要通知的客户端连接列表
    // 针对每个 consumer(连接)做处理
    for (const auto& consumer : consumers) { // consumers 是经过 shouldConsumeEvent() 过滤的连接(即对该事件感兴趣的客户端)
        // 复制事件结构体(每个 connection 都是独立副本)
        DisplayEventReceiver::Event copy = event;
        // 如果是 VSync 事件,填入连接专属的时间线信息
        if (event.header.type == DisplayEventReceiver::DISPLAY_EVENT_VSYNC) {
            // 获取此连接所需的 frameInterval
            const int64_t frameInterval = mGetVsyncPeriodFunction(consumer->mOwnerUid);
            copy.vsync.vsyncData.frameInterval = frameInterval;
            // 调用 generateFrameTimeline() 为该连接生成完整的帧时间线(带多个帧预测信息)
            generateFrameTimeline(copy.vsync.vsyncData, frameInterval, copy.header.timestamp,
                                  event.vsync.vsyncData.preferredExpectedPresentationTime(),
                                  event.vsync.vsyncData.preferredDeadlineTimestamp());
        }
        // postEvent(...) 实际是往 DisplayEventReceiver 注册的 Binder fd 写入事件
        // EventThreadConnection::postEvent
        // 消费端(如 App 内部的 Choreographer)读取该 fd 触发对应的事件处理
        switch (consumer->postEvent(copy)) {
            case NO_ERROR: // 成功发送
                break;

            case -EAGAIN: // 写入管道失败(可能 pipe 满了),可以稍后重试
                // TODO: Try again if pipe is full.
                ALOGW("Failed dispatching %s for %s", toString(event).c_str(),
                      toString(*consumer).c_str());
                break;

            default: // 如 EPIPE 表示接收端挂掉了,主动清理连接
                // Treat EPIPE and other errors as fatal.
                removeDisplayEventConnectionLocked(consumer);
        }
    }
}

总结要点

核心点说明
每个连接独立派发事件每个 consumer 会收到一份拷贝,确保独立性
针对 vsync,生成个性化 frameTimeline不同 app 拥有不同 frameInterval 和调度策略
VSYNC 事件包含 frameInterval、多个候选帧时间线用于 Choreographer 与 GPU pipeline 调度
若连接无响应或挂掉,自动清理防止资源泄露

4.10 onNewVsyncSchedule

EventThread::onNewVsyncSchedule(…) 与 onNewVsyncScheduleInternal(…) 的代码,是 SurfaceFlinger 中 EventThread 切换新的 VsyncSchedule 调度器的实现逻辑。这是动态刷新率、Vsync 策略管理中的关键一环。

当 Vsync 调度策略发生变化(如刷新率变更、display 配置更新等),SurfaceFlinger 会调用:EventThread::onNewVsyncSchedule(…)。将新的 VsyncSchedule 安装进来,并在需要时重新注册 Vsync 回调,确保之后的 Vsync 事件能正确调度并触发 onVsync(…) 回调。

void EventThread::onNewVsyncSchedule(std::shared_ptr<scheduler::VsyncSchedule> schedule) {
    // 外部入口(保持线程安全、避免死锁)
    // Hold onto the old registration until after releasing the mutex to avoid deadlock.
    // 仅调用了内部实际逻辑函数,并保留返回值用于延迟释放资源(避免死锁)
    scheduler::VSyncCallbackRegistration oldRegistration =
            onNewVsyncScheduleInternal(std::move(schedule));
}

scheduler::VSyncCallbackRegistration EventThread::onNewVsyncScheduleInternal(
        std::shared_ptr<scheduler::VsyncSchedule> schedule) {
    std::lock_guard<std::mutex> lock(mMutex);
    // 取消旧的回调注册, 解除当前 mVsyncRegistration 在调度器中的绑定。
    const bool reschedule = mVsyncRegistration.cancel() == scheduler::CancelResult::Cancelled;
    // 替换调度器和回调
    mVsyncSchedule = std::move(schedule); // 更新 mVsyncSchedule
    // 用新的 VsyncDispatch 创建并替换掉旧的 mVsyncRegistration
    // 绑定 createDispatchCallback() 作为新的回调函数
    // 注解:VSyncCallbackRegistration 是个包装器:用于自动管理 dispatch → callback 的注册与注销逻辑
    auto oldRegistration =
            std::exchange(mVsyncRegistration,
                          scheduler::VSyncCallbackRegistration(mVsyncSchedule->getDispatch(),
                                                               createDispatchCallback(),
                                                               mThreadName));
    // 如果之前是激活状态(成功取消),则重新 schedule vsync
    if (reschedule) {
        mVsyncRegistration.schedule({.workDuration = mWorkDuration.get().count(), // 客户端工作所需时间(提前多久 wakeup)
                                     .readyDuration = mReadyDuration.count(), // GPU 准备所需时间(提前多久提交)
                                     .earliestVsync = mLastVsyncCallbackTime.ns()}); // 当前最早允许的 vsync 时间戳(避免早唤醒)
    }
    return oldRegistration;
}

// 创建 Vsync 回调函数(最终回到 onVsync)
scheduler::VSyncDispatch::Callback EventThread::createDispatchCallback() {
    return [this](nsecs_t vsyncTime, nsecs_t wakeupTime, nsecs_t readyTime) {
        onVsync(vsyncTime, wakeupTime, readyTime);
    };
}

4.11 createDispatchCallback

EventThread::createDispatchCallback() 方法,返回一个类型为 scheduler::VSyncDispatch::Callback 的 闭包(lambda)函数,它将 onVsync(…) 方法绑定为 VSYNC 回调处理逻辑的执行入口。

scheduler::VSyncDispatch::Callback EventThread::createDispatchCallback() {
    return [this](nsecs_t vsyncTime, nsecs_t wakeupTime, nsecs_t readyTime) {
        onVsync(vsyncTime, wakeupTime, readyTime);
    };
}
  • EventThread 调用 createDispatchCallback() 创建一个 VSYNC 到来时执行的函数。
  • 这个函数被注册进了 scheduler::VSyncDispatch(调度器)中。
  • 当 VSYNC 被触发时,VSyncDispatch 会调用这个 lambda。
  • Lambda 内部调用 onVsync(vsyncTime, wakeupTime, readyTime),这是 EventThread实际处理逻辑的入口。

createDispatchCallback() 的作用是为当前 EventThread 生成一个 专属 VSYNC 响应函数,并注册到 VSyncDispatch 调度系统中。一旦系统检测到下一次 VSYNC 到来,调度器就会调用这个函数。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值