Android surfaceflinger (4) -Vsync产生上报流程

本文深入解析了VSync信号的产生及传递过程,包括硬件产生VSync信号的方式、信号如何通过不同层级的软件组件最终到达应用程序的过程。此外还详细介绍了VSync信号在SurfaceFlinger、EventThread等组件间的传递机制。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

1、垂直同步信号

VSync(即V-Sync垂直同步)的具体含义和用途文章不细说,看下图的VSync的位置大致也就知道它的用途(简单理解成是硬件定时中断貌似也可以,周期性的硬件中断,频率为60Hz,周期为0.0167s,也就是16ms)。
本文主要关注以下几个问题: \
(1)VSync是如何产生的? \
(2)VSync是如何分发到应用进程的?

2、流程框图

这里写图片描述

3、VSync产生

VSync事件一般由硬件周期性产生,如果没有相应的硬件产生VSync事件,则通过软件模拟。下面主要看下从硬件产生VSync事件。

bool VSyncThread::threadLoop()
{
    if (mFakeVSync) {
        performFakeVSync();//软件模拟产生
    }
    else {
        performVSync();//硬件产生
    }

    return true;
}

void VSyncThread::performVSync()
{
    uint64_t timestamp = 0;
    uint32_t crt = (uint32_t)&timestamp;

    //调用kernel等待VSync信号
    int err = ioctl(mCtx->mDispInfo[HWC_DISPLAY_PRIMARY].fd,
                    MXCFB_WAIT_FOR_VSYNC, crt);
    if ( err < 0 ) {
        ALOGE("FBIO_WAITFORVSYNC error: %s\n", strerror(errno));
        return;
    }

    //回调至HWComposer类的hook_vsync方法 详见第3节
    mCtx->m_callback->vsync(mCtx->m_callback, 0, timestamp);
    ..........
}

4、VSync信号上报过程

4.1 HWComposer至DispSyncThread过程

在上面分析到了HWComposer类,hook_vsync实现如下:

void HWComposer::hook_vsync(const struct hwc_procs* procs, int disp,
        int64_t timestamp) {
    cb_context* ctx = reinterpret_cast<cb_context*>(
            const_cast<hwc_procs_t*>(procs));
    ctx->hwc->vsync(disp, timestamp);
}

ctx->hwc指向的就是当前的this指针,也就是当前的对象,因此调用的就是当前对象的vsync函数,看一下这个函数:

void HWComposer::vsync(int disp, int64_t timestamp) {
    if (uint32_t(disp) < HWC_NUM_PHYSICAL_DISPLAY_TYPES) {
        ........
        mEventHandler.onVSyncReceived(disp, timestamp);
    }
}

最重要的就是调用了mEventHandler.onVSyncReceived()函数,这里mEventHandler是在HWComposer初始化的,实际上就是创建当前HWComposer对象的SurfaceFlinger对象,因此该函数回调至SurfaceFlinger.onVSyncReceived()函数,故HWC硬件产生的同步信号就可以到达SurfaceFlinger里面了。onVSyncReceived的实现如下:

void SurfaceFlinger::onVSyncReceived(int type, nsecs_t timestamp) {
        .........
            needsHwVsync = mPrimaryDispSync.addResyncSample(timestamp);
        .......
#endif
}

mPrimaryDispSync是一个DispSync对象,其初始化是在surfaceflinger::init()完成的。

回调的流程为DispSync.addResyncSample—–>DispSync.DispSyncThread.updateModel,如下所示:

bool DispSync::addResyncSample(nsecs_t timestamp) {
   .......
    updateModelLocked();
    .......
}
void DispSync::updateModelLocked() {
        .......
        mThread->updateModel(mPeriod, mPhase);

}

mThread指的是DispSyncThread线程,故上述调用的是DispSyncThread线程中的updateModel方法。

    void updateModel(nsecs_t period, nsecs_t phase) {
        .......
        mCond.signal();//唤醒被阻塞的DispSyncThread线程
    }

DispSyncThread线程在实时监测,一旦监测到退出信号就会退出阻塞

4.2 DispSyncThread至EventThread过程


    virtual bool threadLoop() {

        while (true) {
            .........
                    err = mCond.wait(mMutex);//线程阻塞等待           
            .........
            //从mEventListeners中收集所有满足时间条件的EventListener 详见第3.2.1节
                callbackInvocations = gatherCallbackInvocationsLocked(now);
             .........            
            fireCallbackInvocations(callbackInvocations);//详见第3.2.2节
             .........
    }
4.2.1 EventListener的初始化

在surfaceflinger::init中创建DispSyncSource对象,执行构造函数时会调用addEventListener进行初始化

class DispSyncSource : public VSyncSource, private DispSync::Callback {
public:
    DispSyncSource(DispSync* dispSync, nsecs_t phaseOffset, bool traceVsync,
        const char* label) :
            mValue(0),
            mTraceVsync(traceVsync),
            mVsyncOnLabel(String8::format("VsyncOn-%s", label)),
            mVsyncEventLabel(String8::format("VSYNC-%s", label)),
            mDispSync(dispSync),
            mCallbackMutex(),
            mCallback(),
            mVsyncMutex(),
            mPhaseOffset(phaseOffset),
            mEnabled(false) {}


    virtual void setVSyncEnabled(bool enable) {
        Mutex::Autolock lock(mVsyncMutex);
        if (enable) {
            status_t err = mDispSync->addEventListener(mPhaseOffset,
                    static_cast<DispSync::Callback*>(this));//this指的是当前的surfaceflinger对象
        } else {
            status_t err = mDispSync->removeEventListener(
                    static_cast<DispSync::Callback*>(this));
        }
        mEnabled = enable;
    }
status_t DispSync::addEventListener(nsecs_t phase,
        const sp<Callback>& callback) {

    Mutex::Autolock lock(mMutex);
    return mThread->addEventListener(phase, callback);//callback即surfaceflinger对象
}
    status_t addEventListener(nsecs_t phase, const sp<DispSync::Callback>& callback) {
        .......
        listener.mCallback = callback;//callback即surfaceflinger对象

        mEventListeners.push(listener);

        mCond.signal();

        return NO_ERROR;
    }
    Vector<CallbackInvocation> gatherCallbackInvocationsLocked(nsecs_t now) {
            ........
              if (t < now) {
                CallbackInvocation ci;
                ci.mCallback = mEventListeners[i].mCallback;//mCallback即surfaceflinger对象
                ci.mEventTime = t;
                callbackInvocations.push(ci);
                mEventListeners.editItemAt(i).mLastEventTime = t;
            }

        return callbackInvocations;
    }
4.2.2 回调至EventThread
    void fireCallbackInvocations(const Vector<CallbackInvocation>& callbacks) {
        for (size_t i = 0; i < callbacks.size(); i++) {
            callbacks[i].mCallback->onDispSyncEvent(callbacks[i].mEventTime);//回调至surfaceflinger对象的onDispSyncEvent方法
        }
    }
    virtual void onDispSyncEvent(nsecs_t when) {
        sp<VSyncSource::Callback> callback;
        {
            Mutex::Autolock lock(mCallbackMutex);
            callback = mCallback;//mCallback指的是EventThread对象

            if (mTraceVsync) {
                mValue = (mValue + 1) % 2;
                ATRACE_INT(mVsyncEventLabel.string(), mValue);
            }
        }

        if (callback != NULL) {
            callback->onVSyncEvent(when);//调用至EventThread
        }
    }
void EventThread::onVSyncEvent(nsecs_t timestamp) {
    .......
    mCondition.broadcast();//发广播释放线程阻塞
}

4.3 EventThread至jni

先看一下EventThread的线程实现如下:

bool EventThread::threadLoop() {
    DisplayEventReceiver::Event event;
    Vector< sp<EventThread::Connection> > signalConnections;
    signalConnections = waitForEvent(&event); //等待事件

    // dispatch events to listeners...
    const size_t count = signalConnections.size();
    for (size_t i=0 ; i<count ; i++) {
        const sp<Connection>& conn(signalConnections[i]);
        // now see if we still need to report this event
        status_t err = conn->postEvent(event);//消息继续上报
        ........
    }
    return true;
}
Vector< sp<EventThread::Connection> > EventThread::waitForEvent(
        DisplayEventReceiver::Event* event)
{
    Mutex::Autolock _l(mLock);
    Vector< sp<EventThread::Connection> > signalConnections;

    do {
       .......
        mCondition.wait(mLock);//线程阻塞等待
        ......   

    } while (signalConnections.isEmpty());

    return signalConnections;
}

postEvent会调用DisplayEventReceiver::sendEvents()->BitTube::sendObjects();然后通过BitTube与jni进行通信,调用NativeDisplayEventReceiver::handleEvent()

int NativeDisplayEventReceiver::handleEvent(int receiveFd, int events, void* data) {
    .......

    if (processPendingEvents(&vsyncTimestamp, &vsyncDisplayId, &vsyncCount)) {//processPendingEvents获取信号
        ALOGV("receiver %p ~ Vsync pulse: timestamp=%" PRId64 ", id=%d, count=%d",
                this, vsyncTimestamp, vsyncDisplayId, vsyncCount);
        mWaitingForVsync = false;
        dispatchVsync(vsyncTimestamp, vsyncDisplayId, vsyncCount);//信号分发
    }

    return 1; // keep the callback
}
void NativeDisplayEventReceiver::dispatchVsync(nsecs_t timestamp, int32_t id, uint32_t count) {
    JNIEnv* env = AndroidRuntime::getJNIEnv();

    ScopedLocalRef<jobject> receiverObj(env, jniGetReferent(env, mReceiverWeakGlobal));
    if (receiverObj.get()) {
        env->CallVoidMethod(receiverObj.get(),
                gDisplayEventReceiverClassInfo.dispatchVsync, timestamp, id, count);//回调Java层
        ALOGV("=zsx= receiver %p ~ Returned from vsync handler.", this);
    }

    mMessageQueue->raiseAndClearException(env, "dispatchVsync");
}

由上面分析可知,将回调至Choreographer.java中FrameDisplayEventReceiver类中的onVsync方法。

5、Java层

    public void onVsync(long timestampNanos, int builtInDisplayId, int frame) {
            .......
            mHandler.sendMessageAtTime(msg, timestampNanos / TimeUtils.NANOS_PER_MS);
        }
  private final class FrameHandler extends Handler {

        public void handleMessage(Message msg) {//根据不同消息类型进行处理
            switch (msg.what) {
                case MSG_DO_FRAME:
                    doFrame(System.nanoTime(), 0);
                    break;
                case MSG_DO_SCHEDULE_VSYNC:
                    doScheduleVsync();
                    break;
                case MSG_DO_SCHEDULE_CALLBACK:
                    doScheduleCallback(msg.arg1);
                    break;
            }
        }
    }
<think>好的,我现在需要回答用户关于SurfaceFlinger和DisplayManagerService在安卓启动流程中处于哪一层的问题。首先,我要回顾一下之前提供的安卓启动流程,确保自己理解各个阶段。 用户之前的提问是关于安卓启动流程的,我详细介绍了从Bootloader到Launcher的六个阶段。现在用户进一步询问SurfaceFlinger和DisplayManagerService具体属于哪一层。我需要明确这两个服务在启动过程中的位置。 首先,我需要确认SurfaceFlinger和DisplayManagerService的作用。SurfaceFlinger是负责形合成的服务,将各个应用的窗口内容合成到屏幕上。DisplayManagerService则管理显示设备,比如屏幕的配置、分辨率、多屏显示等。 接下来,回顾之前的启动阶段:Init进程阶段会启动一些核心服务,包括surfaceflinger和servicemanager。而System Server阶段会启动各种系统服务,比如ActivityManagerService、WindowManagerService、PowerManagerService和DisplayManagerService等。 因此,SurfaceFlinger是在Init进程阶段由init.rc脚本启动的,属于较早期的服务,因为它需要为后续的形界面提供基础。而DisplayManagerService则是在System Server阶段由SystemServer进程启动的,属于系统服务层,可能在较后的阶段启动,因为它依赖于其他服务的存在,比如可能需要ActivityManagerService或WindowManagerService已经就绪。 需要验证这个理解是否正确。查阅Android官方文档或相关资料,确认SurfaceFlinger确实在Init阶段启动,而DisplayManagerService属于System Server的一部分。例如,AOSP的文档指出,Init进程会解析init.rc文件,启动关键服务如SurfaceFlinger,而System Server则负责启动其他系统服务,包括DisplayManagerService。 另外,用户可能想知道这两个服务在启动流程中的依赖关系。例如,SurfaceFlinger作为形合成的核心,必须在显示驱动加载之后启动,而DisplayManagerService可能需要SurfaceFlinger已经运行才能管理显示设备。因此,启动顺序上SurfaceFlinger早于DisplayManagerService。 还需要注意是否有例外情况或不同的Android版本之间的差异。例如,在较新的Android版本中,启动流程是否有变化,或者某些服务是否被合并或拆分。但根据目前的知识,SurfaceFlinger属于Init阶段,DisplayManagerService属于System Server阶段,这一点应该是稳定的。 总结:SurfaceFlinger在Init进程阶段启动,属于系统底层服务;DisplayManagerService在System Server阶段启动,属于系统服务层。需要将这些信息清晰、有条理地传达给用户,并确保术语准确,避免混淆。</think>以下是关于SurfaceFlinger与DisplayManagerService在安卓启动流程中的层级归属及详细解析: --- ### **一、归属层级** 1. **SurfaceFlinger** - **启动阶段**:**Init进程阶段**(用户空间初始化的早期阶段) - **层级**:**系统底层形服务** - **关键依赖**:Linux内核显示驱动(如DRM/KMS)、硬件帧缓冲(Framebuffer) 2. **DisplayManagerService** - **启动阶段**:**System Server阶段**(系统服务初始化阶段) - **层级**:**Android框架层系统服务** - **关键依赖**:SurfaceFlinger、WindowManagerService、硬件抽象层(HAL) --- ### **二、启动流程详解** #### **1. SurfaceFlinger的启动路径** - **触发时机**: Init进程解析`init.rc`脚本时启动,属于**用户空间最早启动的核心服务之一**。 - **具体流程**: 1. **Init进程阶段**: - 挂载`/system`、`/vendor`分区后,加载`init.rc`配置。 - 执行`start surfaceflinger`命令,启动SurfaceFlinger服务。 2. **初始化任务**: - 绑定到**Binder通信框架**(成为系统服务)。 - 通过HAL层调用**Gralloc(形内存分配器)**,初始化硬件合成器(如HWC)。 - 创建**EventThread**处理VSync信号,管理帧率同步。 - **典型日志标记**: ```bash adb logcat -s SurfaceFlinger # 查看启动日志 ``` #### **2. DisplayManagerService的启动路径** - **触发时机**: 在System Server进程中启动,属于**Android框架层的核心服务**。 - **具体流程**: 1. **System Server阶段**: - Zygote孵化SystemServer进程后,调用`startBootstrapServices()`方法。 - 在`startCoreServices()`阶段初始化DisplayManagerService。 2. **初始化任务**: - 注册到**ServiceManager**,提供显示管理接口。 - 通过Binder IPC与SurfaceFlinger交互,获取物理显示配置(如分辨率、刷新率)。 - 监听显示设备热插拔事件(如HDMI连接)。 - **依赖关系**: - **必须等待SurfaceFlinger就绪**,否则无法获取显示硬件信息。 - 需与WindowManagerService协作,管理窗口与显示的逻辑映射。 --- ### **三、两者协作关系** 1. **启动顺序**: ```plaintext SurfaceFlinger(Init阶段) → DisplayManagerService(System Server阶段) ``` 2. **功能协作**: - **SurfaceFlinger**:负责**物理显示合成**(将层数据提交给GPU/HWC)。 - **DisplayManagerService**:负责**逻辑显示管理**(多屏配置、虚拟显示、显示模式切换)。 3. **通信方式**: - 通过Binder IPC传递显示配置参数(如`DisplayState`)。 - SurfaceFlinger通过`HWComposer`上报硬件显示状态(如连接/断开)。 --- ### **四、调试与问题定位** #### **1. SurfaceFlinger常见问题** - **黑屏/闪屏**: - 检查内核显示驱动是否加载(`dmesg | grep "drm"`)。 - 验证SurfaceFlinger日志是否正常绑定HWC(`adb shell dumpsys SurfaceFlinger`)。 - **性能问题**: - 使用`systrace`分析帧合成耗时(关注`VSYNC-app/sf`信号)。 #### **2. DisplayManagerService常见问题** - **显示配置错误**: - 检查`config.xml`中的默认显示配置(如`/system/etc/displayconfig/`)。 - 查看DisplayManagerService的当前状态: ```bash adb shell dumpsys display # 显示所有已注册的显示设备 ``` - **多屏显示异常**: - 验证`DisplayDeviceRepository`是否正确识别外接显示器。 --- ### **五、扩展知识** - **Android形架构演进**: - **Android 12**:引入`CompositionEngine`重构合成逻辑,减少对SurfaceFlinger的直接依赖。 - **Android 13**:支持**动态刷新率切换**(DisplayManagerService与SurfaceFlinger协同实现)。 - **替代方案**: - 部分定制ROM(如MIUI)可能重写DisplayManagerService的逻辑,支持自定义显示模式。 --- 通过理解这两个服务的层级定位,可以更高效地分析显示相关问题(如开机动画卡顿、多屏适配异常),并针对性地优化系统启动流程或显示渲染性能。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值