App 的Vsync 信号已经进行了注册,那什么时候和怎么返回这个信号到 Choreographer.java的onVsync呢,DispSync对象在创建的时候会启动一个DispSyncThread线程,该线程用于模拟Vsync信号,主要是在DispSync.cpp文件中。
![](https://i-blog.csdnimg.cn/blog_migrate/a1560c8b28b910cbbd1dc6873e1d45a1.png)
堆栈信息如下:
2021-03-23 14:21:53.423 968-1128/? D/zx1: #00 pc 000000000009090c /system/lib64/libgui.so (android::DisplayEventReceiver::sendEvents(android::gui::BitTube*, android::DisplayEventReceiver::Event const*, unsigned long)+72)
2021-03-23 14:21:53.423 968-1128/? D/zx1: #01 pc 00000000000f5d78 /system/lib64/libsurfaceflinger.so (android::EventThreadConnection::postEvent(android::DisplayEventReceiver::Event const&)+84)
2021-03-23 14:21:53.423 968-1128/? D/zx1: #02 pc 00000000000f796c /system/lib64/libsurfaceflinger.so (void* std::__1::__thread_proxy<std::__1::tuple<std::__1::unique_ptr<std::__1::__thread_struct, std::__1::default_delete<std::__1::__thread_struct> >, android::impl::EventThread::EventThread(std::__1::unique_ptr<android::VSyncSource, std::__1::default_delete<android::VSyncSource> >, std::__1::function<void (long)>)::$_0> >(void*)+1504)
2021-03-23 14:21:53.423 968-1128/? D/zx1: #03 pc 00000000000b0654 /apex/com.android.runtime/lib64/bionic/libc.so (__pthread_start(void*)+392)
2021-03-23 14:21:53.423 968-1128/? D/zx1: #04 pc 0000000000050888 /apex/com.android.runtime/lib64/bionic/libc.so (__start_thread+64)
/frameworks/native/services/surfaceflinger/scheduler/DispSync.cpp
DispSync::DispSync(const char* name, bool hasSyncFramework)
: mName(name), mIgnorePresentFences(!hasSyncFramework) {
// This flag offers the ability to turn on systrace logging from the shell.
char value[PROPERTY_VALUE_MAX];
property_get("debug.sf.dispsync_trace_detailed_info", value, "0");
mTraceDetailedInfo = atoi(value);
mThread = new DispSyncThread(name, mTraceDetailedInfo);
mThread->run("DispSync", PRIORITY_URGENT_DISPLAY + PRIORITY_MORE_FAVORABLE); @1
// set DispSync to SCHED_FIFO to minimize jitter
struct sched_param param = {0};
param.sched_priority = 2;
if (sched_setscheduler(mThread->getTid(), SCHED_FIFO, ¶m) != 0) {
ALOGE("Couldn't set SCHED_FIFO for DispSyncThread");
}
beginResync();
if (mTraceDetailedInfo && kEnableZeroPhaseTracer) {
mZeroPhaseTracer = std::make_unique<ZeroPhaseTracer>();
addEventListener("ZeroPhaseTracer", 0, mZeroPhaseTracer.get(), 0);
}
}
class DispSyncThread : public Thread {
......
}
在@1处创建了DispSyncThread 并执行了run方法,由于DispSyncThread继承Thread, run方法执行后会执行DispSyncThread的 threadLoop方法,
/frameworks/native/services/surfaceflinger/scheduler/DispsSync.cpp
virtual bool threadLoop() {
nsecs_t now = systemTime(SYSTEM_TIME_MONOTONIC);
while (true) {
std::vector<CallbackInvocation> callbackInvocations;
......
callbackInvocations = gatherCallbackInvocationsLocked(now, computeNextRefreshLocked(0, now)); @1
if (callbackInvocations.size() > 0) {
fireCallbackInvocations(callbackInvocations); @2
}
}
......
省略了若干代码,此处是一个死循环,用于制造模拟信号。最终会到代码末尾@1 @2处,@1处是收集注册的listener信息,@2处就是进行回调。
nsecs_t computeNextRefreshLocked(int periodOffset, nsecs_t now) const {
nsecs_t phase = mReferenceTime + mPhase;
if (mPeriod == 0) {
return 0;
}
return (((now - phase) / mPeriod) + periodOffset + 1) * mPeriod + phase;
}
有一定的计算,最终返回一个时间,从命名上面看,意思是计算下一个刷新时间。
再看gatherCallbackInvocationsLocked,第一个参数是从开机开始算,第二个参数就是computeNextRefreshLocked算出来的那个。
std::vector<CallbackInvocation> gatherCallbackInvocationsLocked(nsecs_t now,
nsecs_t expectedVSyncTime) {
if (mTraceDetailedInfo) ATRACE_CALL();
ALOGV("[%s] gatherCallbackInvocationsLocked @ %" PRId64, mName, ns2us(now));
std::vector<CallbackInvocation> callbackInvocations;
nsecs_t onePeriodAgo = now - mPeriod;
for (auto& eventListener : mEventListeners) { @1
nsecs_t t = computeListenerNextEventTimeLocked(eventListener, onePeriodAgo);
if (t < now) {
if (isCloseToPeriod(now - eventListener.mLastCallbackTime)) {
eventListener.mLastEventTime = t;
ALOGV("[%s] [%s] Skipping event due to model error", mName,
eventListener.mName);
continue;
}
CallbackInvocation ci;
ci.mCallback = eventListener.mCallback;
ci.mEventTime = t;
ci.mExpectedVSyncTime = expectedVSyncTime;
if (eventListener.mPhase < 0) {
ci.mExpectedVSyncTime += mPeriod;
}
ALOGV("[%s] [%s] Preparing to fire, latency: %" PRId64, mName, eventListener.mName,
t - eventListener.mLastEventTime);
callbackInvocations.push_back(ci);
eventListener.mLastEventTime = t;
eventListener.mLastCallbackTime = now;
}
}
return callbackInvocations;
}
@1 处是一个for循环,遍历mEventListeners。之前注册的listener全部被mEventListeners.push_back存起来( 回忆addEventListener方法)。mEventListeners经过一系列的操作存入到了callbackInvocations中。主要就是把EventListener对象值 赋给callbackInvocation对象。
它两个的结构体
struct EventListener {
const char* mName;
nsecs_t mPhase;
nsecs_t mLastEventTime;
nsecs_t mLastCallbackTime;
DispSync::Callback* mCallback;
};
struct CallbackInvocation {
DispSync::Callback* mCallback;
nsecs_t mEventTime;
nsecs_t mExpectedVSyncTime;
};
接下来会执行fireCallbakcInvocations方法。
void fireCallbackInvocations(const std::vector<CallbackInvocation>& callbacks) {
if (mTraceDetailedInfo) ATRACE_CALL();
for (size_t i = 0; i < callbacks.size(); i++) {
callbacks[i].mCallback->onDispSyncEvent(callbacks[i].mEventTime, callbacks[i].mExpectedVSyncTime);
}
}
很明显 要把vsync分发下去,且有两个参数。
/frameworks/native/services/surfaceflinger/Scheduler/DispSyncSource.cpp
void DispSyncSource::onDispSyncEvent(nsecs_t when, nsecs_t expectedVSyncTimestamp) {
VSyncSource::Callback* callback;
{
std::lock_guard lock(mCallbackMutex);
callback = mCallback;
}
if (mTraceVsync) {
mValue = (mValue + 1) % 2;
}
if (callback != nullptr) {
callback->onVSyncEvent(when, expectedVSyncTimestamp);
}
}
void DispSyncSource::setCallback(VSyncSource::Callback* callback) {
std::lock_guard lock(mCallbackMutex);
mCallback = callback;
}
callback是谁呢,发现是在EventThread的构造方法中调用了DispSyncSource的setCallback方法
/frameworks/native/services/surfaceflinger/Scheduler/EventThread.cpp
EventThread::EventThread(std::unique_ptr<VSyncSource> vsyncSource,
InterceptVSyncsCallback interceptVSyncsCallback)
: mVSyncSource(std::move(vsyncSource)),
mInterceptVSyncsCallback(std::move(interceptVSyncsCallback)),
mThreadName(mVSyncSource->getName()) {
mVSyncSource->setCallback(this);
所以这个callback就是eventthread的对象,所以就会调用到EventThread的onVsyncEvent方法
/frameworks/native/services/surfaceflinger/Scheduler/EventThread.cpp
void EventThread::onVSyncEvent(nsecs_t timestamp, nsecs_t expectedVSyncTimestamp) {
std::lock_guard<std::mutex> lock(mMutex);
LOG_FATAL_IF(!mVSyncState);
mPendingEvents.push_back(makeVSync(mVSyncState->displayId, timestamp, ++mVSyncState->count,
expectedVSyncTimestamp));
mCondition.notify_all();
}
重要的一句mCondition.notify_all,唤醒 threadMain中wait的地方,进行下一个循环,会执行如下语句
void EventThread::threadMain(std::unique_lock<std::mutex>& lock) {
......
if (!consumers.empty()) {
dispatchEvent(*event, consumers);
consumers.clear();
}
......
}
这个consumer是什么,它是eventThreadConnection,consumer会在threadMain中的循环,根据mDisplayEventConnections的数据来填充,注册过当然不为空,下一句consumer.clear,
都分发出去了,当然要清空了,否则下次多发了vsync,不就出问题了。
void EventThread::dispatchEvent(const DisplayEventReceiver::Event& event,
const DisplayEventConsumers& consumers) {
for (const auto& consumer : consumers) {
switch (consumer->postEvent(event)) { @1
case NO_ERROR:
break;
case -EAGAIN:
// TODO: Try again if pipe is full.
ALOGW("Failed dispatching %s for %s", toString(event).c_str(),
toString(*consumer).c_str());
break;
default:
// Treat EPIPE and other errors as fatal.
removeDisplayEventConnectionLocked(consumer); @2;
}
}
}
@1处执行EventThreadConnection的postEvent方法,@2处移除掉此监听。就验证了咱们的请求一次vsync,返回一次vsync。
status_t EventThreadConnection::postEvent(const DisplayEventReceiver::Event& event) {
ssize_t size = DisplayEventReceiver::sendEvents(&mChannel, &event, 1);
return size < 0 ? status_t(size) : status_t(NO_ERROR);
}
/frameworks/native/libs/gui/DisplayEventReceiver.cpp
ssize_t DisplayEventReceiver::sendEvents(gui::BitTube* dataChannel,
Event const* events, size_t count)
{
return gui::BitTube::sendObjects(dataChannel, events, count);
}
这块就发出去了,跨进程?之后就能到Choreograhper.java 的onVsync。
打印了一下Choreographer onVsync堆栈
2021-03-23 14:21:53.449 1686-2293/system_process D/zx1 Choreographer: java.lang.Throwable
at android.view.Choreographer$FrameDisplayEventReceiver.onVsync(Choreographer.java:1015)
at android.view.DisplayEventReceiver.dispatchVsync(DisplayEventReceiver.java:203)
at android.os.MessageQueue.nativePollOnce(Native Method)
at android.os.MessageQueue.next(MessageQueue.java:335)
at android.os.Looper.loop(Looper.java:195)
at android.os.HandlerThread.run(HandlerThread.java:67)
at com.android.server.ServiceThread.run(ServiceThread.java:44)
可以知道这条vsync从何而来。但中间怎么通过BitTube 跨进程的,目前还咩有看出来,问题暂存。
看一下Choreographer.java 的FrameDisplayEventReceive 的onVsync
/frameworks/base/core/java/android/view/Choreographer.java
private final class FrameDisplayEventReceiver extends DisplayEventReceiver
implements Runnable {
private boolean mHavePendingVsync;
private long mTimestampNanos;
private int mFrame;
public FrameDisplayEventReceiver(Looper looper, int vsyncSource) {
super(looper, vsyncSource, CONFIG_CHANGED_EVENT_SUPPRESS);
}
// TODO(b/116025192): physicalDisplayId is ignored because SF only emits VSYNC events for
// the internal display and DisplayEventReceiver#scheduleVsync only allows requesting VSYNC
// for the internal display implicitly.
@Override
public void onVsync(long timestampNanos, long physicalDisplayId, int frame) {
// Post the vsync event to the Handler.
// The idea is to prevent incoming vsync events from completely starving
// the message queue. If there are no messages in the queue with timestamps
// earlier than the frame time, then the vsync event will be processed immediately.
// Otherwise, messages that predate the vsync event will be handled first.
long now = System.nanoTime();
if (timestampNanos > now) {
Log.w(TAG, "Frame time is " + ((timestampNanos - now) * 0.000001f)
+ " ms in the future! Check that graphics HAL is generating vsync "
+ "timestamps using the correct timebase.");
timestampNanos = now;
}
if (mHavePendingVsync) {
Log.w(TAG, "Already have a pending vsync event. There should only be "
+ "one at a time.");
} else {
mHavePendingVsync = true;
}
mTimestampNanos = timestampNanos;
mFrame = frame;
Message msg = Message.obtain(mHandler, this); @1
msg.setAsynchronous(true); @2
mHandler.sendMessageAtTime(msg, timestampNanos / TimeUtils.NANOS_PER_MS);
}
@Override
public void run() { @3
mHavePendingVsync = false;
doFrame(mTimestampNanos, mFrame);
}
}
在@2处设置了此message为异步消息,还记得当时在ViewRootImpl的scheduleTraversals方法吗?
@UnsupportedAppUsage
void scheduleTraversals() {
......
mTraversalBarrier = mHandler.getLooper().getQueue().postSyncBarrier();
mChoreographer.postCallback(
Choreographer.CALLBACK_TRAVERSAL, mTraversalRunnable, null);
......
}
}
对在申请Vsync之前mHandler.getLooper().getQueue().postSyncBarrier(); 设置了同步栅栏,也就是所申请的vsync信号到来后,优先执行异步消息。而在@2处设置了此消息为异步消息,此消息就会优先执行,所以一般view的更新消息是优先执行的。执行完了异步消息后就会通过removeSyncBarrier该方法将同步屏障移除。(方法在 MessageQueue.java 中)
在@1 处注意看一下obtain第二个参数是this,FrameDisplayEventReceiver implements Runnable,所以this为当前runnable, Message中的callback也就不为null了
/frameworks/base/core/java/android/os/Message.java
public static Message obtain(Handler h, Runnable callback) {
Message m = obtain();
m.target = h;
m.callback = callback;
return m;
}
而我们都知道Handle的handleMessage在执行之前会执行dispatchMessage
/frameworks/base/core/java/android/os/Handler.java
/**
* Handle system messages here.
*/
public void dispatchMessage(@NonNull Message msg) {
if (msg.callback != null) { @4
handleCallback(msg);
} else {
if (mCallback != null) {
if (mCallback.handleMessage(msg)) {
return;
}
}
handleMessage(msg);
}
}
在@3处 很明显msg.callback不为空,执行handleCallback
/frameworks/base/core/java/android/os/Handler.java
private static void handleCallback(Message message) {
message.callback.run();
}
这个run方法又让回到了Choreographer中的 FrameDisplayEventReceiver中的run方法也就会@3处,会执行我们熟悉的doFrame,两个参数第一个应该是vsync信号的时间,第二个参数根据前面是1,
@UnsupportedAppUsage
void doFrame(long frameTimeNanos, int frame) {
}
![](https://i-blog.csdnimg.cn/blog_migrate/f856b381b167c0f3fa473064bd5e2b52.png)
App申请Vsync信号和Vsync信号的返回大致说完。接下来应用的绘制后续再看。