一起养成写作习惯!这是我参与「掘金日新计划 · 4 月更文挑战」的第1天,点击查看活动详情。
SurfaceFlinger和VSync信号
在显示图形系统中,有一个很重要的概念--VSync信号,垂直同步信号,HWC利用硬件或者软件产生的持续Vsync信号去触发SF和UI去做绘图相关的工作,让绘图工作充分利用每个Vsync信号间隔的时间
hal层Composer回调函数
在SurfaceFlinger初始化的过程中,会初始化一个HWComposer指针对象,然后调用这个对象的setConfiguration函数
void HWComposer::setConfiguration(HWC2::ComposerCallback* callback, int32_t sequenceId) {
// ......
mRegisteredCallback = true;
sp<ComposerCallbackBridge> callbackBridge(
new ComposerCallbackBridge(callback, sequenceId, mComposer->isVsyncPeriodSwitchSupported()));
mComposer->registerCallback(callbackBridge);
}
在这个函数中,通过初始化ComposerCallbackBridge指针对象,为android::hwc2::Composer对象注册一个回调类,其实从ComposerCallbackBridge类的名称,我们也可以看到,这个类对象起了一个桥梁的作用,即将接收到的回调信号传递给回调类处理,那么此处具体是做什么呢?
为了便于理解,先绘制一个类图结构如下:
从这张图来看,
- ComposerCallbackBridge类继承了hal::IComposerCallback类,IComposerCallback类的命名空间在hal,也就是说它是一个hal层的Composer回调类,
- ComposerCallbackBridge有一个参数mCallback是一个ComposerCallback对象,SurfaceFlinger类继承自这个ComposerCallback类,而setConfiguration函数传入的第一个参数为SurfaceFlinger对象,因此此处,ComposerCallbackBridge的参数mCallback是一个指向SurfaceFlinger的指针
- ComposerCallbackBridge类关联的是hal层的IComposerCallback类和frameworks-native层的ComposerCallback对象,而此处是SurfaceFlinger对象
而我们再查看ComposerCallbackBridge类函数的具体实现
class ComposerCallbackBridge : public hal::IComposerCallback {
public:
ComposerCallbackBridge(ComposerCallback* callback, int32_t sequenceId, bool vsyncSwitchingSupported)
: mCallback(callback),
mSequenceId(sequenceId),
mVsyncSwitchingSupported(vsyncSwitchingSupported) {}
android::hardware::Return<void> onHotplug(hal::HWDisplayId display, hal::Connection conn) override {
mCallback->onHotplugReceived(mSequenceId, display, conn);
return android::hardware::Void();
}
android::hardware::Return<void> onRefresh(hal::HWDisplayId display) override {
mCallback->onRefreshReceived(mSequenceId, display);
return android::hardware::Void();
}
android::hardware::Return<void> onVsync(hal::HWDisplayId display, int64_t timestamp) override {
if (!mVsyncSwitchingSupported) {
mCallback->onVsyncReceived(mSequenceId, display, timestamp, std::nullopt);
} else {
ALOGW("Unexpected onVsync callback on composer >= 2.4, ignoring.");
}
return android::hardware::Void();
}
android::hardware::Return<void> onVsync_2_4(hal::HWDisplayId display, int64_t timestamp,
hal::VsyncPeriodNanos vsyncPeriodNanos) override {
if (mVsyncSwitchingSupported) {
mCallback->onVsyncReceived(mSequenceId, display, timestamp,
std::make_optional(vsyncPeriodNanos));
} else {
ALOGW("Unexpected onVsync_2_4 callback on composer <= 2.3, ignoring.");
}
return android::hardware::Void();
}
android::hardware::Return<void> onVsyncPeriodTimingChanged(
hal::HWDisplayId display,
const hal::VsyncPeriodChangeTimeline& updatedTimeline) override {
mCallback->onVsyncPeriodTimingChangedReceived(mSequenceId, display, updatedTimeline);
return android::hardware::Void();
}
android::hardware::Return<void> onSeamlessPossible(hal::HWDisplayId display) override {
mCallback->onSeamlessPossible(mSequenceId, display);
return android::hardware::Void();
}
private:
ComposerCallback* mCallback;
const int32_t mSequenceId;
const bool mVsyncSwitchingSupported;
};
也就是说,hal层发出的IComposerCallback类中的回调信号,最终的处理均是在SurfaceFlinger对象中的对应回调函数中处理
SurfaceFlinger::init函数
在SurfaceFlinger初始化的时候,
- 通过HWComposer的setConfiguration函数,会引起驱动Composer向Frameworks发送一个插拔显示设备的信号事件,在frameworks的SurfaceFligner::onHotplugReceived回调函数中处理,
- 然后通过processDisplayHotplugEventsLocked函数,来运行这个设备热插拔事件,
- 而在这个函数中,会通过initScheduler函数来初始化Scheduler对应的相关操作
因此,我们首先需要查看下initScheduler函数的具体功能
void SurfaceFlinger::initScheduler(DisplayId primaryDisplayId) {
// ......
// start the EventThread
// 初始化Scheduler对象
mScheduler = getFactory().createScheduler([this](bool enabled) { setPrimaryVsyncEnabled(enabled); },
*mRefreshRateConfigs, *this);
// 初始化两个ConnectionHandle对象
mAppConnectionHandle =
mScheduler->createConnection("app", mPhaseConfiguration->getCurrentOffsets().late.app,
impl::EventThread::InterceptVSyncsCallback());
mSfConnectionHandle =
mScheduler->createConnection("sf", mPhaseConfiguration->getCurrentOffsets().late.sf,
[this](nsecs_t timestamp) {
mInterceptor->saveVSyncEvent(timestamp);
});
// 设置EventQueue的ConnectionHandle
mEventQueue->setEventConnection(mScheduler->getEventConnection(mSfConnectionHandle));
mVSyncModulator.emplace(*mScheduler, mAppConnectionHandle, mSfConnectionHandle,
mPhaseConfiguration->getCurrentOffsets());
// 启动一个RegionSamplingThread对象
mRegionSamplingThread =
new RegionSamplingThread(*this, *mScheduler,
RegionSamplingThread::EnvironmentTimingTunables());
// Dispatch a config change request for the primary display on scheduler
// initialization, so that the EventThreads always contain a reference to a
// prior configuration.
//
// This is a bit hacky, but this avoids a back-pointer into the main SF
// classes from EventThread, and there should be no run-time binder cost
// anyway since there are no connected apps at this point.
// 设置VSYNC信号周期
const nsecs_t vsyncPeriod =
mRefreshRateConfigs->getRefreshRateFromConfigId(currentConfig).getVsyncPeriod();
mScheduler->onPrimaryDisplayConfigChanged(mAppConnectionHandle, primaryDisplayId.value,
currentConfig, vsyncPeriod);
}
这段代码的初始化,我们在默认DisplayDevice显示设备加载流程分析文章有分析过这个Scheduler对象的初始化流程,只是上篇关注点在显示设备加载上,而忽略了其他初始化流程,因此本篇将从另一个方向来分析下这个初始化流程
从此前篇章分析中,在SurfaceFlinger::initScheduler函数,主要是做了:
- 初始化一个Scheduler指针对象,在这个初始化中,顺便初始化了Scheduler的两个参数,mPrimaryDispSync和mEventControlThread,分别对应的是VSyncReactor对象和EventControlThread对象
- 初始化两个ConnectionHandle,分别对应的是SF和APP
- 设置SurfaceFlinger的MessageQueue的消息处理文件句柄
- 初始化一个RegionSamplingThread线程,并启动这个线程
- Scheduler的onPrimaryDisplayConfigChanged回调函数的调用,启动EventThread消息机制
Scheduler初始化流程
此处直接借助类图和时序图来说明其具体流程
从如上的Scheduler初始化流程的类图和时序图来看,这边主要的工作如下:
- 在Scheduler的初始化过程中,首先通过调用Scheduler的createDispSync函数初始化了一个VSyncReactor指针对象,VSyncReactor继承自android::DispSync对象,同时VSyncReactor对象中包含两个参数mTracker和mDispatch,它们分别是继承自VSyncTracker类的VSyncPredictor指针对象,以及继承自VSyncDispatch类的VSyncDispatchTimerQueue指针对象
std::unique_ptr<DispSync> createDispSync(bool supportKernelTimer) {
// TODO (140302863) remove this and use the vsync_reactor system.
if (property_get_bool("debug.sf.vsync_reactor", true)) {
// TODO (144707443) tune Predictor tunables.
static constexpr int defaultRate = 60;
static constexpr auto initialPeriod =
std::chrono::duration<nsecs_t, std::ratio<1, defaultRate>>(1);
static constexpr size_t vsyncTimestampHistorySize = 20;
static constexpr size_t minimumSamplesForPrediction = 6;
static constexpr uint32_t discardOutlierPercent = 20;
// 初始化VSyncPredictor对象,此类继承自VSyncTracker类
auto tracker = std::make_unique<
scheduler::VSyncPredictor>(std::chrono::duration_cast<std::chrono::nanoseconds>(
initialPeriod)
.count(),
vsyncTimestampHistorySize, minimumSamplesForPrediction,
discardOutlierPercent);
static constexpr auto vsyncMoveThreshold =
std::chrono::duration_cast<std::chrono::nanoseconds>(3ms);
static constexpr auto timerSlack =
std::chrono::duration_cast<std::chrono::nanoseconds>(500us);
// 初始化VSyncDispatchTimerQueue指针对象,此类继承自VSyncDispatch类
auto dispatch = std::make_unique<
scheduler::VSyncDispatchTimerQueue>(std::make_unique<scheduler::Timer>(), *tracker,
timerSlack.count(), vsyncMoveThreshold.count());
static constexpr size_t pendingFenceLimit = 20;
// 返回一个VSyncReactor对象,此类继承自android::DispSync类
// 注意,此处返回的android::DispSync类跟else分支中的android::impl::DispSync不是同一个类
return std::make_unique<scheduler::VSyncReactor>(std::make_unique<scheduler::SystemClock>(),
std::move(dispatch), std::move(tracker),
pendingFenceLimit, supportKernelTimer);
} else {
return std::make_unique<impl::DispSync>("SchedulerDispSync",
sysprop::running_without_sync_framework(true));
}
}
- 同时,在Scheduler初始化过程中,直接初始化了一个EventControlThread指针对象,在这个对象的初始化过程中,会启动一个线程并调用其threadMain函数,在这个函数中,有一个while循环,这个while循环中,首先会调用SurfaceFlinger在createScheduler过程中传递的第一个参数对应的函数指针,最终会调用SurfaceFlinger::setPrimaryVsyncEnabled函数(第一次设置VSyncEnabled为false),此后会调用mCondition的wait函数,等待对应的VsyncEnabled状态变化时再次调用SurfaceFlinger::setPrimaryVsyncEnabled函数
EventControlThread::EventControlThread(EventControlThread::SetVSyncEnabledFunction function)
: mSetVSyncEnabled(std::move(function)) {
pthread_setname_np(mThread.native_handle(), "EventControlThread");
pid_t tid = pthread_gettid_np(mThread.native_handle());
setpriority(PRIO_PROCESS, tid, ANDROID_PRIORITY_URGENT_DISPLAY);
set_sched_policy(tid, SP_FOREGROUND);
}
void EventControlThread::threadMain() NO_THREAD_SAFETY_ANALYSIS {
auto keepRunning = true;
auto currentVsyncEnabled = false;
while (keepRunning) {
// SurfaceFlinger中调用SurfaceFlingerDefaultFactory::createScheduler时传入的第一个参数
// 最终会调用到SurfaceFlinger::setPrimaryVsyncEnabled函数
mSetVSyncEnabled(currentVsyncEnabled);
std::unique_lock<std::mutex> lock(mMutex);
// 等待其他部分唤醒
mCondition.wait(lock, [this, currentVsyncEnabled, keepRunning]() NO_THREAD_SAFETY_ANALYSIS {
// 条件满足时释放lock锁后继续运行
return currentVsyncEnabled != mVsyncEnabled || keepRunning != mKeepRunning;
});
currentVsyncEnabled = mVsyncEnabled;
keepRunning = mKeepRunning;
}
}
创建ConnectionHandle
看这个流程中的类图和时序图:
从如上的类图和流程图来看,在这个过程中
- Scheduler的createConnection函数
- 首先初始化了一个DispSyncSource类对象,这个DispSyncSource类继承自VSyncSource类和android::DispSync::Callback回调类,同时其包含了一个参数名为mDispSync的指针指向在Scheduler初始化过程中初始化的一个VSyncReactor对象
- 创建一个EventThread对象,并且其包含了一个参数名为mVSyncSource的指针指向刚刚创建的DispSyncSource对象,且包含一个名称为mInterceptVSyncsCallback的指针参数指向Scheduler调用createConnection函数时传入的第三个参数对应的函数指针
- 在创建EevntThread对象的同时,设置DispSyncSource指针对象的Callback为当前的EventThread
- 同时在EventThread构造函数中启动一个线程,并且调用EventThread::threadMain函数,在这个函数中,主要操作处理接收一些显示设备传递的一些Event(如插拔事件或者VSYNC事件等)
- 最终,EventThread::threadMain函数mCondition.wait(lock)处于等待堵塞状态
- 调用EventThread对象的createEventConnection函数,初始化一个EventThreadConnection对象,并且这个对象中包含参数名为mEventThread的指针参数指向刚刚创建的EventThread对象,resyncCallback指针参数指向一个在Scheduler调用EventThread::createEventConnection函数时传递的第一个函数指针参数
- 初始化EventThreadConnection对象的过程中,会调用其onFirstRefs函数,在这个函数中会调用EventThread::registerDisplayEventConnection函数,从而最终触发EventThread::threadMain的同步条件
Scheduler::ConnectionHandle Scheduler::createConnection(
const char* connectionName, nsecs_t phaseOffsetNs,
impl::EventThread::InterceptVSyncsCallback interceptCallback) {
// 初始化一个DispSyncSource指针对象
auto vsyncSource = makePrimaryDispSyncSource(connectionName, phaseOffsetNs);
// 初始化一个EventThread指针对象
auto eventThread = std::make_unique<impl::EventThread>(std::move(vsyncSource),
std::move(interceptCallback));
return createConnection(std::move(eventThread));
}
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(), ISurfaceComposer::eConfigChangedSuppress);
// 在创建EventThreadConnection指针对象和EventThread指针对象作为values值添加到mConnections
mConnections.emplace(handle, Connection{connection, std::move(eventThread)});
return handle;
}
sp<EventThreadConnection> Scheduler::createConnectionInternal(
EventThread* eventThread, ISurfaceComposer::ConfigChanged configChanged) {
return eventThread->createEventConnection([&] { resync(); }, configChanged);
}
sp<EventThreadConnection> EventThread::createEventConnection(
ResyncCallback resyncCallback, ISurfaceComposer::ConfigChanged configChanged) const {
return new EventThreadConnection(const_cast<EventThread*>(this), std::move(resyncCallback),
configChanged);
}
EventThreadConnection::EventThreadConnection(EventThread* eventThread,
ResyncCallback resyncCallback,
ISurfaceComposer::ConfigChanged configChanged)
: resyncCallback(std::move(resyncCallback)),
mConfigChanged(configChanged),
mEventThread(eventThread),
mChannel(gui::BitTube::DefaultSize) {}
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);
// ......
// 为mDisplayEventConnections添加参数,这样EventThread::threadMain函数在唤醒的时候就会执行对应的代码
// 但是,此时如果追踪下去代码,会发现,EventThread::threadMain函数依旧会被堵塞,因为mPendingEvents中依旧无数据
mDisplayEventConnections.push_back(connection);
// 唤醒mCondition,此处是EventThread::threadMain函数中阻塞
mCondition.notify_all();
return NO_ERROR;
}
- 在SurfaceFlinger中调用MessageQueue::setEventConnection函数,进而调用Looper::addFd函数,从而将SurfaceFlinger的消息处理和此处的EventThread进行关联,当EventThread接收到Composer驱动发出的Event消息,则会在MessageQueue::cb_eventReceiver函数中进行最终的处理
// 注意,此处关联的是SF对应的EventThreadConnection指针对象
mEventQueue->setEventConnection(mScheduler->getEventConnection(mSfConnectionHandle));
void MessageQueue::setEventConnection(const sp<EventThreadConnection>& connection) {
// ......
mEvents = connection;
// 设置mEventTube为对应EventThreadConnection的mChannal通道
mEvents->stealReceiveChannel(&mEventTube);
// 将EventThreadConnection指针对象的receive fd,并且设置的回调函数为MessageQueue::cb_eventReceiver函数
mLooper->addFd(mEventTube.getFd(), 0, Looper::EVENT_INPUT, MessageQueue::cb_eventReceiver,
this);
}
初始化Display设备
同样地,先来一张初始化显示设备的时序图
从这张图中也能看到,在SurfaceFlinger的init中,通过initializeDisplays函数初始化对应的显示设备,在此期间,设置DisplayDevice的PowerMode状态为PowerMode::ON,然后在Scheduler中设置mHWVsyncAvailable参数的值为true,表明当前Composer驱动或者HWComposer的硬件VSYNC已经准备完成,此后设置VSyncReactor(继承自DispSync类)的VSYNC Period值,显示设备的VSYNC信号启动上报。
驱动VSync信号上报
在前述的分析中,我们知道,Hal层的Composer信号通过HWComposer的ComposerCallbackBridge指针对象中的回调函数,传递到SurfaceFlinger的回调函数,因此当硬件VSYNC信号上报时,触发了ComposerCallbackBridge指针对象的onVsync函数回调,继而调用了SurfaceFlinger的onVsyncReceived函数回调,即
SurfaceFlinger接收到硬件VSYNC信号回调函数onVsyncReceived后通过Scheduler的addResyncSample构建硬件模型Sample,确认是否需要开启或者关闭硬件驱动VSYNC信号的触发