Android 12(S) 图像显示系统 - SurfaceFlinger 之 VSync - 中篇(十七)
必读:
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
}
}
}
核心的处理应该是createDisplayEventConnection
和stealReceiveChannel
,下面分别看看这两个操作具体做了啥子
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);
}
mSfConnectionHandle
和mAppConnectionHandle
是在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 - 中篇(十七)的更多相关文章
- Android 12(S) 图像显示系统 - SurfaceFlinger之VSync-上篇(十六)
必读: Android 12(S) 图像显示系统 - 开篇 一.前言 为了提高Android系统的UI交互速度和操作的流畅度,在Android 4.1中,引入了Project Butter,即&quo ...
- Android 12(S) 图像显示系统 - SurfaceFlinger GPU合成/CLIENT合成方式 - 随笔1
必读: Android 12(S) 图像显示系统 - 开篇 一.前言 SurfaceFlinger中的图层选择GPU合成(CLIENT合成方式)时,会把待合成的图层Layers通过renderengi ...
- Android 12(S) 图像显示系统 - drm_hwcomposer 简析(上)
必读: Android 12(S) 图像显示系统 - 开篇 前言 Android源码中有包含drm_hwcomposer:/external/drm_hwcomposer/ drm_hwcompose ...
- Android 12(S) 图像显示系统 - GraphicBuffer同步机制 - Fence
必读: Android 12(S) 图像显示系统 - 开篇 一.前言 前面的文章中讲解Android BufferQueue的机制时,有遇到过Fence,但没有具体讲解.这篇文章,就针对Fence这种 ...
- Android 12(S) 图像显示系统 - 基础知识之 BitTube
必读: Android 12(S) 图像显示系统 - 开篇 一.基本概念 在Android显示子系统中,我们会看到有使用BitTube来进行跨进程数据传递.BitTube的实现很简洁,就是一对&quo ...
- Android 12(S) 图像显示系统 - HWC HAL 初始化与调用流程
必读: Android 12(S) 图像显示系统 - 开篇 接口定义 源码位置:/hardware/interfaces/graphics/composer/ 在源码目录下可以看到4个版本的HIDL ...
- Android 12(S) 图像显示系统 - drm_hwcomposer 简析(下)
必读: Android 12(S) 图像显示系统 - 开篇 合成方式 合成类型的定义:/hardware/interfaces/graphics/composer/2.1/IComposerClien ...
- Android 12(S) 图形显示系统 - SurfaceFlinger的启动和消息队列处理机制(四)
1 前言 SurfaceFlinger作为Android图形显示系统处理逻辑的核心单元,我们有必要去了解其是如何启动,初始化及进行消息处理的.这篇文章我们就来简单分析SurfaceFlinger这个B ...
- Android 12(S) 图形显示系统 - createSurface的流程(五)
题外话 刚刚开始着笔写作这篇文章时,正好看电视在采访一位92岁的考古学家,在他的日记中有这样一句话,写在这里与君共勉"不要等待幸运的降临,要去努力的掌握知识".如此朴实的一句话,此 ...
随机推荐
- [vmware to openstack] 安装virtio驱动
描述 从vmware的虚拟机迁移到opensatck,由于vmware虚拟机磁盘类型采用的是scsi,要迁移到opensatck平台运行,发现虚拟机无法起来,原因是vmware虚拟机没有安装vir ...
- js file对象 文件大小转换可视容易阅读的单位
function returnFileSize(number) { if(number < 1024) { return number + 'bytes'; } else if(number & ...
- Oracle入门基础(六)一一子查询
SQL> --查询工资比SCOTT高的员工信息 SQL> --1. SCOTT的工资 SQL> select sal from emp where ename='SCOTT'; SA ...
- 如何在自定义端口上运行 Spring Boot 应用程序?
为了在自定义端口上运行 Spring Boot 应用程序,您可以在 application.properties 中指定端口. server.port = 8090
- mybatis插件机制原理
mybatis插件机制及分页插件原理 参考链接:mybatis插件机制及分页插件原理 如何编写一个自定义mybatis插件 参考链接:mybatis 自定义插件的使用
- Mac SVN Cornerstone 安装使用详解
Cornerstone 是收费软键,这里提供一个破解版 ,安装后需要输入安装密码:www.ifunmac.com 链接:https://pan.baidu.com/s/1LqY2s8vEJAQ9JJh ...
- 学习saltstack (七)
一.SaltStack概述 Salt,,一种全新的基础设施管理方式,部署轻松,在几分钟内可运行起来,扩展性好,很容易管理上万台服务器,速度够快,服务器之间秒级通讯. salt底层采用动态的连接总线, ...
- element-ui 无法对绑定表单的对象中的对象属性进行验证
<el-form-item label="类型" :label-width="formLabelWidth" prop="typeId" ...
- hackgame2018_签到
hackgame2018_签到 进入题目得到如下提示 尝试提交 发现这个输入框长度做了限制我们将前端js修改一下 然后提交以下这样就发现了flag这题比较简单--
- CPU架构:CPU架构详细介绍
1 概述 CPU架构是CPU商给CPU产品定的一个规范,主要目的是为了区分不同类型的CPU.目前市场上的CPU分类主要分有两大阵营,一个是intel.AMD为首的复杂指令集CPU,另一个是以IBM.A ...