前面一篇文章从整体介绍View绘制的流程,其中一点就是绘制的起始点就是界面收到了Vsync之后,开始新一帧的绘制,所以可以说, 是vsync触发了绘制。收到vsync信号后的处理我们已经清楚了,现在我们分析以下sync是怎么产生的,以及怎么消费的。
我们16ms这个时间应该是印象深刻了,我们经常听到在大部分屏幕的刷新频率是60Hz的情况下,那每一帧的时间就约16ms,如果应用程序在收到一次vsync信号开始绘制,16毫秒内没有绘制完毕,就会出现丢帧,卡顿。确实如此,但是这听起来却有些难以理解,绘制慢一点怎么就影响到到屏幕刷新了,它不是按照屏幕的硬件60Hz频率刷的吗?为什么会丢呢?丢了为什么会卡顿呢?究竟vsync什么时候来?
这不是本文的重点,只是作为背景知识介绍一下。假设一下以下的情况:
这3个问题就是因为生产显示数据和消费显示数据不一致导致的。因此需要将二者进行同步。
这个同步就是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的技术分析。
整体来看,Vsync的流程可以分为SurfaceFlinger 层的Vsync信号产生流程,App层的监听流程和触发流程。
下面我们沿着这个流程来看看每个环节的实现。本片文章首先分析surfaceflinger部分,介绍Vsync的架构基础
这一节里面主要会介绍到以下的内容
代码编译后,它是一个独立的可执行程序打包到镜像文件里,路径是/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 flinger = surfaceflinger::createSurfaceFlinger();
flinger->init();
// publish surface flinger
sp 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 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 {
...
}
上面的定义说明,我们可以大致认为 SurfaceFlinger对象会被注册到HWComposer去,在HWComposer端收到硬件的Vsync后,会回调SurfaceFlinger的onComposerHalVsync方法;同时SurfaceFlinger对象会被注册到Scheduler中去,在适当时候会回调setVsyncEnabled方法。下面看看是如果这些代码是关联起来的。
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.
我们接着看看上面创建的两个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(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) {
const ConnectionHandle handle = ConnectionHandle{mNextConnectionHandleId++};
ALOGV("Creating a connection handle with ID %" PRIuPTR, handle.id);
auto connection = createConnectionInternal(eventThread.get());
std::lock_guard 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 Scheduler::createConnectionInternal(
EventThread* eventThread, ISurfaceComposer::EventRegistrationFlags eventRegistration) {
return eventThread->createEventConnection([&] { resync(); }, eventRegistration);
}
调用eventThread的createEventConnection
frameworks/native/services/surfaceflinger/Scheduler/EventThread.cpp
sp EventThread::createEventConnection(
ResyncCallback resyncCallback,
ISurfaceComposer::EventRegistrationFlags eventRegistration) const {
return new EventThreadConnection(const_cast(this),
IPCThreadState::self()->getCallingUid(),
std::move(resyncCallback), eventRegistration);
}
创建的EventThreadConnection是一个Binder对象,所以可以同归Binder再不同进程间传递,它有两个重要方法,
class EventThreadConnection : public BnDisplayEventConnection {
virtual status_t postEvent(const DisplayEventReceiver::Event& event);
void requestNextVsync() override; // asynchronous
...
}
所以EventThread也是起起着两个作用,它无限循环,然后根据需要执行postEvent或者requestNextVsync。
创建了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 registration;
std::mutex mutex;
TracedOrdinal 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 expectedWakeupTime GUARDED_BY(mutex);
TracedOrdinal value = {"VSYNC-sf", 0};
};
EventThread是Vsync中非常重要的一个类,我们单独来分析一下。
EventThread::EventThread(std::unique_ptr 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 lock(mMutex);
threadMain(lock);
});
....
构造函数里主要作了两件事情
class VSyncSource {
public:
class Callback {
public:
virtual ~Callback() {}
virtual void onVSyncEvent(nsecs_t when, nsecs_t expectedVSyncTimestamp,
nsecs_t deadlineTimestamp) = 0;
};
...
}
void EventThread::threadMain(std::unique_lock& lock) {
DisplayEventConsumers consumers;
while (mState != State::Quit) {
std::optional 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));
}
}
}
}
这是收集到事件,事件是从那里来的,后来会再分析。
这是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& connection) {
std::lock_guard 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开启的那个线程)
当存在消费者也有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(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(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(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的分发
当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出去。
HWComposer会通过HAL接口向硬件注册回调接口,这样硬件上报的Vsync就可以转发SurfaceFlinger 来处理. HWComposer的创建是在这里:
frameworks/native/services/surfaceflinger/SurfaceFlingerDefaultFactory.cpp
std::unique_ptr DefaultFactory::createHWComposer(const std::string& serviceName) {
return std::make_unique(serviceName);
}
对应的构造方法是:
HWComposer::HWComposer(const std::string& composerServiceName)
: HWComposer(std::make_unique(composerServiceName)) {}
HWComposer::HWComposer(std::unique_ptr 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 getCapabilities() = 0;
virtual std::string dumpDebugInfo() = 0;
virtual void registerCallback(const sp& callback) = 0;
...
}
它有一个registerCallback 注册回调
void Composer::registerCallback(const sp& 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 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 hwcVsyncPeriod,
bool* periodFlushed) {
bool needsHwVsync = false;
*periodFlushed = false;
{ // Scope for the lock
std::lock_guard 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 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 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(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,
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这个逻辑,它相对比较简单。
我们这篇文章主要介绍了Vsync在SurfaceFlinger的实现原理。
到这里SurfaceFlinger就搭建好的Vsync的基础框架,但还等待客户端的请求,这个内容将在下一篇文章中继续分析。