前面一篇文章从整体介绍View制作的流程,其中一点便是制作的起始点便是界面收到了Vsync之后,开端新一帧的制作,所以能够说, 是vsync触发了制作。收到vsync信号后的处理咱们现已清楚了,现在咱们剖析以下sync是怎样发生的,以及怎样消费的。

1. 从 16ms说起

咱们16ms这个时刻应该是形象深刻了,咱们经常听到在大部分屏幕的改写频率是60Hz的状况下,那每一帧的时刻就约16ms,假如应用程序在收到一次vsync信号开端制作,16毫秒内没有制作结束,就会呈现丢帧,卡顿。确实如此,可是这听起来却有些难以了解,制作慢一点怎样就影响到到屏幕改写了,它不是依照屏幕的硬件60Hz频率刷的吗?为什么会丢呢?丢了为什么会卡顿呢?终究vsync什么时分来?

2. Vsync的效果

这不是本文的要点,仅仅作为布景常识介绍一下。假设一下以下的状况:

  • app每秒钟匀速生成120张图片,可是屏幕每秒只能匀速显现60张。结果是120张中只有60张展现,步骤相同的状况下,偶数张被忽略,即丢帧,app多生成的60张属于糟蹋CPU,CPU完全能够出产1张后休眠一会,节省资源
  • app每秒钟生成30张,可是屏幕每秒钟改写60次。结果是第2次改写时展现的内容是上一次出产的,屏幕完全能够改写一次歇息一次,削减耗电。
  • app每秒生成60张,屏幕每秒钟改写60次,可是步骤不一致,屏幕显现完上半屏内容的时分,新的显现数据来了,下半屏幕将显现新的内容,构成画面撕裂。

这3个问题便是由于出产显现数据和消费显现数据不一致导致的。因而需求将二者进行同步。

  • app需求更新内容时告诉屏幕开端改写,不然屏幕不作改写;
  • 屏幕显现完了告诉app能够出产新数据,app进行制作,不然app不做制作;
  • 屏幕显现完结前,也不做显现数据的更新,防止画面撕裂。

这个同步便是Vsync。其实vsync并不是咱们想象的那样,屏幕每16ms改写一次,然后每16毫秒就发送一次sync(屏幕是否一直是每16ms就无条件改写一次,暂时还无法从代码里得到证明),事实是假如界面没有工作,比方点击,动画,焦点等需求展现新内容操作,比方一个界面展现一个文本后,没有任何用户交互,这个段时刻内就不会有sync信号呈现。这很好了解,一个静态的页面在那里不停制作相同的内容,肯定是糟蹋电的,这对手机来说是至关重要的。只有当内容是需求一直在改变的,比方在连续滑动的界面,动画和游戏等才有vsync信号持续呈现,而至于一个静态的图片展现页面是没有Vsync信号的。

假设一个电影文件里1秒钟记载了60张图片,假如屏幕改写率只有30次,假如没有sync,那电影文件里一张展现一张不展现,假如人的眼睛特别活络的话,就会发现画面不连贯,不展现的那些帧便是所谓的丢帧

在软件里,和电影不一样,每一帧都是运算后画出来的,理论上来说经过VSync来控制后,不存在丢帧的状况,也便是出产出来的每一帧都会被展现,可是会呈现卡顿不连贯,比方第N帧耗时比较多的时分,当前帧(N-1)展现时刻就相应增加,而(N+1)帧开端时刻会相应推迟,相应计算出来的改变就过大。从视觉上看便是屏幕一直停在某个画面,可是画面改变时一下又变得很大,最终在给定时刻内展现的帧数也比预期的少。比方一个动画,设置总的时刻是1000毫米,移动间隔600像素,假如每帧制作很快,那总共能够展现60帧,榜首帧16ms移动到10,第二帧32ms移动到20…第60帧移动到600,这便是很流通的,帧数60次。这个位移值是一个时刻的函数(不是次数的函数),它是动画当前的时刻减去发动时刻,再去算动画时长的位移,假如每帧履行的时刻变成32s,显现时便是榜首帧32ms帧20,第二帧64ms帧40… 这就导致榜首帧展现了32ms(时刻变长了),而且第二帧直接从20移动到40(改变太大了),帧数也只有30次,相当于“丢失”了30帧。假如是不均匀的改变,那么界面的抖动就更加的难以承受。所以Vsync并不能避免丢帧卡顿的状况。它只能避免屏幕撕裂,以及削减资源的糟蹋

下面正式进入vsync的技能剖析。

3. Vsync流程

整体来看,Vsync的流程能够分为SurfaceFlinger 层的Vsync信号发生流程,App层的监听流程和触发流程。

  • Vsync信号的发生流程,首要包括sufacefinger对HAL层注册回调以及处理,并敞开一个EventThread来分发Vsync信号
  • App在展现UI的时分,注册监听获取Vsync的告诉
  • Vsync在surfaceflinger发生后,并不会直接上报,而是在等候UI层的告诉,UI层触发后底层发动工作分发,然后UI层收到Vsync才开端制作

下面咱们沿着这个流程来看看每个环节的完结。本片文章首先剖析surfaceflinger部分,介绍Vsync的架构基础

4. SurfaceFlinger层的完结

这一节里边首要会介绍到以下的内容

  • 作为布景,介绍surfaceFligger 的发动和初始化
  • HWComposer 关于vsync的接口
  • Schedualer, EventThread ,MessageQueue , 工作分发

4.1. SurfaceFlinger的初始化

代码编译后,它是一个独立的可履行程序打包到镜像文件里,路径是/system/bin/surfaceflinger,在Init的时分发动
frameworks/native/services/surfaceflinger/surfaceflinger.rc

service surfaceflinger /system/bin/surfaceflinger
    class core animation
    user system
    group graphics drmrpc readproc
    capabilities SYS_NICE
    onrestart restart zygote
    task_profiles HighPerformance
    socket pdx/system/vr/display/client     stream 0666 system graphics u:object_r:pdx_display_client_endpoint_socket:s0
    socket pdx/system/vr/display/manager    stream 0666 system graphics u:object_r:pdx_display_manager_endpoint_socket:s0
    socket pdx/system/vr/display/vsync      stream 0666 system graphics u:object_r:pdx_display_vsync_endpoint_socket:s0

Init的流程就不讲了,咱们直接进入它到main函数
frameworks/native/services/surfaceflinger/main_surfaceflinger.cpp

int main(int, char**) {
    sp<SurfaceFlinger> flinger = surfaceflinger::createSurfaceFlinger();
    flinger->init();
    // publish surface flinger
    sp<IServiceManager> sm(defaultServiceManager());
    sm->addService(String16(SurfaceFlinger::getServiceName()), flinger, false,
                   IServiceManager::DUMP_FLAG_PRIORITY_CRITICAL | IServiceManager::DUMP_FLAG_PROTO);
    if (SurfaceFlinger::setSchedFifo(true) != NO_ERROR) {
        ALOGW("Couldn't set to SCHED_FIFO: %s", strerror(errno));
    }
    flinger->run();
    return 0;
}

经过工厂来创立SurfaceFlinger的实例
frameworks/native/services/surfaceflinger/SurfaceFlingerFactory.cpp

sp<SurfaceFlinger> createSurfaceFlinger() {
    static DefaultFactory factory;
    return new SurfaceFlinger(factory);
}

这个factory是默认的DefaultFactory,界说在_frameworks/native/services/surfaceflinger/SurfaceFlingerDefaultFactory.cpp_

SurfaceFlinger::SurfaceFlinger(Factory& factory, SkipInitializationTag)
      : mFactory(factory),
      ...
}
SurfaceFlinger::SurfaceFlinger(Factory& factory) : SurfaceFlinger(factory, SkipInitialization) {
    ...
}

其他服务暂时略去,仅仅看一下surfaceflinger的发动,创立一个SurfaceFlinger目标,然后调用init初始化,之后注册到servicemanager,供长途访问,最终履行run发动服务,这儿首要便是结构办法和init 办法。SurfaceFligger的父类或许接口包括以下几个:

class SurfaceFlinger : public BnSurfaceComposer,
                       public PriorityDumper,
                       private IBinder::DeathRecipient,
                       private HWC2::ComposerCallback,
                       private ISchedulerCallback {
...
}
  • BnSurfaceComposer是作为ISurfaceComposer的服务端桩
  • HWC2::ComposerCallback 作为HWComposer的回调,首要包括onComposerHalVsync等办法,界说在_frameworks/native/services/surfaceflinger/DisplayHardware/HWC2.h_
  • ISchedulerCallback,作为Scheduler的回调,首要包括setVsyncEnabled办法界说在frameworks/native/services/surfaceflinger/Scheduler/Scheduler.h。

上面的界说说明,咱们能够大致认为 SurfaceFlinger目标会被注册到HWComposer去,在HWComposer端收到硬件的Vsync后,会回调SurfaceFlinger的onComposerHalVsync办法;一起SurfaceFlinger目标会被注册到Scheduler中去,在适当时分会回调setVsyncEnabled办法。下面看看是假如这些代码是相关起来的。

4.1.1. init

void SurfaceFlinger::init() {
    mCompositionEngine->setHwComposer(getFactory().createHWComposer(mHwcServiceName));
    mCompositionEngine->getHwComposer().setCallback(this);
    ...
    processDisplayHotplugEventsLocked();
    ..
}

这儿首先调用了factory.createHWComposer办法去创立一个HWComposer,然后再调用setCallback(this)完结SurfaceFlinger与HWComposer的相关。然后调用processDisplayHotplugEventsLocked办法,处理屏幕热插拔工作,处理包括内置屏幕在内初始化

void SurfaceFlinger::processDisplayHotplugEventsLocked() {
    for (const auto& event : mPendingHotplugEvents) {
        ...
        if (event.connection == hal::Connection::CONNECTED) {
               ...
                if (event.hwcDisplayId == getHwComposer().getInternalHwcDisplayId()) {
                    initScheduler(state);
                }
                ...
            } else {
               ...
            }
       }
}

假如找到了内置显现器,则调用initScheduler

void SurfaceFlinger::initScheduler(const DisplayDeviceState& displayState) {
    ...
    // start the EventThread
    mScheduler = getFactory().createScheduler(*mRefreshRateConfigs, *this);
    const auto configs = mVsyncConfiguration->getCurrentConfigs();
    const nsecs_t vsyncPeriod = currRefreshRate.getPeriodNsecs();
    mAppConnectionHandle =
            mScheduler->createConnection("app", mFrameTimeline->getTokenManager(),
                                         /*workDuration=*/configs.late.appWorkDuration,
                                         /*readyDuration=*/configs.late.sfWorkDuration,
                                         impl::EventThread::InterceptVSyncsCallback());
    mSfConnectionHandle =
            mScheduler->createConnection("appSf", mFrameTimeline->getTokenManager(),
                                         /*workDuration=*/std::chrono::nanoseconds(vsyncPeriod),
                                         /*readyDuration=*/configs.late.sfWorkDuration,
                                         [this](nsecs_t timestamp) {
                                             mInterceptor->saveVSyncEvent(timestamp);
                                         });
    mEventQueue->initVsync(mScheduler->getVsyncDispatch(), *mFrameTimeline->getTokenManager(),
                           configs.late.sfWorkDuration);
   ...
}
  • getFactory().createScheduler(*mRefreshRateConfigs, *this) 第二个参数的类型是ISchedulerCallback,此处传入this,所以将SurfaceFlingger 和Scheduler相关了起来。

  • 创立好Schdueler之后,连续调用createConnection创立了一个名叫“app”的mAppConnectionHandle 和 “appSf”的mSfConnectionHandle,他们的类型是ConnectionHandle。

  • 然后调用mEventQueue->initVsync 初始化Vsync.

4.1.2. Schduler

咱们接着看看上面创立的两个ConnectionHandle创立的细节
frameworks/native/services/surfaceflinger/Scheduler/Scheduler.cpp

Scheduler::ConnectionHandle Scheduler::createConnection(
        const char* connectionName, frametimeline::TokenManager* tokenManager,
        std::chrono::nanoseconds workDuration, std::chrono::nanoseconds readyDuration,
        impl::EventThread::InterceptVSyncsCallback interceptCallback) {
    auto vsyncSource = makePrimaryDispSyncSource(connectionName, workDuration, readyDuration);
    auto throttleVsync = makeThrottleVsyncCallback();
    auto getVsyncPeriod = makeGetVsyncPeriodFunction();
    auto eventThread = std::make_unique<impl::EventThread>(std::move(vsyncSource), tokenManager,
                                                           std::move(interceptCallback),
                                                           std::move(throttleVsync),
                                                           std::move(getVsyncPeriod));
    return createConnection(std::move(eventThread));
}

先根据称号(便是app,或许appSf)调用makePrimaryDispSyncSource来生成一个DispSyncSource目标,以此目标为参数生成EventThread目标,然后调用createConnection生成一个ConnectionHandle.


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

ConnectionHandle 相关一个Connection,这个Connect持有一个经过createConnectionInternal创立出来的connect,它实际上是一个EventThreadConnection。所以能够认为Scheduler::createConnection实际上创立了一个EventThread,然后与这个EventThread了一个衔接.最终将这个联系保存到dispatcher的mConnections变量。

sp<EventThreadConnection> Scheduler::createConnectionInternal(
        EventThread* eventThread, ISurfaceComposer::EventRegistrationFlags eventRegistration) {
    return eventThread->createEventConnection([&] { resync(); }, eventRegistration);
}

调用eventThread的createEventConnection
frameworks/native/services/surfaceflinger/Scheduler/EventThread.cpp

sp<EventThreadConnection> EventThread::createEventConnection(
        ResyncCallback resyncCallback,
        ISurfaceComposer::EventRegistrationFlags eventRegistration) const {
    return new EventThreadConnection(const_cast<EventThread*>(this),
                                     IPCThreadState::self()->getCallingUid(),
                                     std::move(resyncCallback), eventRegistration);
}

创立的EventThreadConnection是一个Binder目标,所以能够同归Binder再不同进程间传递,它有两个重要办法,

  • postEvent,告诉有一个新的Vsync能够发送到UI层。
  • requestNextVsync ,UI 层跨进程告诉SurfaceFlinger准备下一次Vsync。
class EventThreadConnection : public BnDisplayEventConnection {
        virtual status_t postEvent(const DisplayEventReceiver::Event& event);
        void requestNextVsync() override; // asynchronous
        ...
}

所以EventThread也是起起着两个效果,它无限循环,然后根据需求履行postEvent或许requestNextVsync。

4.1.3. EventQueue

创立了ConnectionHandle后,后边调用了mEventQueue->initVsync。
frameworks/native/services/surfaceflinger/Scheduler/MessageQueue.cpp

void MessageQueue::initVsync(scheduler::VSyncDispatch& dispatch,
                             frametimeline::TokenManager& tokenManager,
                             std::chrono::nanoseconds workDuration) {
    setDuration(workDuration);
    mVsync.tokenManager = &tokenManager;
    mVsync.registration = std::make_unique<
            scheduler::VSyncCallbackRegistration>(dispatch,
                                                  std::bind(&MessageQueue::vsyncCallback, this,
                                                            std::placeholders::_1,
                                                            std::placeholders::_2,
                                                            std::placeholders::_3),
                                                  "sf");
}

这儿仅仅将MessageQueue::vsyncCallback这个办法与mVsync绑定,在后边mVsync.registration.schedule的时分,会触发MessageQueue::vsyncCallback办法。
mVsync是一个结构体,界说在_frameworks/native/services/surfaceflinger/Scheduler/MessageQueue.h_

struct Vsync {
        frametimeline::TokenManager* tokenManager = nullptr;
        std::unique_ptr<scheduler::VSyncCallbackRegistration> registration;
        std::mutex mutex;
        TracedOrdinal<std::chrono::nanoseconds> workDuration
                GUARDED_BY(mutex) = {"VsyncWorkDuration-sf", std::chrono::nanoseconds(0)};
        std::chrono::nanoseconds lastCallbackTime GUARDED_BY(mutex) = std::chrono::nanoseconds{0};
        bool scheduled GUARDED_BY(mutex) = false;
        std::optional<nsecs_t> expectedWakeupTime GUARDED_BY(mutex);
        TracedOrdinal<int> value = {"VSYNC-sf", 0};
    };

4.2 EventThread

EventThread是Vsync中非常重要的一个类,咱们独自来剖析一下。

4.2.1 初始化

EventThread::EventThread(std::unique_ptr<VSyncSource> vsyncSource,
                         android::frametimeline::TokenManager* tokenManager,
                         InterceptVSyncsCallback interceptVSyncsCallback,
                         ThrottleVsyncCallback throttleVsyncCallback,
                         GetVsyncPeriodFunction getVsyncPeriodFunction)
      : mVSyncSource(std::move(vsyncSource)),
        mTokenManager(tokenManager),
        mInterceptVSyncsCallback(std::move(interceptVSyncsCallback)),
        mThrottleVsyncCallback(std::move(throttleVsyncCallback)),
        mGetVsyncPeriodFunction(std::move(getVsyncPeriodFunction)),
        mThreadName(mVSyncSource->getName()) {
    LOG_ALWAYS_FATAL_IF(getVsyncPeriodFunction == nullptr,
            "getVsyncPeriodFunction must not be null");
    mVSyncSource->setCallback(this);
    mThread = std::thread([this]() NO_THREAD_SAFETY_ANALYSIS {
        std::unique_lock<std::mutex> lock(mMutex);
        threadMain(lock);
    });
   ....

结构函数里首要作了两件工作

  • 自己作为mVSyncSource的callback,当mVSyncSource上有工作时,会调用EventThread的onVSyncEvent办法,它的界说在
    frameworks/native/services/surfaceflinger/Scheduler/EventThread.h
class VSyncSource {
public:
    class Callback {
    public:
        virtual ~Callback() {}
        virtual void onVSyncEvent(nsecs_t when, nsecs_t expectedVSyncTimestamp,
                                  nsecs_t deadlineTimestamp) = 0;
    };
...
}
  • 敞开一个线程去履行threadMain办法。这是工作分发的中心办法,它无限循环,去查看pendingEvents,有的话就履行
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.
        if (!mPendingEvents.empty()) {
            event = mPendingEvents.front();
            mPendingEvents.pop_front();
            switch (event->header.type) {
                ...
                case DisplayEventReceiver::DISPLAY_EVENT_VSYNC:
                    if (mInterceptVSyncsCallback) {
                        mInterceptVSyncsCallback(event->header.timestamp);
                    }
                    break;
            }
        }
        bool vsyncRequested = false;
        // Find connections that should consume this event.
        auto it = mDisplayEventConnections.begin();
        while (it != mDisplayEventConnections.end()) {
            if (const auto connection = it->promote()) {
                vsyncRequested |= connection->vsyncRequest != VSyncRequest::None;
                if (event && shouldConsumeEvent(*event, connection)) {
                    consumers.push_back(connection);
                 }
        ...
        }
        if (!consumers.empty()) {
            dispatchEvent(*event, consumers);
            consumers.clear();
        }
       ...
        if (event) {
            continue;
        }
        // Wait for event or client registration/request.
        if (mState == State::Idle) {
            mCondition.wait(lock);
        } else {
            // Generate a fake VSYNC after a long timeout in case the driver stalls. When the
            // display is off, keep feeding clients at 60 Hz.
            const std::chrono::nanoseconds timeout =
                    mState == State::SyntheticVSync ? 16ms : 1000ms;
            if (mCondition.wait_for(lock, timeout) == std::cv_status::timeout) {
                if (mState == State::VSync) {
                    ALOGW("Faking VSYNC due to driver stall for thread %s", mThreadName);
                    std::string debugInfo = "VsyncSource debug info:\n";
                    mVSyncSource->dump(debugInfo);
                    // Log the debug info line-by-line to avoid logcat overflow
                    auto pos = debugInfo.find('\n');
                    while (pos != std::string::npos) {
                        ALOGW("%s", debugInfo.substr(0, pos).c_str());
                        debugInfo = debugInfo.substr(pos + 1);
                        pos = debugInfo.find('\n');
                    }
                }
                LOG_FATAL_IF(!mVSyncState);
                const auto now = systemTime(SYSTEM_TIME_MONOTONIC);
                const auto deadlineTimestamp = now + timeout.count();
                const auto expectedVSyncTime = deadlineTimestamp + timeout.count();
                const int64_t vsyncId = [&] {
                    if (mTokenManager != nullptr) {
                        return mTokenManager->generateTokenForPredictions(
                                {now, deadlineTimestamp, expectedVSyncTime});
                    }
                    return FrameTimelineInfo::INVALID_VSYNC_ID;
                }();
                mPendingEvents.push_back(makeVSync(mVSyncState->displayId, now,
                                                   ++mVSyncState->count, expectedVSyncTime,
                                                   deadlineTimestamp, vsyncId));
            }
        }
    }
}
  • mPendingEvents 是收到的工作,其中就包括Vsync工作DISPLAY_EVENT_VSYNC
  • mDisplayEventConnections 这个集合里边记载的是工作的顾客,也便是长途衔接过来的app,
  • dispatchEvent 将工作分发给顾客,
  • mCondition.wait,等候下一次处理。

4.2.2 mPendingEvents

这是收集到工作,工作是从那里来的,后来会再剖析。

4.2.3 mDisplayEventConnections

这是Vsync的顾客,便是长途衔接过来的app。app怎么衔接过来的,将在后边章节剖析。前面提到EventThreadConnection是继承自BnDisplayEventConnection,所以它能够重写onFirstRef办法,(当长途衔接读取到这个binder的时分会发送BC_ACQUIRE这个指令,增加服务端的引证,从而会调用到onFirstRef办法)

void EventThreadConnection::onFirstRef() {
    // NOTE: mEventThread doesn't hold a strong reference on us
    mEventThread->registerDisplayEventConnection(this);
}
status_t EventThread::registerDisplayEventConnection(const sp<EventThreadConnection>& connection) {
    std::lock_guard<std::mutex> lock(mMutex);
    // this should never happen
    auto it = std::find(mDisplayEventConnections.cbegin(),
            mDisplayEventConnections.cend(), connection);
    if (it != mDisplayEventConnections.cend()) {
        ALOGW("DisplayEventConnection %p already exists", connection.get());
        mCondition.notify_all();
        return ALREADY_EXISTS;
    }
    mDisplayEventConnections.push_back(connection);
    mCondition.notify_all();
    return NO_ERROR;
}

假如不存在这个connection,就把它参加到mDisplayEventConnections,从这儿能够看到,一旦有app衔接过来,就会成为Vsync的顾客。而且调用了mCondition.notify_all();唤醒等候的线程(便是EventThread敞开的那个线程)

4.2.4 dispatchEvent

当存在顾客也有Vsync工作的时分,就会进行分发

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) {
            copy.vsync.frameInterval = mGetVsyncPeriodFunction(consumer->mOwnerUid);
        }
        switch (consumer->postEvent(copy)) {
          ...
        }
    }
}

分发之调用的consumer->postEvent(copy),这个consumer便是上面参加的EventThreadConnection目标。它的postEvent如下:

status_t EventThreadConnection::postEvent(const DisplayEventReceiver::Event& event) {
     ...
    auto size = DisplayEventReceiver::sendEvents(&mChannel, &event, 1);
    return toStatus(size);
}

mChannel 的类型是BitTube,保存的是EventThreadConnection中记载的文件描述符,这个文件描述符会复制到衔接过来的app进程.然后调用DisplayEventReceiver::sendEvents(&mChannel, &event, 1)办法,

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

frameworks/native/libs/gui/BitTube.cpp

ssize_t BitTube::sendObjects(BitTube* tube, void const* events, size_t count, size_t objSize) {
    const char* vaddr = reinterpret_cast<const char*>(events);
    ssize_t size = tube->write(vaddr, count * objSize);
    // should never happen because of SOCK_SEQPACKET
    LOG_ALWAYS_FATAL_IF((size >= 0) && (size % static_cast<ssize_t>(objSize)),
                        "BitTube::sendObjects(count=%zu, size=%zu), res=%zd (partial events were "
                        "sent!)",
                        count, objSize, size);
    // ALOGE_IF(size<0, "error %d sending %d events", size, count);
    return size < 0 ? size : size / static_cast<ssize_t>(objSize);
}
ssize_t BitTube::write(void const* vaddr, size_t size) {
    ssize_t err, len;
    do {
        len = ::send(mSendFd, vaddr, size, MSG_DONTWAIT | MSG_NOSIGNAL);
        // cannot return less than size, since we're using SOCK_SEQPACKET
        err = len < 0 ? errno : 0;
    } while (err == EINTR);
    return err == 0 ? len : -err;
}

经过调用系统函数send向与顾客相关的文件描述符FD发送信号,所以完结Vsync的分发

4.2.5 mCondition.wait(lock);

当pendingEvents为空的时分,就会调用mCondition.wait(lock);等候有新的Vsync或许新的Client进入。这个有两个逻辑。 假如UI上一直没有恳求同步的话nextState = State::Idle;

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

那么wait是没有时刻约束的,不然的话wait有超时时刻,超时之后,会发出一个模拟的Vsync信号

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) {
                ...
                mPendingEvents.push_back(makeVSync(mVSyncState->displayId, now,
                                                   ++mVSyncState->count, expectedVSyncTime,
                                                   deadlineTimestamp, vsyncId));
            }
        }

也便是说mCondition.notify_all有许多场景,假如UI现已恳求Vsync了,可是底层并没有VSync发生的话,会生成一个Vsync参加到pendingEvents中,从而再下一次循环中dispatch出去。

5. HWComposer

HWComposer会经过HAL接口向硬件注册回调接口,这样硬件上报的Vsync就能够转发SurfaceFlinger 来处理. 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);
}

对应的结构办法是:

HWComposer::HWComposer(const std::string& composerServiceName)
      : HWComposer(std::make_unique<Hwc2::impl::Composer>(composerServiceName)) {}
HWComposer::HWComposer(std::unique_ptr<Hwc2::Composer> composer)
      : mComposer(std::move(composer)),
        ...
{}

结构的时分会一起创立一个Hwc2::impl::Composer,保存在HWComposer.mComposer字段中。这个Hwc2::impl::Composer界说在:
frameworks/native/services/surfaceflinger/DisplayHardware/ComposerHal.h

public:
    virtual ~Composer() = 0;
    virtual std::vector<IComposer::Capability> getCapabilities() = 0;
    virtual std::string dumpDebugInfo() = 0;
    virtual void registerCallback(const sp<IComposerCallback>& callback) = 0;
     ...
  }

它有一个registerCallback 注册回调

void Composer::registerCallback(const sp<IComposerCallback>& callback)
{
    android::hardware::setMinSchedulerPolicy(callback, SCHED_FIFO, 2);
    auto ret = [&]() {
        if (mClient_2_4) {
            return mClient_2_4->registerCallback_2_4(callback);
        }
        return mClient->registerCallback(callback);
    }();
    if (!ret.isOk()) {
        ALOGE("failed to register IComposerCallback");
    }
}

这个里是经过mClient_2_4来注册这个callback,这个mClient_2_4便是屏幕硬件Hwbinder的客户端,它通信的另一端便是硬件厂商依照HWbinder的接口供给的一个服务,所以到这儿便是与硬件的边界。经过把这个callback传递到硬件,咱们就能够收到硬件上的Vsync信号。经过一层一层的回调,就会回到SurfaceFlingger完结的onComposerHalVsync办法

void SurfaceFlinger::onComposerHalVsync(hal::HWDisplayId hwcDisplayId, int64_t timestamp,
                                        std::optional<hal::VsyncPeriodNanos> vsyncPeriod) {
   ...
    mScheduler->addResyncSample(timestamp, vsyncPeriod, &periodFlushed);
    if (periodFlushed) {
        modulateVsync(&VsyncModulator::onRefreshRateChangeCompleted);
    }
}

它会调用mScheduler->addResyncSample增加的一个采样时刻数据,这个采样数据经过一些算法处理后,会决议这个硬件的vsync是否需求上报到app,以及是否需求翻开和关闭硬件的Vsync. 这个算法比较复杂,这儿就不展开了。假如需求上报的话,它会把periodFlushed 这个指针设置为true

void Scheduler::addResyncSample(nsecs_t timestamp, std::optional<nsecs_t> hwcVsyncPeriod,
                                bool* periodFlushed) {
    bool needsHwVsync = false;
    *periodFlushed = false;
    { // Scope for the lock
        std::lock_guard<std::mutex> lock(mHWVsyncLock);
        if (mPrimaryHWVsyncEnabled) {
            needsHwVsync = mVsyncSchedule.controller->addHwVsyncTimestamp(timestamp, hwcVsyncPeriod,
                                                                          periodFlushed);
        }
    }
    if (needsHwVsync) {
        enableHardwareVsync();
    } else {
        disableHardwareVsync(false);
    }
}

当periodFlushed 设置为true时,持续履行modulateVsync(&VsyncModulator::onRefreshRateChangeCompleted);
frameworks/native/services/surfaceflinger/SurfaceFlinger.h

void modulateVsync(Handler handler, Args... args) {
        if (const auto config = (*mVsyncModulator.*handler)(args...)) {
            const auto vsyncPeriod = mRefreshRateConfigs->getCurrentRefreshRate().getVsyncPeriod();
            setVsyncConfig(*config, vsyncPeriod);
        }
    }

这儿的handler本质是传入的VsyncModulator::onRefreshRateChangeCompleted,处理完改写率改变之后履行setVsyncConfig

void SurfaceFlinger::setVsyncConfig(const VsyncModulator::VsyncConfig& config,
                                    nsecs_t vsyncPeriod) {
    mScheduler->setDuration(mAppConnectionHandle,
                            /*workDuration=*/config.appWorkDuration,
                            /*readyDuration=*/config.sfWorkDuration);
    mScheduler->setDuration(mSfConnectionHandle,
                            /*workDuration=*/std::chrono::nanoseconds(vsyncPeriod),
                            /*readyDuration=*/config.sfWorkDuration);
    mEventQueue->setDuration(config.sfWorkDuration);
}

这儿经过mScheduler和EventQueue的setDuration办法做了什么工作呢?

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

进一步骤用了EventThread.setDuration

void EventThread::setDuration(std::chrono::nanoseconds workDuration,
                              std::chrono::nanoseconds readyDuration) {
    std::lock_guard<std::mutex> lock(mMutex);
    mVSyncSource->setDuration(workDuration, readyDuration);
}

进一步骤用 mVSyncSource->setDuration

void DispSyncSource::setDuration(std::chrono::nanoseconds workDuration,
                                 std::chrono::nanoseconds readyDuration) {
    std::lock_guard lock(mVsyncMutex);
    mWorkDuration = workDuration;
    mReadyDuration = readyDuration;
    // If we're not enabled, we don't need to mess with the listeners
    if (!mEnabled) {
        return;
    }
    mCallbackRepeater->start(mWorkDuration, mReadyDuration);
}

mCallbackRepeater的mRegistration绑定的是DispSyncSource::onVsyncCallback,因而start办法最终会履行这个onVsyncCallback

mCallbackRepeater =
            std::make_unique<CallbackRepeater>(vSyncDispatch,
                                               std::bind(&DispSyncSource::onVsyncCallback, this,
                                                         std::placeholders::_1,
                                                         std::placeholders::_2,
                                                         std::placeholders::_3),
                                               name, workDuration, readyDuration,
                                               std::chrono::steady_clock::now().time_since_epoch());
void DispSyncSource::onVsyncCallback(nsecs_t vsyncTime, nsecs_t targetWakeupTime,
                                     nsecs_t readyTime) {
    VSyncSource::Callback* callback;
    {
        std::lock_guard lock(mCallbackMutex);
        callback = mCallback;
    }
    if (callback != nullptr) {
        callback->onVSyncEvent(targetWakeupTime, vsyncTime, readyTime);
    }
}

从而履行到DispSyncSource.mCallback.onVSyncEvent办法,而DispSyncSource.mCallback的callback本质是EventThread,

EventThread::EventThread(std::unique_ptr<VSyncSource> vsyncSource,
                         android::frametimeline::TokenManager* tokenManager,
                         InterceptVSyncsCallback interceptVSyncsCallback,
                         ThrottleVsyncCallback throttleVsyncCallback,
                         GetVsyncPeriodFunction getVsyncPeriodFunction)
      : mVSyncSource(std::move(vsyncSource)) {
        ...
    mVSyncSource->setCallback(this);
    ....
}

所以回调将进入到EventThread.onVSyncEvent办法,咱们前面介绍了,EventThread是Vsync的中心类

void EventThread::onVSyncEvent(nsecs_t timestamp, nsecs_t expectedVSyncTimestamp,
                               nsecs_t deadlineTimestamp) {
    ...
    mPendingEvents.push_back(makeVSync(mVSyncState->displayId, timestamp, ++mVSyncState->count,
                                       expectedVSyncTimestamp, deadlineTimestamp, vsyncId));
    mCondition.notify_all();
}

这儿咱们能够看到,调用了makeVSync生成一个Event并参加到mPendingEvents后边,然后调用mCondition.notify_all(),告诉等候的线程,持续履行Event的分发办法threadMain,前面现已介绍过了,这儿就不再赘述。

今后有时刻再介绍关闭和翻开Vsync这个逻辑,它相对比较简单。

6 总结

咱们这篇文章首要介绍了Vsync在SurfaceFlinger的完结原理。

  • 在SurfaceFlingger初始化时,会向HWComposer注册回调,HWComposer会经过HWBinder向硬件测注册回调。
  • SurfaceFlinger搭建好处理Vsync的基础设施,初始化Scheduler,DispVsyncSoure以及最重要的EventThread。 EventThread的threadMain办法无限循环处理pendingEvents,对Vsync类型的Event分发到顾客,经过往顾客的FD写数据,告诉APP有Vsync信号到来。pendingEvents中的音讯处理完了,分发线程等候mCondition的告诉。
  • 当HWComposer收到硬件经过HWBinder回调onVSyncEvent时,会经过SurfaceFlinger的onVSyncEvent最终调用到EventThread的onVSyncEvent,所以调用makeVSync生成Vsync的Event, 增加到pendingEvents,然后再调用mCondition.notify_all()唤起等候中的分发线程。

到这儿SurfaceFlinger就搭建好的Vsync的基础框架,但还等候客户端的恳求,这个内容将在下一篇文章中持续剖析。

重视公众号:Android老皮!!!欢迎大家来找我讨论沟通