通过上一篇文章我们创建了一个 EventThread 线程,并且它持有了 SurfaceFlinger 中 resyncWithRateLimit() 方法的指针。这里我们主要来看一下 EventThread 对信号的处理。
一、发送Vsync信号
当 SurfaceFlinger 执行完 queueBuffer() 方法之后,通过 onFrameAvailable 又会回调到 SurfaceFlinger 中的 commit() 方法中。
1、SurfaceFlinger.cpp
源码位置:/frameworks/native/services/surfaceflinger/SurfaceFlinger.cpp
commit
bool SurfaceFlinger::commit(nsecs_t frameTime, int64_t vsyncId, nsecs_t expectedVsyncTime)
FTL_FAKE_GUARD(kMainThreadContext) {
……
if (mSetActiveModePending) {
// 检查是否有待处理的帧
if (framePending) {
mScheduler->scheduleFrame();
return false;
}
mSetActiveModePending = false;
{
Mutex::Autolock lock(mStateLock);
updateInternalStateWithChangedMode();
}
}
// 检查是否有待处理的帧
if (framePending) {
if ((hwcFrameMissed && !gpuFrameMissed) || mPropagateBackpressureClientComposition) {
scheduleCommit(FrameHint::kNone);
return false;
}
}
……
}
这里多次检查是否有待处理的帧,如果有最终都会调用 mScheduler->scheduleFrame() 来尝试调度一个新帧。
scheduleCommit
void SurfaceFlinger::scheduleCommit(FrameHint hint) {
if (hint == FrameHint::kActive) {
// 重置空闲计时器
mScheduler->resetIdleTimer();
}
// 通知即将更新显示
mPowerAdvisor->notifyDisplayUpdateImminent();
// 试调度一个新帧
mScheduler->scheduleFrame();
}
这里最终同样是来调度一个新的帧提交,上面的 mScheduler 继承自 MessageQueue。
2、MessageQueue.cpp
源码位置:/frameworks/native/services/surfaceflinger/Scheduler/MessageQueue.cpp
scheduleFrame
// 设置事件注入器
void MessageQueue::setInjector(sp<EventThreadConnection> connection) {
……
mInjector.connection = std::move(connection);
}
void MessageQueue::scheduleFrame() {
……
{
std::lock_guard lock(mInjector.mutex);
if (CC_UNLIKELY(mInjector.connection)) {
// 请求下一个VSync信号
mInjector.connection->requestNextVsync();
return;
}
}
……
}
这里通过 EventThreadConnection 来请求 VSync 信号,从而调度新的帧提交。
3、EventThread.cpp
源码位置:/frameworks/native/services/surfaceflinger/Scheduler/EventThread.cpp
看到这里,是不是就进入到前面创建的信号处理线程了,该类启动一个专门用于处理 VSync 信号的线程。其中 EventThreadConnection 是 EventThread 的内部类。
EventThreadConnection::requestNextVsync
binder::Status EventThreadConnection::requestNextVsync() {
ATRACE_CALL();
mEventThread->requestNextVsync(this);
return binder::Status::ok();
}
这里调用了 EventThread 的 requestNextVsync() 函数。
EventThread::requestNextVsync
void EventThread::requestNextVsync(const sp<EventThreadConnection>& connection) {
if (connection->resyncCallback) {
connection->resyncCallback();
}
std::lock_guard<std::mutex> lock(mMutex);
if (connection->vsyncRequest == VSyncRequest::None) {
connection->vsyncRequest = VSyncRequest::Single;
// 通知所有等待线程
mCondition.notify_all();
} else if (connection->vsyncRequest == VSyncRequest::SingleSuppressCallback) {
connection->vsyncRequest = VSyncRequest::Single;
}
}
该函数主要用于处理与垂直同步(vsync)相关的请求。这里的 resyncCallback() 函数是在创建 EventThreadConnection 时以参数的形式传入的,我们来看一下。
createEventConnection
sp<EventThreadConnection> EventThread::createEventConnection(ResyncCallback resyncCallback,
ISurfaceComposer::EventRegistrationFlags eventRegistration) const {
return new EventThreadConnection(const_cast<EventThread*>(this),
IPCThreadState::self()->getCallingUid(), std::move(resyncCallback), eventRegistration);
}
而该创建函数是在 MessageQueue 的子类 Scheduler 中调用的。
4、Scheduler.cpp
源码位置:/frameworks/native/services/surfaceflinger/Scheduler/Scheduler.cpp
createConnectionInternal
sp<EventThreadConnection> Scheduler::createConnectionInternal(EventThread* eventThread,
ISurfaceComposer::EventRegistrationFlags eventRegistration) {
return eventThread->createEventConnection([&] { resync(); }, eventRegistration);
}
所以上面的 resyncCallback 应该就是这里的 resync() 函数。
resync
void Scheduler::resync() {
// 两次重新同步之间需要忽略的最短时间间隔,这里是750毫秒
static constexpr nsecs_t kIgnoreDelay = ms2ns(750);
// 获取当前系统时间
const nsecs_t now = systemTime();
// 获取并更新上次重新同步的时间
const nsecs_t last = mLastResyncTime.exchange(now);
// 如果当前时间和上次重新同步时间之间的差值大于kIgnoreDelay,表示需要重新同步
if (now - last > kIgnoreDelay) {
// 获取当前的刷新率
const auto refreshRate = [&] {
// 获取当前活动模式的刷新率(FPS)
std::scoped_lock lock(mRefreshRateConfigsLock);
return mRefreshRateConfigs->getActiveMode()->getFps();
}();
// 重新同步,传入false表示不需要强制重新同步
resyncToHardwareVsync(false, refreshRate);
}
}
该函数主要功能是重新同步系统时间与硬件 VSync 信号,同时根据需要适当地调整了重新同步的频率。
void Scheduler::resyncToHardwareVsync(bool makeAvailable, Fps refreshRate) {
{
std::lock_guard<std::mutex> lock(mHWVsyncLock);
if (makeAvailable) { // 硬件VSync可用
mHWVsyncAvailable = makeAvailable;
} else if (!mHWVsyncAvailable) { // 硬件VSync不可用
// 取消重新同步尝试
return;
}
}
// 设置VSync周期
setVsyncPeriod(refreshRate.getPeriodNsecs());
}
该函数不仅确保了在硬件 VSync 可用的情况下进行重新同步,还根据需要适当地设置了 VSync 周期。
void Scheduler::setVsyncPeriod(nsecs_t period) {
if (period <= 0) return;
std::lock_guard<std::mutex> lock(mHWVsyncLock);
// 开始周期转换过程,设置新的VSync周期
mVsyncSchedule->getController().startPeriodTransition(period);
if (!mPrimaryHWVsyncEnabled) { // 未启用
// 重置VSync追踪模型
mVsyncSchedule->getTracker().resetModel();
// 启用VSync
mSchedulerCallback.setVsyncEnabled(true);
// 主硬件VSync现在已启用
mPrimaryHWVsyncEnabled = true;
}
}
该函数不仅确保了 VSync 周期的正确设置,还根据需要启用了硬件 VSync。 这里主要的操作有两个:
startPeriodTransition:设置新的 VSync 周期。
setVsyncEnabled:启用 VSync。
下面来分别看一下这两个信号处理的调用流程。
二、信号处理
1、设置VSync周期
上面设置信号周期的 mVsyncSchedule 就是 VsyncSchedule。这里看一下对应的 getController 函数。
源码位置:/frameworks/native/services/surfaceflinger/Scheduler/VsyncSchedule.h
getController
class VsyncController;
VsyncController& getController() { return *mController; }
可以看到 getController() 函数返回的是 VsyncController,而 VSyncReactor 又继承了 VsyncController,所以上面 mVsyncSchedule->getController().startPeriodTransition() 最终调用的其实就是 VSyncReactor 中的对应函数。
VSyncReactor.cpp
源码位置:/frameworks/native/services/surfaceflinger/Scheduler/VSyncReactor.cpp
void VSyncReactor::startPeriodTransition(nsecs_t period) {
ATRACE_INT64("VSR-setPeriod", period);
std::lock_guard lock(mMutex);
// 重置最后的硬件VSync时间
mLastHwVsync.reset();
if (!mSupportKernelIdleTimer && period == mTracker.currentPeriod()) {
// 结束周期转换过程,无需实际转换周期
endPeriodTransition();
// 取消忽略呈现围栏
setIgnorePresentFencesInternal(false);
mMoreSamplesNeeded = false;
} else {
// 开始周期转换过程
startPeriodTransitionInternal(period);
}
}
这里开始 VSync 周期的转换过程,调用 startPeriodTransitionInternal() 函数。
startPeriodTransitionInternal
void VSyncReactor::startPeriodTransitionInternal(nsecs_t newPeriod) {
ATRACE_CALL();
// 周期转换正在进行中
mPeriodConfirmationInProgress = true;
// 新的周期值
mPeriodTransitioningTo = newPeriod;
// 需要收集更多的样本数据来确认新的周期
mMoreSamplesNeeded = true;
// 忽略呈现围栏,有助于避免在周期转换期间出现干扰。
setIgnorePresentFencesInternal(true);
}
这里 VSync 周期转换过程的正确开始,并设置了必要的标志来支持周期转换的完成。
setIgnorePresentFencesInternal
void VSyncReactor::setIgnorePresentFencesInternal(bool ignore) {
mInternalIgnoreFences = ignore;
// 更新内部状态
updateIgnorePresentFencesInternal();
}
该函数用于设置是否忽略呈现围栏。
updateIgnorePresentFencesInternal
void VSyncReactor::updateIgnorePresentFencesInternal() {
if (mExternalIgnoreFences || mInternalIgnoreFences) {
// 清空未触发的围栏列表
mUnfiredFences.clear();
}
}
这里根据外部和内部的忽略标志来更新未触发的围栏列表。
2、启用VSync
上面的 mSchedulerCallback 是 ISchedulerCallback,而 SurfaceFlinger 又继承了该类,所以这里其实调用的就是 SurfaceFlinger 中的 setVsyncEnabled 函数。
setVsyncEnabled
void SurfaceFlinger::setVsyncEnabled(bool enabled) {
ATRACE_CALL();
// 调度一个任务,确保在主线程上执行
static_cast<void>(mScheduler->schedule([=]() FTL_FAKE_GUARD(mStateLock) {
mHWCVsyncPendingState = enabled ? hal::Vsync::ENABLE : hal::Vsync::DISABLE;
// 默认显示设备是否已打开电源
if (const auto display = getDefaultDisplayDeviceLocked(); display && display->isPoweredOn()) {
// 设置硬件VSync的启用状态
setHWCVsyncEnabled(display->getPhysicalId(), mHWCVsyncPendingState);
}
}));
}
该函数主要功能是在主线程上设置硬件 VSync 的启用状态。
setHWCVsyncEnabled
源码位置:/frameworks/native/services/surfaceflinger/SurfaceFlinger.h
void setHWCVsyncEnabled(PhysicalDisplayId id, hal::Vsync enabled) {
mLastHWCVsyncState = enabled;
getHwComposer().setVsyncEnabled(id, enabled);
}
这里调用了 HWComposer 中的 setVsyncEnabled() 函数。
HWComposer.cpp
源码位置:/frameworks/native/services/surfaceflinger/DisplayHardware/HWComposer.cpp
std::unique_ptr<HWC2::Display> hwcDisplay;
void HWComposer::setVsyncEnabled(PhysicalDisplayId displayId, hal::Vsync enabled) {
RETURN_IF_INVALID_DISPLAY(displayId);
auto& displayData = mDisplayData[displayId];
……
auto error = displayData.hwcDisplay->setVsyncEnabled(enabled);
displayData.vsyncEnabled = enabled;
……
}
这里将硬件 VSync 的启用状态能够在指定的物理显示设备上正确地设置。
HWC2.cpp
源码位置:/frameworks/native/services/surfaceflinger/DisplayHardware/HWC2.cpp
Error Display::setVsyncEnabled(Vsync enabled)
{
auto intEnabled = static_cast<Hwc2::IComposerClient::Vsync>(enabled);
auto intError = mComposer.setVsyncEnabled(mId, intEnabled);
return static_cast<Error>(intError);
}
AidlComposerHal.cpp
源码位置:/frameworks/native/services/surfaceflinger/DisplayHardware/AidlComposerHal.cpp
Error AidlComposer::setVsyncEnabled(Display display, IComposerClient::Vsync enabled) {
const bool enableVsync = enabled == IComposerClient::Vsync::ENABLE;
const auto status =
mAidlComposerClient->setVsyncEnabled(translate<int64_t>(display), enableVsync);
if (!status.isOk()) {
ALOGE("setVsyncEnabled failed %s", status.getDescription().c_str());
return static_cast<Error>(status.getServiceSpecificError());
}
return Error::NONE;
}
这里接下来调用到 Hal 层,并最终调用到 硬件合成器(HWC),调用对应的预加载接口,这里就不做过多介绍了。
标签:Vsync,lock,void,SurfaceFlinger,VSync,cpp,setVsyncEnabled,Android,Scheduler From: https://blog.csdn.net/c19344881x/article/details/140875529