前面一篇文章从整体介绍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老皮!!!欢迎大家来找我讨论沟通