学向勤中得,萤窗万卷书。这篇文章主要讲述Android SurfaceFlinger服务 ----- VSync信号的分发相关的知识,希望能为你提供帮助。
HWComposer模块产生VSync信号后要经过分发才能送达到关心VSync事件的模块中去。VSync信号分发大致流程为HWComposer->
SurfaceFlinger->
DispSync->
DispSyncSource->
各个具体模块。下面具体分析下这个流程。
在上一篇文章中分析到硬件或者软件VSync信号产生时,会回调SurfaceFlinger的onVSyncReceived函数,来看看这个函数:
void SurfaceFlinger::onVSyncReceived(int type, nsecs_t timestamp) {
bool needsHwVsync = false;
{ // Scope for the lock
Mutex::Autolock _l(mHWVsyncLock);
if (type == 0 &
&
mPrimaryHWVsyncEnabled) {
needsHwVsync = mPrimaryDispSync.addResyncSample(timestamp);
}
}if (needsHwVsync) {
enableHardwareVsync();
} else {
disableHardwareVsync(false);
}
}
- mPrimaryDispSync类型为DispSync,在构造的时候会创建DispSyncThread
DispSync::DispSync() :
mRefreshSkipCount(0),
mThread(new DispSyncThread()) {mThread->
run("DispSync", PRIORITY_URGENT_DISPLAY + PRIORITY_MORE_FAVORABLE);
reset();
beginResync();
if (kTraceDetailedInfo) {
// If we‘re not getting present fences then the ZeroPhaseTracer
// would prevent HW vsync event from ever being turned off.
// Even if we‘re just ignoring the fences, the zero-phase tracing is
// not needed because any time there is an event registered we will
// turn on the HW vsync events.
if (!kIgnorePresentFences) {
addEventListener(0, new ZeroPhaseTracer());
}
}
}
- 调用DispSync的addResyncSample方法,最终会去唤醒DispSyncThread线程
bool DispSync::addResyncSample(nsecs_t timestamp) {
Mutex::Autolock lock(mMutex);
size_t idx = (mFirstResyncSample + mNumResyncSamples) % MAX_RESYNC_SAMPLES;
mResyncSamples[idx] = timestamp;
if (mNumResyncSamples <
MAX_RESYNC_SAMPLES) {
mNumResyncSamples++;
} else {
mFirstResyncSample = (mFirstResyncSample + 1) % MAX_RESYNC_SAMPLES;
}updateModelLocked();
if (mNumResyncSamplesSincePresent++ >
MAX_RESYNC_SAMPLES_WITHOUT_PRESENT) {
resetErrorLocked();
}if (kIgnorePresentFences) {
// If we don‘t have the sync framework we will never have
// addPresentFence called.This means we have no way to know whether
// or not we‘re synchronized with the HW vsyncs, so we just request
// that the HW vsync events be turned on whenever we need to generate
// SW vsync events.
return mThread->
hasAnyEventListeners();
}return mPeriod == 0 || mError >
kErrorThreshold;
}
- 调用updateModelLocked函数
- 计算是否需要开启硬件VSync,进行同步
void DispSync::updateModelLocked() {
if (mNumResyncSamples >
= MIN_RESYNC_SAMPLES_FOR_UPDATE) {......mThread->
updateModel(mPeriod, mPhase);
}
}
- 成员变量mThread为DispSyncThread类的对象
- 调用DispSyncThread类pdateModel方法
void updateModel(nsecs_t period, nsecs_t phase) {
Mutex::Autolock lock(mMutex);
mPeriod = period;
mPhase = phase;
mCond.signal();
}
- 该方法主要设置成员变量mPeriod、mPhase
- 然后在唤醒线程循环
virtual bool threadLoop() {
status_t err;
nsecs_t now = systemTime(SYSTEM_TIME_MONOTONIC);
nsecs_t nextEventTime = 0;
while (true) {
Vector<
CallbackInvocation>
callbackInvocations;
nsecs_t targetTime = 0;
{ // Scope for lock
Mutex::Autolock lock(mMutex);
......callbackInvocations = gatherCallbackInvocationsLocked(now);
}if (callbackInvocations.size() >
0) {
fireCallbackInvocations(callbackInvocations);
}
}return false;
}
- 通过gatherCallbackInvocationsLocked得到监听者集合
- 通过fireCallbackInvocations调用监听者回调函数
virtual void setVSyncEnabled(bool enable) {
Mutex::Autolock lock(mVsyncMutex);
if (enable) {
status_t err = mDispSync->
addEventListener(mPhaseOffset,
static_cast<
DispSync::Callback*>
(this));
if (err != NO_ERROR) {
ALOGE("error registering vsync callback: %s (%d)",
strerror(-err), err);
}
//ATRACE_INT(mVsyncOnLabel.string(), 1);
} else {
status_t err = mDispSync->
removeEventListener(
static_cast<
DispSync::Callback*>
(this));
if (err != NO_ERROR) {
ALOGE("error unregistering vsync callback: %s (%d)",
strerror(-err), err);
}
//ATRACE_INT(mVsyncOnLabel.string(), 0);
}
mEnabled = enable;
}
- DispSyncSource类继承于DispSync::Callback
- 调用DispSync-> addEventListener注册回调,当DispSyncSource收到DispSync的VSync信号时,会回调整onDispSyncEvent函数
virtual void onDispSyncEvent(nsecs_t when) {
sp<
VSyncSource::Callback>
callback;
{
Mutex::Autolock lock(mCallbackMutex);
callback = mCallback;
if (mTraceVsync) {
mValue = https://www.songbingjia.com/android/(mValue + 1) % 2;
ATRACE_INT(mVsyncEventLabel.string(), mValue);
}
}if (callback != NULL) {
callback->
onVSyncEvent(when);
}
}
- 这个函数最终还是调用VSyncSource::Callback的onVSyncEvent函数。
- VSyncSource::Callback函数的注册是通过调用DispSyncSource的setCallback注册。
void SurfaceFlinger::init() {......// start the EventThread
sp<
VSyncSource>
vsyncSrc = https://www.songbingjia.com/android/new DispSyncSource(&
mPrimaryDispSync,
vsyncPhaseOffsetNs, true,"app");
mEventThread = new EventThread(vsyncSrc);
sp<
VSyncSource>
sfVsyncSrc = https://www.songbingjia.com/android/new DispSyncSource(&
mPrimaryDispSync,
sfVsyncPhaseOffsetNs, true,"sf");
mSFEventThread = new EventThread(sfVsyncSrc);
mEventQueue.setEventThread(mSFEventThread);
......
}
- 以sfVsyncSrc为参数创建EventThread对象
- 在EventThread的线程循环中会去调用enableVSyncLocked函数
void EventThread::enableVSyncLocked() {
if (!mUseSoftwareVSync) {
// never enable h/w VSYNC when screen is off
if (!mVsyncEnabled) {
mVsyncEnabled = true;
mVSyncSource->
setCallback(static_cast<
VSyncSource::Callback*>
(this));
mVSyncSource->
setVSyncEnabled(true);
}
}
mDebugVsyncEnabled = true;
sendVsyncHintOnLocked();
}
- EventThread继承VSyncSource::Callback接口,实现了onVSyncEvent函数
- 调用mVSyncSource的setCallback函数设置回调
- 调用mVSyncSource的setVSyncEnabled函数使能VSync信号的监听
void EventThread::onVSyncEvent(nsecs_t timestamp) {
Mutex::Autolock _l(mLock);
mVSyncEvent[0].header.type = DisplayEventReceiver::DISPLAY_EVENT_VSYNC;
mVSyncEvent[0].header.id = 0;
mVSyncEvent[0].header.timestamp = timestamp;
mVSyncEvent[0].vsync.count++;
mCondition.broadcast();
}
- EventThread收到VSync信号后,发送广播消息,唤醒相关线程
- 最终EventThread将VSnc信号传递给MessageQueue
推荐阅读
- AndroidStudio制作欢迎界面与应用图标
- android布局中使用include及需注意点
- Spring框架 ? 项目启动时执行特定处理及ApplicationListener源码分析
- android 调用系统相机录像并保存
- Android各大手机系统打开权限管理页面
- Spring框架 ? WebApplicationInitializer源码分析及应用
- android学习(intent和Bundle传值上的区别)
- 推荐!Python Pandas面试题和答案详解
- Kali Linux面试题和答案精华推荐