Vsync可以控制系统绘图/合成的频率周期,是内容能够在正确的时机完整地显示在屏幕上
在Surfaceflinger中有一套SW-Vsync的机制,能够更灵活的控制app绘图与surfaceflinger合成的速度

从图中可以看出,DispSync接收hw-vsync作为输入,计算出Vsync的分发时机。对于其他关心硬件Vsync的组件,在指定的便宜以后发送SW-VSYNC,并且接收fence timestamp,来校准模型。当误差在接收范围内,便会关闭硬件VSYNC,只用该模型模拟的VSYNC 来控制整个系统绘制/合成速度。
于是,在这个机制当中,有两件事情就变得尤为重要:

  1. 如何建立VSYNC分发的机制
  2. 如何计算出正确分发SW-VSYNC的时机
    基于以上两点,本文将围绕以上两点进行说明:

分发

在分发的系统中,有几个比较重要的类,先来简单说明一下他们之间的关系
DispSyncSource
接收HW-Vsync,并更新计算出SW-Vsync的间隔
EventThread
接收Vsync信号,并分发给surfaceflinger 和 app等需要Vsync信号的进程
Connection
任何一个对VSYNC感兴趣都会在EventThread中抽象为一个connection

先来讲讲这个系统是怎么运转起来的
从surfacelinger 的初始化讲起
surfaceflinger::init()

void SurfaceFlinger::init() {...// Process any initial hotplug and resulting display changes.processDisplayHotplugEventsLocked();...
}

SurfaceFlinger::processDisplayHotplugEventsLocked(),在这里调用initscheduler,初始化整个Vsync系统

void SurfaceFlinger::processDisplayHotplugEventsLocked() {for (const auto& event : mPendingHotplugEvents) {...if (event.connection == hal::Connection::CONNECTED) {...if (it == mPhysicalDisplayTokens.end()) {...if (event.hwcDisplayId == getHwComposer().getInternalHwcDisplayId()) {initScheduler(state);//从这个里初始化整个VSYNC系统}mInterceptor->saveDisplayCreation(state);} else {...} else {...}...}...}...
}

在initScheduler接口中,主要做了如下几件事情

  1. 实例化Scheduler对象,命名为mScheduler
  2. create two connection,one for surfaceflinger,another for app
  3. 将VsyncDispatch绑定到messageQueue的回调函数上,名字为 " sf "
  4. onPrimaryDisplayModeChanged
    下面分析每一步到底做了些什么
void SurfaceFlinger::initScheduler(const DisplayDeviceState& displayState) {if (mScheduler) {// In practice it's not allowed to hotplug in/out the primary display once it's been// connected during startup, but some tests do it, so just warn and return.ALOGW("Can't re-init scheduler");return;}const auto displayId = displayState.physical->id;scheduler::RefreshRateConfigs::Config config ={.enableFrameRateOverride = android::sysprop::enable_frame_rate_override(false),.frameRateMultipleThreshold =base::GetIntProperty("debug.sf.frame_rate_multiple_threshold", 0)};mRefreshRateConfigs =std::make_unique<scheduler::RefreshRateConfigs>(displayState.physical->supportedModes,displayState.physical->activeMode->getId(),config);const auto currRefreshRate = displayState.physical->activeMode->getFps();mRefreshRateStats = std::make_unique<scheduler::RefreshRateStats>(*mTimeStats, currRefreshRate,hal::PowerMode::OFF);mVsyncConfiguration = getFactory().createVsyncConfiguration(currRefreshRate);mVsyncModulator = sp<VsyncModulator>::make(mVsyncConfiguration->getCurrentConfigs());// start the EventThreadmScheduler = 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);mRegionSamplingThread =new RegionSamplingThread(*this, RegionSamplingThread::EnvironmentTimingTunables());mFpsReporter = new FpsReporter(*mFrameTimeline, *this);// Dispatch a mode change request for the primary display on scheduler// initialization, so that the EventThreads always contain a reference to a// prior configuration.//// This is a bit hacky, but this avoids a back-pointer into the main SF// classes from EventThread, and there should be no run-time binder cost// anyway since there are no connected apps at this point.mScheduler->onPrimaryDisplayModeChanged(mAppConnectionHandle, displayId,displayState.physical->activeMode->getId(),vsyncPeriod);static auto ignorePresentFences =base::GetBoolProperty("debug.sf.vsync_reactor_ignore_present_fences"s, false);mScheduler->setIgnorePresentFences(ignorePresentFences ||getHwComposer().hasCapability(hal::Capability::PRESENT_FENCE_IS_NOT_RELIABLE));
}

实例化Scheduler对象,命名为mScheduler

在surfaceflingerdefaultfacroty中真正去实例化Scheduler对象,这里的 callback = surfaceflinger

std::unique_ptr<Scheduler> DefaultFactory::createScheduler(const scheduler::RefreshRateConfigs& configs, ISchedulerCallback& callback) {return std::make_unique<Scheduler>(configs, callback);
}

Scheduler共有三个不同的构造函数,在实例化对象的时候差不多是一个从上到下的调用关系,初始化一些必要的成员变量。为了叙述方便,从上到下依次成为 C1,C2, C3。

//C1
Scheduler::Scheduler(const scheduler::RefreshRateConfigs& configs, ISchedulerCallback& callback): Scheduler(configs, callback,{.supportKernelTimer = sysprop::support_kernel_idle_timer(false),.useContentDetection = sysprop::use_content_detection_for_refresh_rate(false)}) {}

在C2中,调用了createVsyncSchedule,在其中创建和初始化了和VSync信号产生、分发相关的类对象和运行逻辑。tracker,dispatch,VsyncReactor对象实例化,返回VsyncScheduler结构体对象

Scheduler::VsyncSchedule Scheduler::createVsyncSchedule(bool supportKernelTimer) {auto clock = std::make_unique<scheduler::SystemClock>();auto tracker = createVSyncTracker();auto dispatch = createVSyncDispatch(*tracker);// TODO(b/144707443): Tune constants.constexpr size_t pendingFenceLimit = 20;auto controller =std::make_unique<scheduler::VSyncReactor>(std::move(clock), *tracker, pendingFenceLimit,supportKernelTimer);return {std::move(controller), std::move(tracker), std::move(dispatch)};
}
//C2
Scheduler::Scheduler(const scheduler::RefreshRateConfigs& configs, ISchedulerCallback& callback,Options options): Scheduler(createVsyncSchedule(options.supportKernelTimer), configs, callback,createLayerHistory(configs), options) {using namespace sysprop;const int setIdleTimerMs = base::GetIntProperty("debug.sf.set_idle_timer_ms"s, 0);if (const auto millis = setIdleTimerMs ? setIdleTimerMs : set_idle_timer_ms(0); millis > 0) {const auto callback = mOptions.supportKernelTimer ? &Scheduler::kernelIdleTimerCallback: &Scheduler::idleTimerCallback;mIdleTimer.emplace("IdleTimer", std::chrono::milliseconds(millis),[this, callback] { std::invoke(callback, this, TimerState::Reset); },[this, callback] { std::invoke(callback, this, TimerState::Expired); });mIdleTimer->start();}if (const int64_t millis = set_touch_timer_ms(0); millis > 0) {// Touch events are coming to SF every 100ms, so the timer needs to be higher than thatmTouchTimer.emplace("TouchTimer", std::chrono::milliseconds(millis),[this] { touchTimerCallback(TimerState::Reset); },[this] { touchTimerCallback(TimerState::Expired); });mTouchTimer->start();}if (const int64_t millis = set_display_power_timer_ms(0); millis > 0) {mDisplayPowerTimer.emplace("DisplayPowerTimer", std::chrono::milliseconds(millis),[this] { displayPowerTimerCallback(TimerState::Reset); },[this] { displayPowerTimerCallback(TimerState::Expired); });mDisplayPowerTimer->start();}
}
//C3
Scheduler::Scheduler(VsyncSchedule schedule, const scheduler::RefreshRateConfigs& configs,ISchedulerCallback& schedulerCallback,std::unique_ptr<LayerHistory> layerHistory, Options options): mOptions(options),mVsyncSchedule(std::move(schedule)),mLayerHistory(std::move(layerHistory)),mSchedulerCallback(schedulerCallback),mRefreshRateConfigs(configs),mPredictedVsyncTracer(base::GetBoolProperty("debug.sf.show_predicted_vsync", false)? std::make_unique<PredictedVsyncTracer>(*mVsyncSchedule.dispatch): nullptr) {mSchedulerCallback.setVsyncEnabled(false);
}

create two connection,one for surfaceflinger,another for app

接下来看看在createconnection中具体做了些什么(以 " appsf "为例)
这里解释一下一些变量的含义
workduration:client完成工作的时长,例如surfaceflinger完成一帧合成的时间
readyduration:对于app来说,完成一帧显示还要考虑sf合成的时间,因此这个值 = sf workduration;对于sf 来说,为0
earliestVsync:目标显示时间,the target display time。因此,callback应该在 earliestVsync 前 workduration + readyduration ns 前被dispatch

首先在 makePrimaryDispSyncSource 接口中 实例化了DispSyncSource对象,然后实例化了EventThread对象

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

DispSyncSource构造函数中,vSyncDispatch为前面Scheduler中创建的对象。这里可以看到,传进来的name = “appsf”, 在mValue中被保存为了 “VSYNC-appsf”,这也与dump出来的结果是一致的。
然后还新建了一个CallbackRepeater对象

DispSyncSource::DispSyncSource(scheduler::VSyncDispatch& vSyncDispatch,std::chrono::nanoseconds workDuration,std::chrono::nanoseconds readyDuration, bool traceVsync,const char* name): mName(name),mValue(base::StringPrintf("VSYNC-%s", name), 0),mTraceVsync(traceVsync),mVsyncOnLabel(base::StringPrintf("VsyncOn-%s", name)),mWorkDuration(base::StringPrintf("VsyncWorkDuration-%s", name), workDuration),mReadyDuration(readyDuration) {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());
}

来看看CallbackRepeater构造函数中做了些什么,
将DispSyncSource::onVsyncCallback 作为 callback函数保存下来

CallbackRepeater(VSyncDispatch& dispatch, VSyncDispatch::Callback cb, const char* name,std::chrono::nanoseconds workDuration, std::chrono::nanoseconds readyDuration,std::chrono::nanoseconds notBefore): mName(name),mCallback(cb),mRegistration(dispatch,std::bind(&CallbackRepeater::callback, this, std::placeholders::_1,std::placeholders::_2, std::placeholders::_3),mName),mStarted(false),mWorkDuration(workDuration),mReadyDuration(readyDuration),mLastCallTime(notBefore) {}

并新建了一个 VSyncCallbackRegistration 对象,从这里可以看到,调用到了VSyncDispatchTimerQueue(为VsyncDispatch的实现类)的registercallback中,

VSyncCallbackRegistration::VSyncCallbackRegistration(VSyncDispatch& dispatch,VSyncDispatch::Callback const& callbackFn,std::string const& callbackName): mDispatch(dispatch),mToken(dispatch.registerCallback(callbackFn, callbackName)),mValidToken(true) {}

回调函数是DispSyncSource::onVsyncCallback ,name = " appsf"

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

到这里,回调函数的绑定基本就结束了
我们再回头看看第二件事,实例化EventThread对象

auto eventThread = std::make_unique<impl::EventThread>(std::move(vsyncSource), tokenManager,std::move(interceptCallback),std::move(throttleVsync),std::move(getVsyncPeriod));

看看EventThread的构造函数中做了什么
除了一些必要的成员变量赋值之外,还做了另外一件事,就是将eventthread 线程运行起来,入口函数为ThreadMain,并设置了线程优先级

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);});pthread_setname_np(mThread.native_handle(), mThreadName);pid_t tid = pthread_gettid_np(mThread.native_handle());// Use SCHED_FIFO to minimize jitterconstexpr int EVENT_THREAD_PRIORITY = 2;struct sched_param param = {0};param.sched_priority = EVENT_THREAD_PRIORITY;if (pthread_setschedparam(mThread.native_handle(), SCHED_FIFO, &param) != 0) {ALOGE("Couldn't set SCHED_FIFO for EventThread");}set_sched_policy(tid, SP_FOREGROUND);
}

再来看看ThreadMain中的实现

  1. 如果有消息,对不同的消息有不同的处理。
    当收到connect的hotplug信号,并且mVSyncState不存在时,将对应的消息保存下来,在后面统一处理;
    当收到disconnect的hotplug信号,并且存在mVSyncState时,将对应display从mVSyncState 删去。
    这里的mVSyncState 记录的就是display的状态,即如果display连接后,mVSyncState 必不为空,反之为空
    当收到Vsync event时,这里的callback在createconnection中设置下来的,在“appsf”中对应 mInterceptor->saveVSyncEvent(timestamp);即把vsync消息保存下来
  2. 然后逐个寻找对应的consumer,找到之后dispatchEvent
  3. 后面更新线程状态,并通过线程状态判断是否需要产生 fake Vsync
  4. 值得一提的是,线程刚开始循环时,会block在mCondition.wait(lock);处,直到有connecction连接。
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_HOTPLUG:// 当收到connect的hotplug信号,并且mVSyncState不存在时,将对应的消息保存下来,在后面统一处理if (event->hotplug.connected && !mVSyncState) {mVSyncState.emplace(event->header.displayId);//当收到disconnect的hotplug信号,并且存在mVSyncState时,将对应display从mVSyncState 删去} else if (!event->hotplug.connected && mVSyncState &&mVSyncState->displayId == event->header.displayId) {mVSyncState.reset();}break;case DisplayEventReceiver::DISPLAY_EVENT_VSYNC:if (mInterceptVSyncsCallback) {//这里的callback在createconnection中设置下来的,在“appsf”中对应mInterceptor->saveVSyncEvent(timestamp);//即把vsync消息保存下来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);}++it;} else {it = mDisplayEventConnections.erase(it);}}if (!consumers.empty()) {dispatchEvent(*event, consumers);consumers.clear();}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;}if (mState != nextState) {if (mState == State::VSync) {mVSyncSource->setVSyncEnabled(false);} else if (nextState == State::VSync) {mVSyncSource->setVSyncEnabled(true);}mState = nextState;}if (event) {continue;}// Wait for event or client registration/request.if (mState == State::Idle) {// 刚开始时会block在此处,直到有connection连接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 overflowauto 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));}}}
}

那什么时候有connection连接进来呢,在createConnectionInternal中,调用eventThread->createEventConnection接口进行connection连接。

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

在这个接口中,创建了一个新的对象,EventThreadConnection

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

构造函数中做了简单的成员变量赋值
并在onFirstRef接口中去registerconnection

EventThreadConnection::EventThreadConnection(EventThread* eventThread, uid_t callingUid, ResyncCallback resyncCallback,ISurfaceComposer::EventRegistrationFlags eventRegistration): resyncCallback(std::move(resyncCallback)),mOwnerUid(callingUid),mEventRegistration(eventRegistration),mEventThread(eventThread),mChannel(gui::BitTube::DefaultSize) {}void EventThreadConnection::onFirstRef() {// NOTE: mEventThread doesn't hold a strong reference on usmEventThread->registerDisplayEventConnection(this);
}

registerDisplayEventConnection接口中,首先是将connection加入队列中,并通过mCondition.notify_all();通知线程解除block,即前面所说的block在mCondition.wait()

status_t EventThread::registerDisplayEventConnection(const sp<EventThreadConnection>& connection) {std::lock_guard<std::mutex> lock(mMutex);// this should never happenauto 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;
}

将VsyncDispatch绑定到messageQueue的回调函数上,名字为 " sf "

接下来介绍一下messagequeue中回调函数的绑定过程
这里实例化了VSyncCallbackRegistration对象,与注册回调的流程相似,将MessageQueue::vsyncCallback作为回调函数设置下去,name 为 " sf " ,最终在VSyncDispatchTimerQueue中回调。

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

onPrimaryDisplayModeChanged

我们最后来看看onPrimaryDisplayModeChanged做了些什么
看代码,最后发现调用到了EventThread的onModeChanged

void Scheduler::onPrimaryDisplayModeChanged(ConnectionHandle handle, PhysicalDisplayId displayId,DisplayModeId modeId, nsecs_t vsyncPeriod) {{std::lock_guard<std::mutex> lock(mFeatureStateLock);// Cache the last reported modes for primary display.mFeatures.cachedModeChangedParams = {handle, displayId, modeId, vsyncPeriod};// Invalidate content based refresh rate selection so it could be calculated// again for the new refresh rate.mFeatures.contentRequirements.clear();}onNonPrimaryDisplayModeChanged(handle, displayId, modeId, vsyncPeriod);
}
void Scheduler::onNonPrimaryDisplayModeChanged(ConnectionHandle handle, PhysicalDisplayId displayId,DisplayModeId modeId, nsecs_t vsyncPeriod) {android::EventThread* thread;{std::lock_guard<std::mutex> lock(mConnectionsLock);RETURN_IF_INVALID_HANDLE(handle);thread = mConnections[handle].thread.get();}thread->onModeChanged(displayId, modeId, vsyncPeriod);
}

onModeChanged中,会自己生成一个event,并加入到列表中,然后通知threadmain去处理,通过dispatchEvent去分发

void EventThread::onModeChanged(PhysicalDisplayId displayId, DisplayModeId modeId,nsecs_t vsyncPeriod) {std::lock_guard<std::mutex> lock(mMutex);mPendingEvents.push_back(makeModeChanged(displayId, modeId, vsyncPeriod));mCondition.notify_all();
}

这里的consumer实际就是EventThreadConnection,通过这个connection回调

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)) {case NO_ERROR:break;case -EAGAIN:// TODO: Try again if pipe is full.ALOGW("Failed dispatching %s for %s", toString(event).c_str(),toString(*consumer).c_str());break;default:// Treat EPIPE and other errors as fatal.removeDisplayEventConnectionLocked(consumer);}}
}

通过displayevetreceiver的sendEvents接口分发消息

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

到这里我们再来聊一聊前面说到的tracker,dispatch,VsyncReactor三个类
这三个类都是接口类,真正的实现在别的类中
VSyncTracker:实现类为VSyncPredictor,根据采样的硬件VSync,建立一个模拟的VSync模型,基于历史Vsync时间数据来预测未来Vsync信号发生的时间点
VSyncDispatch:实现类为VSyncDispatchTimerQueue,分发VSync回调事件
VsyncController:实现类为VSyncReactor,配合VSyncTracker进行硬件VSync的采样

计算

计算的过程稍微有点复杂,研究明白了再更新

Android12 SurfaceFlinger Vsync相关推荐

  1. Android SurfaceFlinger vsync信号产生与分发

    原址 以下分析基于android 4.4代码 vsync信号的产生.分发涉及到以下几个类,先主要了解下他们各自的功能: HWComposer:产生hardware vsync,post fb VSyn ...

  2. Android SurfaceFlinger SW Vsync模型

    Android SurfaceFlinger Vsync这块比较复杂,最初在看这块的时候,迟迟不知道从何入手,网上看了各种SurfaceFlinger Vsync相关的博客,个人感觉紧紧是把代码流程给 ...

  3. SurfaceFlinger启动-Android12

    SurfaceFlinger启动-Android12 android12-release 1. surfaceflinger.rc文件 由init进程所启动的守护进程,在init.rc中该服务如下su ...

  4. Android SurfaceFlinger 学习之路(五)----VSync 工作原理

    原址 VSync信号的科普我们上一篇已经介绍过了,这篇我们要分析在SurfaceFlinger中的作用.(愈发觉得做笔记对自己记忆模块巩固有很多帮助,整理文章不一定是用来给别人看的,但一定是为加强自己 ...

  5. SurfaceFlinger模块-VSYNC研究

    Vsync信号是SurfaceFlinger进程中核心的一块逻辑,我们主要从以下几个方面着手讲解. 软件Vsync是怎么实现的,它是如何保持有效性的? systrace中看到的VSYNC信号如何解读, ...

  6. android vsync信号间隔,Android SurfaceFlinger服务(五) ----- VSync信号的产生

    Android为了增强界面流畅度引入了VSync机制.VSync信号一般由硬件产生,为了兼容一些老的机器,也可以软件产生.因些,就可以分为硬件VSync和软件VSync.VSync的生成逻辑主要在HW ...

  7. android surfaceflinger 老罗,「Android」SurfaceFlinger分析

    本篇针对surfaceFlinger模块进行分析,目录如下: 1.SurfaceFlinger功能 1.1.BufferQueue原理(native/libs/gui模块) 1.2   layer显示 ...

  8. SurfaceFlinger 和 Hardware Composer

    拥有图形数据缓冲区是很精彩的,但是当你在你的设备屏幕上看到它们时生活甚至更美好.那就是 SurfaceFlinger 和 Hardware Composer HAL 做的事情. SurfaceFlin ...

  9. I.MX6 Surfaceflinger 机制

    /***************************************************************************** I.MX6 Surfaceflinger ...

最新文章

  1. java 异常的捕获及处理
  2. MDK5.29,5.30,5.31,5.32,5.33和各种pack软件包镜像下载
  3. 为什么 MySQL的常用引擎都默认使用 B+ 树作为索引?
  4. Uva10294 Arif in Dhaka (置换问题)
  5. POJ 1505(二分+贪心)
  6. Orion算法:GOOGLE干掉百度的核武器?
  7. react-native run-android报错的原因,SDK位置未指定
  8. C++ float的内存布局
  9. .NET Core 3.0 新 JSON API - JsonDocument
  10. TFS2010映射工作区问题 路径 XXX 已在工作区 XXX;XXX 中映射
  11. 【Elasticsearch】Elasticsearch之元数据(meta-fields)介绍
  12. vscode-更换图标主题VSCode Icons.
  13. zul组件、zhtml组件、native组件的区别
  14. Python打包exe文件方法汇总【4种】
  15. 打开我的电脑的快捷键
  16. Unity 之 ShaderGraph 护盾
  17. WMS仓储管理系统定制
  18. 虚拟动力数字人技术亮相第六届文创产业大会,探见元宇宙 驱动新文创
  19. 实时视频应用之QoS关键技术分析
  20. H.264与x264的区别

热门文章

  1. 3年,从双非到百度的学习经验总结
  2. 简单工厂模式和工厂方法模式的区别
  3. 关于手机的IMEI号问题的一些总结
  4. C# 中 TextBox 换行的方法
  5. “OneFlow U” 2020年度社区之星——吴文童
  6. 陈景润“1+2”定理与黎曼“1/2”猜想
  7. c++11 chrono全面解析(最高可达纳秒级别的精度)
  8. paper plane fly away
  9. JFreeChart应用
  10. Nodejs 天涯帖子《鹿鼎记中计》 柳成萌著 下载爬虫