Android VSync 机制分析

1. SurfaceFlinger 初始化 VSync 相关组件

在 SurfaceFlinger 初始化过程中,initScheduler 方法会创建 Scheduler,并启动 EventThread

class SurfaceFlinger{
    std::unique_ptr<scheduler::Scheduler> mScheduler;
}

void SurfaceFlinger::initScheduler(const sp<const DisplayDevice>& display) {
    mScheduler = std::make_unique<Scheduler>(static_cast<ICompositor&>(*this),
                                             static_cast<ISchedulerCallback&>(*this), features,
                                             getFactory(), activeRefreshRate, *mTimeStats);
    mScheduler->createEventThread(scheduler::Cycle::Render, mFrameTimeline->getTokenManager(),
                                  configs.late.appWorkDuration,
                                  configs.late.sfWorkDuration);
    mScheduler->createEventThread(scheduler::Cycle::LastComposite,
                                  mFrameTimeline->getTokenManager(),
                                  activeRefreshRate.getPeriod(),
                                  configs.late.sfWorkDuration);
    mScheduler->initVsync(*mFrameTimeline->getTokenManager(), configs.late.sfWorkDuration);
    mScheduler->startTimers();
}

2. Scheduler 创建 EventThread

Scheduler::createEventThread 方法创建 EventThread,并维护 mRenderEventThread 以及 mLastCompositeEventThread

void Scheduler::createEventThread(Cycle cycle, frametimeline::TokenManager* tokenManager,
                                  std::chrono::nanoseconds workDuration,
                                  std::chrono::nanoseconds readyDuration) {
    auto eventThread =
            std::make_unique<android::impl::EventThread>(cycle == Cycle::Render ? "app" : "appSf",
                                                         getVsyncSchedule(), tokenManager, *this,
                                                         workDuration, readyDuration);

    if (cycle == Cycle::Render) {
        mRenderEventThread = std::move(eventThread);
        mRenderEventConnection = mRenderEventThread->createEventConnection();
    } else {
        mLastCompositeEventThread = std::move(eventThread);
        mLastCompositeEventConnection = mLastCompositeEventThread->createEventConnection();
    }
}

3. APP 触发 requestNextVsync 流程

应用层通过 Choreographer 触发 requestNextVsync 请求。

public final class Choreographer {
    public static Choreographer getInstance() {
        return sThreadInstance.get();
    }

    public void postCallback(int callbackType, Runnable action, Object token) {
        postCallbackDelayed(callbackType, action, token, 0);
    }

    private void scheduleVsyncLocked() {
        try {
            Trace.traceBegin(Trace.TRACE_TAG_VIEW, "Choreographer#scheduleVsyncLocked");
            mDisplayEventReceiver.scheduleVsync();
        } finally {
            Trace.traceEnd(Trace.TRACE_TAG_VIEW);
        }
    }
}

FrameDisplayEventReceiver 继承 DisplayEventReceiver,并通过 nativeScheduleVsync 请求下一次 VSync。

static void nativeScheduleVsync(JNIEnv* env, jclass clazz, jlong receiverPtr) {
    sp<NativeDisplayEventReceiver> receiver =
            reinterpret_cast<NativeDisplayEventReceiver*>(receiverPtr);
    status_t status = receiver->scheduleVsync();
}

4. DisplayEventReceiver 处理 VSync 请求

DisplayEventReceiver 通过 EventThreadConnection 请求下一次 VSync。

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

5. VSync 事件通过 Socket 发送到应用层

VSync 事件通过 BitTube 进行 IPC 传输。

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

BitTube 使用 socketpair 创建数据通道,并在 DisplayEventDispatcher 监听数据。

void BitTube::init(size_t rcvbuf, size_t sndbuf) {
    int sockets[2];
    if (socketpair(AF_UNIX, SOCK_SEQPACKET, 0, sockets) == 0) {
        mReceiveFd.reset(sockets[0]);
        mSendFd.reset(sockets[1]);
    }
}

6. DisplayEventDispatcher 监听 VSync 事件

DisplayEventDispatcher 监听 BitTubemReceiveFd,在 Java 层 dispatchVsync 方法回调 VSync 事件。

public abstract class DisplayEventReceiver {
    private void dispatchVsync(long timestampNanos, long physicalDisplayId, int frame) {
        onVsync(timestampNanos, physicalDisplayId, frame, mVsyncEventData);
    }
}

7. 总结

  1. Choreographer 触发 VSync 请求,调用 scheduleVsyncLocked
  2. DisplayEventReceiver 通过 nativeScheduleVsync 请求 VSync。
  3. EventThread 处理 requestNextVsync,通过 BitTube 发送 VSync 事件。
  4. DisplayEventDispatcher 监听 BitTube 事件,并回调 Java 层 dispatchVsync

整个流程涵盖了应用层、JNI 层、Binder 进程间通信 (IPC) 以及 Native 层的事件分发机制。

©著作权归作者所有,转载或内容合作请联系作者
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

推荐阅读更多精彩内容