必读:

Android 12(S) 图像显示系统 - 开篇


1 前言

这一篇文章,将继续讲解有关VSync的知识,前一篇文章 Android 12(S) 图像显示系统 - SurfaceFlinger之VSync-上篇(十六)中,主要是分析了SurfaceFlinger启动后VSync的一些初始化流程,以及vsync events的分发逻辑。

vsync events汇集到了两个地方:

1. MessageQueue::vsyncCallback  ==> VSYNC-sf

2. EventThread::onVSyncEvent  ==> VSYNC-app  & VSYNC-appSf

本篇中,将从一个简单的demo出发,来具体分析,vsync events是如何传递到  ==> 真正需要的地方

2 可以监测vsync event的应用

2.1 代码位置

代码存放到了GitHub,自取哦

https://github.com/yrzroger/DisplayEventTracker

2.2 如何使用

1. 下载代码放到android源码目录下

2. 执行 mm 编译得到可执行档 DisplayEventTracker

3. 将 DisplayEventTracker,adb push 到测试板的 /system/bin/ 目录下

4. 在console下执行 DisplayEventTracker -h,可以查看简单的命令说明

usage: DisplayEventTracker [options]
------------------------------------ options ---------------------------------------------
[-i] vsync rate(default:1)
[-h] help
input 'r' to call requestNextVsync or input 'q' to exit when running
------------------------------------------------------------------------------------------

5. 示例命令

DisplayEventTracker          // 默认vsync rate = 1, 每个vsync到来时都会收到该event
DisplayEventTracker -i 3 //表示vsync rate = 3, 每3个vsync才会通知一次
DisplayEventTracker -i 0 //除非调用requestNextVsync,否则不会收到vsync event,此时可以输入‘r’来调用requestNextVsync

2.3 执行结果展示

我的测试板默认的屏幕刷新率是60Hz,一个VSync间隔是16.67ms

结果一:默认setVsyncRate(1),每一个vsync event都会都到,可以看结果Vsync period大约是16.68ms

root:/ $ DisplayEventTracker
Vsync received: count=149
Vsync received: count=150 16.687281 ms (59.925879 Hz)
Vsync received: count=151 16.687281 ms (59.925879 Hz)
Vsync received: count=152 16.687281 ms (59.925879 Hz)
Vsync received: count=153 16.687281 ms (59.925879 Hz)
Vsync received: count=154 16.687281 ms (59.925879 Hz)
Vsync received: count=155 16.687281 ms (59.925879 Hz)

结果二:setVsyncRate(6),每间隔6个vsync events才投递一次

root:/ $ DisplayEventTracker -i 6
Vsync received: count=540
Vsync received: count=546 100.102455 ms (9.989765 Hz)
Vsync received: count=552 100.102455 ms (9.989765 Hz)
Vsync received: count=558 100.102455 ms (9.989765 Hz)
Vsync received: count=564 100.102455 ms (9.989765 Hz)
Vsync received: count=570 100.102455 ms (9.989765 Hz)
Vsync received: count=576 100.102455 ms (9.989765 Hz)
Vsync received: count=582 100.102455 ms (9.989765 Hz)

结果三:setVsyncRate(0),每次调用requestNextVsync()后才收到一次vsync event

root:/ $ DisplayEventTracker -i 6
130|RealtekStark:/ $ DisplayEventTracker -i 0
r
Vsync received: count=797
r
Vsync received: count=801 583.896606 ms (1.712632 Hz)
r
Vsync received: count=803 583.900635 ms (1.712620 Hz)
r
Vsync received: count=805 633.949219 ms (1.577413 Hz)
r
Vsync received: count=807 2002.051880 ms (0.499488 Hz)
r
Vsync received: count=809 1951.946533 ms (0.512309 Hz)

3 示例Demo源码解析

3.1 DisplayEventTracker类的定义

DisplayEventTracker定义很简单,继承自Thread,这意味着它可以开启一个独立的新线程,并在新线程中执行threadLoop()中的处理逻辑。

class DisplayEventTracker : public Thread
{
public:
explicit DisplayEventTracker(int vsyncRate); // 构造函数
virtual ~DisplayEventTracker(); // 析构函数 void requestNextVsync(); // 请求下一个 vsync event private:
virtual bool threadLoop();
virtual status_t readyToRun();
void processDisplayEvents(); // Display event handling
class DisplayEventCallback; // LooperCallback的实现类 std::unique_ptr<DisplayEventReceiver> mDisplayEventReceiver; // 接收 display events的核心成员
sp<Looper> mLooper;
int mVsyncRate; // 投递 vsync events的间隔、频率
};

3.2 DisplayEventTracker::readyToRun完成一些初始化设置,设置监听和回调

status_t DisplayEventTracker::readyToRun() {
// Register a display event receiver
// To receive ModeChanged and/or FrameRateOverrides events specify this in the constructor.
mDisplayEventReceiver = std::make_unique<DisplayEventReceiver>(); // 创建 DisplayEventReceiver 对象
status_t status = mDisplayEventReceiver->initCheck(); // 检查 DisplayEventReceiver 初始化成功
if(status != NO_ERROR)
printf("Initialization of DisplayEventReceiver failed with status: %d", status); mLooper->addFd(mDisplayEventReceiver->getFd(), 0, Looper::EVENT_INPUT, // 添加待监测的fd,并设置回调 DisplayEventCallback()
new DisplayEventCallback(), mDisplayEventReceiver.get()); //mDisplayEventReceiver.get()指针作为回调时传递给回调方法的数据
// setVsyncRate() sets the Event::VSync delivery rate.
// A value of 1 returns every Event::VSync.
// A value of 2 returns every other event, etc...
// a value of 0 returns no event unless requestNextVsync() has been called.
mDisplayEventReceiver->setVsyncRate(mVsyncRate); // 设置投递 vsync event的频率 return NO_ERROR;
}

3.3 新线程开启,DisplayEventTracker::threadLoop中等待事件发生

bool DisplayEventTracker::threadLoop() {
processDisplayEvents();
return true;
} void DisplayEventTracker::processDisplayEvents() {
// This will poll mDisplayEventReceiver and if there are new events it'll call
// displayEventCallback synchronously.
mLooper->pollOnce(-1);// 阻塞等待事件发生
}

threadLooper返回true,所以会反复执行。


上面的逻辑就是典型的 Android Native Looper 机制,不熟悉的可以参见文章:

Android Native -- Message/Handler/Looper机制(原理篇)

Android Native -- Message/Handler/Looper机制(应用篇)


3.4 vsync event到来时,回调 handleEvent

class DisplayEventTracker::DisplayEventCallback : public LooperCallback {
nsecs_t oldTimeStamp; // 记录前一个vsync的时间
public:
DisplayEventCallback(): oldTimeStamp(0) {} int handleEvent(int /* fd */, int /*events*/, void* data) {
DisplayEventReceiver* displayEventReceiver = (DisplayEventReceiver*)data;
constexpr int kBufferSize = 100;
DisplayEventReceiver::Event buffer[kBufferSize];
ssize_t numEvents;
do {
numEvents = displayEventReceiver->getEvents(buffer, kBufferSize); // 获取事件
for (size_t i = 0; i < static_cast<size_t>(numEvents); i++) {
const auto& event = buffer[i];
if (event.header.type == DisplayEventReceiver::DISPLAY_EVENT_HOTPLUG) { // 热插拔事件
printf("Hotplug received: %s\n", event.hotplug.connected?"connected":"disconnected");
} if(event.header.type == DisplayEventReceiver::DISPLAY_EVENT_VSYNC) { // vsync 事件
printf("Vsync received: count=%d\t", event.vsync.count); // 打印计数
if (oldTimeStamp) {
float t = float(event.header.timestamp - oldTimeStamp) / s2ns(1);
printf("%f ms (%f Hz)\n", t*1000, 1.0/t); //打印 vsync 事件间隔
} else {
printf("\n");
}
oldTimeStamp = event.header.timestamp; // 记录事件
} if(event.header.type == DisplayEventReceiver::DISPLAY_EVENT_MODE_CHANGE) { // 模式变化事件
printf("Mode change received\n");
} }
} while (numEvents > 0); return 1; // keep the callback
}
};

小结:

demo的整体流程是非常简单的,本质就是通过Looper去监测DisplayEventReceiver::getFd()中的fd,当fd上有事件发生时,就会回调到我们设置的函数。然后就可以从DisplayEventReceiver中getEvents获取事件,判断事件类型进行对应处理了

DisplayEventReceiver由是个啥东东?它为什么可以收到vsync event呢?莫急,稍后分析


4 DisplayEventReceiver相关原理分析

DisplayEventReceiver创建并注册与SurfaceFlinger的事件连接。可用来监测VSync、HotPlug、ModeChange、FrameRateOverride事件。

4.1 类定义

4.2 主要方法解释

DisplayEventReceiver构造函数

可以根据需求来指定VsyncSource,并设置EventRegistrationFlags来决定是否接收ModeChanged和FrameRateOverrides事件。

[/frameworks/native/libs/gui/include/gui/ISurfaceComposer.h]
enum VsyncSource {
eVsyncSourceApp = 0,
eVsyncSourceSurfaceFlinger = 1
}; enum class EventRegistration {
modeChanged = 1 << 0,
frameRateOverride = 1 << 1,
};

status_t setVsyncRate(uint32_t count)

设置投递vsync events的频率,设置1代表每个vsync event均被投递,设置2代表每隔一个投递一次,依次类推 ...

设置0代表只有调用requestNextVsync()后才会投递一次vsync event

status_t requestNextVsync()

请求下一个vsync event,在vsync rate大于0的时候,这个函数调用无效

int getFd() const

获取用于接收事件的文件描述符

ssize_t getEvents(Event* events, size_t count)

当监测到有事件发生时,通过它获取具体的事件列表,函数返回值就是事件的数量

ssize_t sendEvents(Event const* events, size_t count)

发送事件,函数返回值就是事件的数量

本文作者@二的次方  2022-04-27 发布于博客园

4.3 DisplayEventReceiver工作原理,事件是怎么传递过来的?

先看看它的构造函数的具体实现

[/frameworks/native/libs/gui/DisplayEventReceiver.cpp]
DisplayEventReceiver::DisplayEventReceiver(
ISurfaceComposer::VsyncSource vsyncSource,
ISurfaceComposer::EventRegistrationFlags eventRegistration) {
sp<ISurfaceComposer> sf(ComposerService::getComposerService()); // 获取SurfaceFLinger服务
if (sf != nullptr) {
mEventConnection = sf->createDisplayEventConnection(vsyncSource, eventRegistration); // 创建远程事件连接
if (mEventConnection != nullptr) {
mDataChannel = std::make_unique<gui::BitTube>();
mEventConnection->stealReceiveChannel(mDataChannel.get()); // 传递 BitTube
}
}
}

核心的处理应该是createDisplayEventConnectionstealReceiveChannel,下面分别看看这两个操作具体做了啥子

4.3.1 SurfaceFlinger::createDisplayEventConnection

这个方法通过Binder IPC跨进程,一路飞奔,直到SurfaceFlinger核心服务 SurfaceFlinger::createDisplayEventConnection

[/frameworks/native/services/surfaceflinger/SurfaceFlinger.cpp]
sp<IDisplayEventConnection> SurfaceFlinger::createDisplayEventConnection(
ISurfaceComposer::VsyncSource vsyncSource,
ISurfaceComposer::EventRegistrationFlags eventRegistration) {
const auto& handle = // 判断选哪个 vsyncSource
vsyncSource == eVsyncSourceSurfaceFlinger ? mSfConnectionHandle : mAppConnectionHandle;
// 创建 DisplayEventConnection
return mScheduler->createDisplayEventConnection(handle, eventRegistration);
}

mSfConnectionHandlemAppConnectionHandle是在initScheduler时创建的scheduler::ConnectionHandle对象,前一篇文章中有分析过。

通过这两个handle可以在Scheduler::mConnections中找到和他们分别对应的Connection,即

    // Stores EventThread associated with a given VSyncSource, and an initial EventThreadConnection.
struct Connection {
sp<EventThreadConnection> connection;
std::unique_ptr<EventThread> thread;
};

4.3.2 Scheduler::createDisplayEventConnection

先看代码

[/frameworks/native/services/surfaceflinger/Scheduler/Scheduler.cpp]
sp<IDisplayEventConnection> Scheduler::createDisplayEventConnection(
ConnectionHandle handle, ISurfaceComposer::EventRegistrationFlags eventRegistration) {
std::lock_guard<std::mutex> lock(mConnectionsLock);
RETURN_IF_INVALID_HANDLE(handle, nullptr);
return createConnectionInternal(mConnections[handle].thread.get(), eventRegistration);
}

根据handle,从Scheduler::mConnections取出对应的EventThread对象,继续调用 Scheduler::createConnectionInternal

[/frameworks/native/services/surfaceflinger/Scheduler/Scheduler.cpp]
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对象,并返回给调用者。如下图继承关系,保证了DisplayEventReceiver可以取得EventThreadConnection对象的远程代理,保存在成员sp<IDisplayEventConnection> mEventConnection

流程继续,创建EventThreadConnection对象,第一次被引用时会进到onFirstRef中进行注册

void EventThreadConnection::onFirstRef() {
// NOTE: mEventThread doesn't hold a strong reference on us
mEventThread->registerDisplayEventConnection(this);
}

再转到EventThread::registerDisplayEventConnection中,就是把这个connecttion保存到EventThread::mDisplayEventConnections

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);// 保存到 mDisplayEventConnections 这个vector数组中
mCondition.notify_all();
return NO_ERROR;
}

DisplayEventReceiver已经和SurfaceFlinger服务端的Scheduler建立了关系,再回到DisplayEventReceiver的构造函数接着分析下面的操作

[/frameworks/native/libs/gui/DisplayEventReceiver.cpp]
// DisplayEventReceiver构造函数
mDataChannel = std::make_unique<gui::BitTube>();
mEventConnection->stealReceiveChannel(mDataChannel.get()); // 传递跨进程数据传递的对象 BitTube

下一步创建了一个BitTube对象,然后调用了mEventConnection->stealReceiveChannel这个方法会走到

[/frameworks/native/services/surfaceflinger/Scheduler/EventThread.cpp ]
status_t EventThreadConnection::stealReceiveChannel(gui::BitTube* outChannel) {
outChannel->setReceiveFd(mChannel.moveReceiveFd());// resets this BitTube's receive file descriptor to receiveFd
outChannel->setSendFd(base::unique_fd(dup(mChannel.getSendFd()))); // resets this BitTube's send file descriptor to sendFd
return NO_ERROR;
}

这使用到BitTube的跨进程传递数据的方式,基本原理可以参考:Android 12(S) 图像显示系统 - 基础知识之 BitTube


到这里,我们可以清晰的看到,DisplayEventReceiver与SurfaceFlinger建立起来了一条跨进程传递事件的通道:BitTube中封装的socketpair (receive fd  & send fd)


4.4 事件的传递、分发

通信线路已建立,接下来就要把事件经过这条道路向外传递了。

上一篇文章中曾讲到过

收到vsync events的汇集到了两个地方:

1. MessageQueue::vsyncCallback  ==> VSYNC-sf

2. EventThread::onVSyncEvent  ==> VSYNC-app  & VSYNC-appSf

我们这里只看EventThread::onVSyncEvent

[/frameworks/native/services/surfaceflinger/Scheduler/EventThread.cpp]
void EventThread::onVSyncEvent(nsecs_t timestamp, nsecs_t expectedVSyncTimestamp,
nsecs_t deadlineTimestamp) {
...
// 包装为 DisplayEventReceiver::Event对象,存入 mPendingEvents 尾部
mPendingEvents.push_back(makeVSync(mVSyncState->displayId, timestamp, ++mVSyncState->count,
expectedVSyncTimestamp, deadlineTimestamp, vsyncId));
mCondition.notify_all();
}

EventThread收到 vsync event回调事件后,放入mPendingEvents这个待处理的事件队列中,然后唤醒等待的处理线程,即在EventThread::threadMain

[/frameworks/native/services/surfaceflinger/Scheduler/EventThread.cpp]
void EventThread::threadMain(std::unique_lock<std::mutex>& lock) {
// using DisplayEventConsumers = std::vector<sp<EventThreadConnection>>;
DisplayEventConsumers consumers; // consumers是一个EventThreadConnection数组 while (mState != State::Quit) {
std::optional<DisplayEventReceiver::Event> event; // Determine next event to dispatch.
if (!mPendingEvents.empty()) {
event = mPendingEvents.front(); // 取出 mPendingEvents 头部第一个待处理的 event
mPendingEvents.pop_front(); // 删除开头元素 switch (event->header.type) { // 判断是什么类型的事件
case DisplayEventReceiver::DISPLAY_EVENT_HOTPLUG: // 热插拔事件
if (event->hotplug.connected && !mVSyncState) {
mVSyncState.emplace(event->header.displayId);
} else if (!event->hotplug.connected && mVSyncState &&
mVSyncState->displayId == event->header.displayId) {
mVSyncState.reset();
}
break; case DisplayEventReceiver::DISPLAY_EVENT_VSYNC: // VSYNC 事件
if (mInterceptVSyncsCallback) {
// mInterceptVSyncsCallback 是在SurfaceFlinger::initScheduler中createConnection时一路传递过来的
// 这个回调会通知到SurfaceFlinger
mInterceptVSyncsCallback(event->header.timestamp);
}
break;
}
} bool vsyncRequested = false; // Find connections that should consume this event.
auto it = mDisplayEventConnections.begin(); // mDisplayEventConnections 中保存了所有与这个EventThread建立的连接
while (it != mDisplayEventConnections.end()) { // 遍历所有Connection
if (const auto connection = it->promote()) {
vsyncRequested |= connection->vsyncRequest != VSyncRequest::None;//是否请求vsync if (event && shouldConsumeEvent(*event, connection)) { // 判断是否需要分发事件通知这个connection
consumers.push_back(connection);
} ++it;
} else {
it = mDisplayEventConnections.erase(it);
}
} if (!consumers.empty()) {
dispatchEvent(*event, consumers);// 分发事件,最终是使用BitTube发送数据,通知connection
consumers.clear();
} State nextState;
if (mVSyncState && vsyncRequested) {
// synthetic = True if VSYNC should be faked, e.g. when display is off. 屏幕关闭产生虚假的VSYNC
nextState = mVSyncState->synthetic ? State::SyntheticVSync : State::VSync;
} else {
ALOGW_IF(!mVSyncState, "Ignoring VSYNC request while display is disconnected");
nextState = State::Idle; // 进入Idle阻塞等待
} if (mState != nextState) {
if (mState == State::VSync) {
mVSyncSource->setVSyncEnabled(false); // 关闭 vsync
} else if (nextState == State::VSync) {
mVSyncSource->setVSyncEnabled(true); // 开启 vysnc ,作用于CallbackRepeater,循环去schedule next vsync
} mState = nextState;
} 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));
}
}
}
}

EventThread::threadMain代码逻辑上也比较清晰,主体就是从mPendingEvents这个待处理的事件队列中取出event,让后经过判断处理后通知到对应的connections

本文作者@二的次方  2022-04-27 发布于博客园

简单说说

EventThread::shouldConsumeEvent

这个方法就如同它的名字,判断是否去消费这个事件,说白了就是判断这个事件是否要分发通知给指定的connection。

参数event就是当前发生的,准备分发的事件

参数connection就是客户端注册到EventThread中的connection,其中就包装了用于跨进程通信的BitTube对象

对于VSYNC事件,在这个函数中实现了setVsyncRate中设置的分发频率

[ /frameworks/native/services/surfaceflinger/Scheduler/EventThread.cpp]
bool EventThread::shouldConsumeEvent(const DisplayEventReceiver::Event& event,
const sp<EventThreadConnection>& connection) const {
const auto throttleVsync = [&] {
return mThrottleVsyncCallback &&
mThrottleVsyncCallback(event.vsync.expectedVSyncTimestamp, connection->mOwnerUid);
}; switch (event.header.type) {
case DisplayEventReceiver::DISPLAY_EVENT_HOTPLUG: // 热插拔事件
return true; case DisplayEventReceiver::DISPLAY_EVENT_MODE_CHANGE: {// mode change事件
return connection->mEventRegistration.test( //接收者设置了modeChanged标志才会分发
ISurfaceComposer::EventRegistration::modeChanged);
} case DisplayEventReceiver::DISPLAY_EVENT_VSYNC: // VSYNC事件
switch (connection->vsyncRequest) { // setVsyncRate设置分发的频率
case VSyncRequest::None: // rate==0,不分发
return false;
case VSyncRequest::SingleSuppressCallback:// requestNextVsync 有请求时case
connection->vsyncRequest = VSyncRequest::None;
return false;
case VSyncRequest::Single: { // requestNextVsync 有请求时case
if (throttleVsync()) {
return false;
}
connection->vsyncRequest = VSyncRequest::SingleSuppressCallback;
return true;
}
case VSyncRequest::Periodic: // rate==1,周期性,每个VSYNC事件都分发通知
if (throttleVsync()) {
return false;
}
return true;
default:
// We don't throttle vsync if the app set a vsync request rate
// since there is no easy way to do that and this is a very
// rare case
// 根据setVsyncRate设置分发的频率,周期性的计数,每connection->vsyncRequest个分发一个
return event.vsync.count % vsyncPeriod(connection->vsyncRequest) == 0;
} case DisplayEventReceiver::DISPLAY_EVENT_FRAME_RATE_OVERRIDE:
[[fallthrough]];
case DisplayEventReceiver::DISPLAY_EVENT_FRAME_RATE_OVERRIDE_FLUSH: // frame rate override flush事件
return connection->mEventRegistration.test(// 判断接收者设置了frameRateOverride标志才会分发
ISurfaceComposer::EventRegistration::frameRateOverride); default:
return false;
}
}

EventThread::dispatchEvent

当前面判断某一个事件应该分发出去后,接下来就是去实际把事件分发出去,通知到接收者了

最终的事件是通过调用EventThreadConnection::postEvent==> DisplayEventReceiver::sendEvents ==> gui::BitTube::sendObjects

BitTube跨进程通知到接收者

void EventThread::dispatchEvent(const DisplayEventReceiver::Event& event,
const DisplayEventConsumers& consumers) {
// 注意:using DisplayEventConsumers = std::vector<sp<EventThreadConnection>>;
// 从consumers数组中遍历EventThreadConnection
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)) { // postEvent分发事件==>EventThreadConnection::postEvent
...
}
}
}

DispSyncSource::setVSyncEnabled

这个方法去call mRegistration.schedule  == > VSyncCallbackRegistration::schedule 去安排下一次的Vsync events

大概如此,从而周期性的收到vsync events ,  不多讲了


经过上面流程的分析,事件通过BitTube::sendObjects跨进程通知到接收者,接收者通过监听BitTube::mReceiveFd,并在接收到事件时调用BitTube::recvObjects就可以取出事件,做后续处理了

总结一个不是很准确的图,我也不知道该咋表达了,哈

Android 12(S) 图像显示系统 - SurfaceFlinger 之 VSync - 中篇(十七)的更多相关文章

  1. Android 12(S) 图像显示系统 - SurfaceFlinger之VSync-上篇(十六)

    必读: Android 12(S) 图像显示系统 - 开篇 一.前言 为了提高Android系统的UI交互速度和操作的流畅度,在Android 4.1中,引入了Project Butter,即&quo ...

  2. Android 12(S) 图像显示系统 - SurfaceFlinger GPU合成/CLIENT合成方式 - 随笔1

    必读: Android 12(S) 图像显示系统 - 开篇 一.前言 SurfaceFlinger中的图层选择GPU合成(CLIENT合成方式)时,会把待合成的图层Layers通过renderengi ...

  3. Android 12(S) 图像显示系统 - drm_hwcomposer 简析(上)

    必读: Android 12(S) 图像显示系统 - 开篇 前言 Android源码中有包含drm_hwcomposer:/external/drm_hwcomposer/ drm_hwcompose ...

  4. Android 12(S) 图像显示系统 - GraphicBuffer同步机制 - Fence

    必读: Android 12(S) 图像显示系统 - 开篇 一.前言 前面的文章中讲解Android BufferQueue的机制时,有遇到过Fence,但没有具体讲解.这篇文章,就针对Fence这种 ...

  5. Android 12(S) 图像显示系统 - 基础知识之 BitTube

    必读: Android 12(S) 图像显示系统 - 开篇 一.基本概念 在Android显示子系统中,我们会看到有使用BitTube来进行跨进程数据传递.BitTube的实现很简洁,就是一对&quo ...

  6. Android 12(S) 图像显示系统 - HWC HAL 初始化与调用流程

    必读: Android 12(S) 图像显示系统 - 开篇 接口定义 源码位置:/hardware/interfaces/graphics/composer/ 在源码目录下可以看到4个版本的HIDL ...

  7. Android 12(S) 图像显示系统 - drm_hwcomposer 简析(下)

    必读: Android 12(S) 图像显示系统 - 开篇 合成方式 合成类型的定义:/hardware/interfaces/graphics/composer/2.1/IComposerClien ...

  8. Android 12(S) 图形显示系统 - SurfaceFlinger的启动和消息队列处理机制(四)

    1 前言 SurfaceFlinger作为Android图形显示系统处理逻辑的核心单元,我们有必要去了解其是如何启动,初始化及进行消息处理的.这篇文章我们就来简单分析SurfaceFlinger这个B ...

  9. Android 12(S) 图形显示系统 - createSurface的流程(五)

    题外话 刚刚开始着笔写作这篇文章时,正好看电视在采访一位92岁的考古学家,在他的日记中有这样一句话,写在这里与君共勉"不要等待幸运的降临,要去努力的掌握知识".如此朴实的一句话,此 ...

随机推荐

  1. Spring中毒太深,离开了Spring,我居然连最基本的接口都不会写了¯\_(ツ)_/¯

    前言 众所周知,Java必学的框架其中就是SSM,Spring已经融入了每个开发人员的生活,成为了不可或缺的一份子. 随着 Spring 的崛起以及其功能的完善,现在可能绝大部分项目的开发都是使用 S ...

  2. 【freertos】004-任务创建与删除及其实现细节

    前言 后面都是已动态内存任务为例来分析. 注意: 由于当前学习是在linux上跑的freertos,对于freertos底层相关接口,从demo工程来看,都是posix标准相关. 鉴于freertos ...

  3. Elman network with additional notes

    // Author: John McCullock // Date: 10-15-05 // Description: Elman Network Example 1. //http://www.mn ...

  4. Dubbo 和 Spring Cloud 的区别?

    根据微服务架构在各方面的要素,看看 Spring Cloud 和 Dubbo 都提供了哪些支 持. Dubbo Spring Cloud 服务注册中心 Zookeep er Spring Cloud ...

  5. 什么是 Mybatis?

    1.Mybatis 是一个半 ORM(对象关系映射)框架,它内部封装了 JDBC,开发时 只需要关注 SQL 语句本身,不需要花费精力去处理加载驱动.创建连接.创建 statement 等繁杂的过程. ...

  6. Dubbo 用到哪些设计模式?

    Dubbo 框架在初始化和通信过程中使用了多种设计模式,可灵活控制类加载.权 限控制等功能. 工厂模式 Provider 在 export 服务时,会调用 ServiceConfig 的 export ...

  7. switch 是否能作用在byte 上,是否能作用在long 上,是否能作用在String上?

    答:在Java 5以前,switch(expr)中,expr只能是byte.short.char.int.从Java 5开始,Java中引入了枚举类型,expr也可以是enum类型,从Java 7开始 ...

  8. Nginx HTTP负载均衡和反向代理的配置与优化

    一.什么是负载均衡和反向代理 1.负载均衡 负载均衡是由多台服务器以对称的方式组成一个服务器集合,每台服务器具有等价的地位,都可以单独提供服务而无需其他服务的辅助.通过某种负载分担技术,将外部发送来的 ...

  9. FiddlerEverywhere注册账号进行激活失效问题

    有关FiddlerEverywhere通过邮件激活账号时,激活链接提示已失效问题:这个链接有进行一个讨论(https://www.telerik.com/forums/unable-to-activa ...

  10. MariaDB InnoDB基本介绍

    InnoDB锁定模式 事务获取锁,以防止并发事务修改甚至读取某些行或行范围.这样做是为了确保并发写入操作不会冲突. 共享锁(S)和排他锁(X) 两种标准的行级锁是共享锁(S)和排他锁(X) 获取共享锁 ...