• View绘制流程-Vsync信号是如何发送和接受的


    前言:

    vsync信号其实主要有两种,APP和SF两种。

    两种类似的信号分别具有以下的作用:

    1.APP类型,我们常说的Vsync信号其实指的就是这种类型。

    2.SF类型,我感觉有可能是SurfaceFlinger的缩写,这个同步信号主要是通知进行数据buffer的合成。

    本文主要探讨的主APP类型的Vsync信号,SF类型的会在另外一篇文章,View绘制流程中讲解。

    一.整体流程简介

    我把app-VSync的整个流程分为四大块:

    第一块,APP侧发出请求信号,通知到SurfaceFlinger;

    第二块,SurfaceFlinger收到通知后,作为消费者侧去缓存池中查询是否存在VSYNC,如果有,则通知APP侧。

    第三块,SurfaceFlinger中的生产者逻辑,生产下一次的Vsync信号。

    第四块,APP侧收到Vsync信号后进行处理,最终完成绘制流程。

    整体的流程图如下图所示,后续文章也会按照这四大块流程去细讲。


     

    二.客户端发出信号

    2.1 java端流转

    我们把代码的开始点设置为ViewRootImpl中的scheduleTraversals方法,如果想了解这个方法之前的流程,可以参看我的另外一篇文章:

    View绘制流程2-安卓是如何执行measure/layout/draw三个绘制流程_失落夏天的博客-CSDN博客

    scheduleTraversals是负责渲染流程的,界面上任何布局上的改动,最终都会执行这个方法进行刷新操作。scheduleTraversals会通过Choreographer的postCallback方法去请求Vsync信号并且设置回调方法。

    1. mChoreographer.postCallback(
    2. Choreographer.CALLBACK_TRAVERSAL, mTraversalRunnable, null);

    Choreographer中的最终实现是postCallbackDelayedInternal方法:

    1. private void postCallbackDelayedInternal(int callbackType,
    2. Object action, Object token, long delayMillis) {
    3. ...
    4. synchronized (mLock) {
    5. final long now = SystemClock.uptimeMillis();
    6. final long dueTime = now + delayMillis;
    7. mCallbackQueues[callbackType].addCallbackLocked(dueTime, action, token);
    8. if (dueTime <= now) {
    9. scheduleFrameLocked(now);
    10. }
    11. ...
    12. }
    13. }

    这个方法会把回调加入到mCallbackQueues中,然后通过scheduleFrameLocked方法开始请求Vsync信号。

    scheduleFrameLocked中又会进行层层传递,最终调用到native方法。传递关系如下:

    1. scheduleFrameLocked(Choreographer.java)->
    2. scheduleVsyncLocked(Choreographer.java)->
    3. scheduleVsync(DisplayEventReceiver.java)->
    4. nativeScheduleVsync(DisplayEventReceiver.java)

    2.2 native方法中的逻辑流转

    nativeScheduleVsync在native层的注册是DisplayEventReceiver.cpp中的nativeScheduleVsync方法,方法中通过NativeDisplayEventReceiver的scheduleVsync来完成请求:

    1. static void nativeScheduleVsync(JNIEnv* env, jclass clazz, jlong receiverPtr) {
    2. sp<NativeDisplayEventReceiver> receiver =
    3. reinterpret_cast<NativeDisplayEventReceiver*>(receiverPtr);
    4. status_t status = receiver->scheduleVsync();
    5. ...
    6. }

    NativeDisplayEventReceiver是DisplayEventDispatcher的子类,scheduleVsync方法会执行到DisplayEventDispatcher中的scheduleVsync方法,调用DisplayEventReceiver的requestNextVsync继续请求流程。

    1. status_t DisplayEventDispatcher::scheduleVsync() {
    2. if (!mWaitingForVsync) {
    3. ...
    4. status_t status = mReceiver.requestNextVsync();
    5. ...
    6. mWaitingForVsync = true;
    7. ...
    8. }
    9. return OK;
    10. }

    这里有一个本地变量mWaitingForVsync,如果请求了一次sync,就会改为true,接下来的Vsync请求,都不会传输到SurfaceFlinger一层了,避免重复无意义请求。只有等到收到Vsync信号的时候,才会改为false。

    DisplayEventReceiver中,会交给mEventConnection处理:

    1. status_t DisplayEventReceiver::requestNextVsync() {
    2. if (mEventConnection != nullptr) {
    3. mEventConnection->requestNextVsync();
    4. return NO_ERROR;
    5. }
    6. return NO_INIT;
    7. }

    mEventConnection其实是一个binder客户端,是在创建DisplayEventReceiver的时候通过binder方法创建的,其binder服务端实现在SurfaceFlinger进程侧的EventThread.cpp。

    1. DisplayEventReceiver::DisplayEventReceiver(
    2. ISurfaceComposer::VsyncSource vsyncSource,
    3. ISurfaceComposer::EventRegistrationFlags eventRegistration) {
    4. sp<ISurfaceComposer> sf(ComposerService::getComposerService());
    5. if (sf != nullptr) {
    6. mEventConnection = sf->createDisplayEventConnection(vsyncSource, eventRegistration);
    7. ...
    8. }
    9. }

    三.SurfaceFlinger端Vsync信号消费者

    首先,SurfaceFlinger的总体结构图如下,SurfaceFlinger中存在一个Scheduler,Scheduler中存在多个VsyncDispatch。其中VSYNC-app负责所有APP的VSYNC信号的处理,本文主要讲的也是这个流程中的。

    其次,下图是主流程图中的一部分,也是本章要讲的内容。

    3.1 EventThread收到通知后,转发EventThread的工作线程 

    是接收方法如下,转发到mEventThread的requestNextVsync方法中。

    1. binder::Status EventThreadConnection::requestNextVsync() {
    2. ATRACE_CALL();
    3. mEventThread->requestNextVsync(this);
    4. return binder::Status::ok();
    5. }

    我们接着看一下EventThread中的requestNextVsync方法:

    1. void EventThread::requestNextVsync(const sp<EventThreadConnection>& connection) {
    2. ...
    3. if (connection->vsyncRequest == VSyncRequest::None) {
    4. connection->vsyncRequest = VSyncRequest::Single;
    5. mCondition.notify_all();
    6. } else if (connection->vsyncRequest == VSyncRequest::SingleSuppressCallback) {
    7. connection->vsyncRequest = VSyncRequest::Single;
    8. }
    9. }

    这里的逻辑很简单,如果当前的VSYNC状态是None的话,释放锁mCondition。

    这里既然notify_all,那么一定有地方wait等待锁,而等待的地方就是threadMain方法。

    3.2 threadMain方法

    这个方法算是整个Vsync流程的核心,它是一个无限循环的模式,其作用是不断的从mPendingEvents中获取Vsync信号,然后转交给APP端。并且在一次Vsync流程结束后,又通过VsyncSource请求下一次的Vsync信号。

    threadMain方法是EventThread类初始化的时候创建的线程去执行的方法:

    1. mThread = std::thread([this]() NO_THREAD_SAFETY_ANALYSIS {
    2. std::unique_lock<std::mutex> lock(mMutex);
    3. threadMain(lock);
    4. });

    我们看一下精简后的threadMain方法:

    1. void EventThread::threadMain(std::unique_lock<std::mutex>& lock) {
    2. DisplayEventConsumers consumers;
    3. //只要没有退出,就一直循环
    4. while (mState != State::Quit) {
    5. 执行以下1-7的操作
    6. }
    7. }

    总体来说,分为以下四大步骤:

    1.作为消费者尝试从mPendingEvents中获取Vsync信号,如果获取成功,则赋值给event。

    1. std::optional<DisplayEventReceiver::Event> event;
    2. //查看mPendingEvents中是否存在Vsync信号
    3. if (!mPendingEvents.empty()) {
    4. event = mPendingEvents.front();
    5. mPendingEvents.pop_front();
    6. ...
    7. }

    2.计算vsyncRequested的状态,只要客户端消费者的Connection保持连接,则vsyncRequested=true,并且上面步骤一获取到event的话,则把消费者的connection加入到consumers集合中。

    1. bool vsyncRequested = false;
    2. //获取当前的状态,并且判断是否有客户端的消费者在请求,如果有则加入到consumers集合中
    3. auto it = mDisplayEventConnections.begin();
    4. while (it != mDisplayEventConnections.end()) {
    5. if (const auto connection = it->promote()) {
    6. //客户端还是处于请求的状态
    7. vsyncRequested |= connection->vsyncRequest != VSyncRequest::None;
    8. if (event && shouldConsumeEvent(*event, connection)) {
    9. consumers.push_back(connection);
    10. }
    11. ++it;
    12. } else {
    13. it = mDisplayEventConnections.erase(it);
    14. }
    15. }

    3.如果consumers集合不为空,则进行消费。把Vsync信号分发给消费者。(具体步骤我们下一小节中讲)

    1. //如果消费者不为空,则通过dispatchEvent方法最终通知到APP一侧
    2. if (!consumers.empty()) {
    3. dispatchEvent(*event, consumers);
    4. consumers.clear();
    5. }

    4.获取下一个状态

    1. //mVSyncState不会为空,则主要是根据vsyncRequested来判断的。vsyncRequested上面计算的
    2. State nextState;
    3. if (mVSyncState && vsyncRequested) {
    4. nextState = mVSyncState->synthetic ? State::SyntheticVSync : State::VSync;
    5. } else {
    6. ALOGW_IF(!mVSyncState, "Ignoring VSYNC request while display is disconnected");
    7. nextState = State::Idle;
    8. }

    5.进行判断,确定是否需要请求VSYNC信号。这一块挺有意思的,简单理解如下:

    如果当前是VSYNC状态,下一个状态也是VSYNC状态,那么说明信号还没来,所以没必要重复发送。

    如果当前是Idle状态,下一个状态是VSYNC状态,那么则要进行VSYNC信号请求。

    如果当前是VSYNC状态,下一个状态也是Idle状态,那么说明信号已经来了,下一次的客户端请求还没来,所以不要进行VSYNC信号请求,则会进行取消操作。

    1. if (mState != nextState) {
    2. if (mState == State::VSync) {
    3. mVSyncSource->setVSyncEnabled(false);
    4. } else if (nextState == State::VSync) {
    5. //如果下一个状态还是VSync,则继续去请求VSYNC信号
    6. mVSyncSource->setVSyncEnabled(true);
    7. }
    8. mState = nextState;
    9. }

    如何开始和结束去进行VSYNC信号获取的获取操作,我们第四章中讲,这个主要就是消费者逻辑了。

    6.如果event为空,说明mPendingEvents中已经取光了,则进入休眠操作。

    反之event不为空,说明mPendingEvents中也许还存在未消费的VSYNC信号,则contine继续消费。

    1. //如果处理了event,那么说明此次已经拿到了Vsync信号,说明后面有可能还有,则继续拿
    2. if (event) {
    3. continue;
    4. }

    7.进入休眠或者超时之后主动模拟信号加入到mPendingEvents中。

    1. //说明Vsync信号已经消费完了,则进入休眠模式,等到APP侧的下一次通知进行唤醒
    2. // Wait for event or client registration/request.
    3. if (mState == State::Idle) {
    4. mCondition.wait(lock);
    5. } else {
    6. // Generate a fake VSYNC after a long timeout in case the driver stalls. When the
    7. // display is off, keep feeding clients at 60 Hz.
    8. const std::chrono::nanoseconds timeout =
    9. mState == State::SyntheticVSync ? 16ms : 1000ms;
    10. if (mCondition.wait_for(lock, timeout) == std::cv_status::timeout) {
    11. if (mState == State::VSync) {
    12. ALOGW("Faking VSYNC due to driver stall for thread %s", mThreadName);
    13. std::string debugInfo = "VsyncSource debug info:\n";
    14. mVSyncSource->dump(debugInfo);
    15. // Log the debug info line-by-line to avoid logcat overflow
    16. auto pos = debugInfo.find('\n');
    17. while (pos != std::string::npos) {
    18. ALOGW("%s", debugInfo.substr(0, pos).c_str());
    19. debugInfo = debugInfo.substr(pos + 1);
    20. pos = debugInfo.find('\n');
    21. }
    22. }
    23. LOG_FATAL_IF(!mVSyncState);
    24. const auto now = systemTime(SYSTEM_TIME_MONOTONIC);
    25. const auto deadlineTimestamp = now + timeout.count();
    26. const auto expectedVSyncTime = deadlineTimestamp + timeout.count();
    27. mPendingEvents.push_back(makeVSync(mVSyncState->displayId, now,
    28. ++mVSyncState->count, expectedVSyncTime,
    29. deadlineTimestamp));
    30. }
    31. }

    3.3  dispatchEvent方法把Vsync信号分发给消费者

    首先遍历消费者,调用postEvent进行通知

    1. void EventThread::dispatchEvent(const DisplayEventReceiver::Event& event,
    2. const DisplayEventConsumers& consumers) {
    3. for (const auto& consumer : consumers) {
    4. ...
    5. switch (consumer->postEvent(copy)) {
    6. }
    7. }
    8. }

    然后postEvent方法中,调用sendEvent进行信号的发送

    1. status_t EventThreadConnection::postEvent(const DisplayEventReceiver::Event& event) {
    2. ...
    3. auto size = DisplayEventReceiver::sendEvents(&mChannel, mPendingEvents.data(),
    4. mPendingEvents.size());
    5. ...
    6. }

    最终通过Socket的方法进行信号的发送,接受者就是APP侧了。

    1. ssize_t DisplayEventReceiver::sendEvents(gui::BitTube* dataChannel,
    2. Event const* events, size_t count)
    3. {
    4. return gui::BitTube::sendObjects(dataChannel, events, count);
    5. }

    四.SurfaceFlinger端生产者

    上面讲到通过setVSyncEnabled方法去开始或者结束获取Vsync信号的操作。

    4.1 获取VSYNC信号

    setVSyncEnabled方法如下:

    1. void DispSyncSource::setVSyncEnabled(bool enable) {
    2. std::lock_guard lock(mVsyncMutex);
    3. if (enable) {
    4. mCallbackRepeater->start(mWorkDuration, mReadyDuration);
    5. } else {
    6. mCallbackRepeater->stop();
    7. }
    8. mEnabled = enable;
    9. }

    对应的其实就是mCallbackRepeater的start和stop方法,其实现类是DispSyncSource.cpp中的CallbackRepeater。

    我们这里看到一个成员变量mWorkDuration,这个值其实就是控制Vscyn触发时间的。这个我们后续小节再讲,这里只是知道有这个值就好了。

    4.2 把时间设置给Timer定时触发

    start方法中,记录一下传入的workDuration时间,然后传递给mRegistration处理。

    1. void start(std::chrono::nanoseconds workDuration, std::chrono::nanoseconds readyDuration) {
    2. std::lock_guard lock(mMutex);
    3. mStarted = true;
    4. mWorkDuration = workDuration;
    5. mReadyDuration = readyDuration;
    6. auto const scheduleResult =
    7. mRegistration.schedule({.workDuration = mWorkDuration.count(),
    8. .readyDuration = mReadyDuration.count(),
    9. .earliestVsync = mLastCallTime.count()});
    10. }

    mRegistration的实现类是VSyncCallbackRegistration,其中schedule方法也是交给VSyncDispatchTimerQueue来处理:

    1. ScheduleResult VSyncCallbackRegistration::schedule(VSyncDispatch::ScheduleTiming scheduleTiming) {
    2. if (!mValidToken) {
    3. return std::nullopt;
    4. }
    5. return mDispatch.get().schedule(mToken, scheduleTiming);
    6. }

    schedule方法中,进行一系列的合法判断,最终会交给 rearmTimerSkippingUpdateFor方法处理。

    然后我们就可以看到rearmTimerSkippingUpdateFor中去调用setTimer方法去设置定时触发。

    rearmTimerSkippingUpdateFor方法略,

    setTimer方法如下:

    1. void VSyncDispatchTimerQueue::setTimer(nsecs_t targetTime, nsecs_t /*now*/) {
    2. mIntendedWakeupTime = targetTime;
    3. mTimeKeeper->alarmAt(std::bind(&VSyncDispatchTimerQueue::timerCallback, this),
    4. mIntendedWakeupTime);
    5. mLastTimerSchedule = mTimeKeeper->now();
    6. }

    则到了targetTime之后,就会执行timerCallBack方法。

    4.3 生成Vsync信号加入mPendingEvents

    timerCallback方法如下:

    1. void VSyncDispatchTimerQueue::timerCallback() {
    2. struct Invocation {
    3. std::shared_ptr<VSyncDispatchTimerQueueEntry> callback;
    4. nsecs_t vsyncTimestamp;
    5. nsecs_t wakeupTimestamp;
    6. nsecs_t deadlineTimestamp;
    7. };
    8. std::vector<Invocation> invocations;
    9. {
    10. std::lock_guard lock(mMutex);
    11. auto const now = mTimeKeeper->now();
    12. mLastTimerCallback = now;
    13. for (auto it = mCallbacks.begin(); it != mCallbacks.end(); it++) {
    14. auto& callback = it->second;
    15. auto const wakeupTime = callback->wakeupTime();
    16. if (!wakeupTime) {
    17. continue;
    18. }
    19. auto const readyTime = callback->readyTime();
    20. auto const lagAllowance = std::max(now - mIntendedWakeupTime, static_cast<nsecs_t>(0));
    21. if (*wakeupTime < mIntendedWakeupTime + mTimerSlack + lagAllowance) {
    22. callback->executing();
    23. invocations.emplace_back(Invocation{callback, *callback->lastExecutedVsyncTarget(),
    24. *wakeupTime, *readyTime});
    25. }
    26. }
    27. mIntendedWakeupTime = kInvalidTime;
    28. rearmTimer(mTimeKeeper->now());
    29. }
    30. for (auto const& invocation : invocations) {
    31. invocation.callback->callback(invocation.vsyncTimestamp, invocation.wakeupTimestamp,
    32. invocation.deadlineTimestamp);
    33. }

    这里的核心逻辑其实就是遍历mCallbacks,然后分别回调。

    那么mCallbacks是怎么添加的呢? CallbackRepeater创建的时候,回去注册 mRegistration,同时会传入CallbackRepeater::callback方法作为回调,所以mCallbacks其实就是CallbackRepeater::callback。

    1. void callback(nsecs_t vsyncTime, nsecs_t wakeupTime, nsecs_t readyTime) {
    2. ...
    3. mCallback(vsyncTime, wakeupTime, readyTime);
    4. ...
    5. }

    很明显直接交给mCallback处理,所以我们又得看一下这个mCallback从何而来。

    这个mCallback是CallbackRepeater创建时传入的DispSyncSource::onVsyncCallback方法:

    1. mCallbackRepeater =
    2. std::make_unique<CallbackRepeater>(vSyncDispatch,
    3. std::bind(&DispSyncSource::onVsyncCallback, this,
    4. std::placeholders::_1,
    5. std::placeholders::_2,
    6. std::placeholders::_3),
    7. name, workDuration, readyDuration,
    8. std::chrono::steady_clock::now().time_since_epoch());

    所以,最终会调用到DispSyncSource::onVsyncCallback方法:

    1. void DispSyncSource::onVsyncCallback(nsecs_t vsyncTime, nsecs_t targetWakeupTime,
    2. nsecs_t readyTime) {
    3. VSyncSource::Callback* callback;
    4. {
    5. std::lock_guard lock(mCallbackMutex);
    6. callback = mCallback;
    7. }
    8. ...
    9. if (callback != nullptr) {
    10. callback->onVSyncEvent(targetWakeupTime, {vsyncTime, readyTime});
    11. }
    12. }

    又是回调,这里很绕。这里的callback其实就是EventThread,仍然是在创建EventThread的时候设置的:

    1. EventThread::EventThread(std::unique_ptr<VSyncSource> vsyncSource,
    2. android::frametimeline::TokenManager* tokenManager,
    3. InterceptVSyncsCallback interceptVSyncsCallback,
    4. ThrottleVsyncCallback throttleVsyncCallback,
    5. GetVsyncPeriodFunction getVsyncPeriodFunction)
    6. : mVSyncSource(std::move(vsyncSource)),
    7. mTokenManager(tokenManager),
    8. mInterceptVSyncsCallback(std::move(interceptVSyncsCallback)),
    9. mThrottleVsyncCallback(std::move(throttleVsyncCallback)),
    10. mGetVsyncPeriodFunction(std::move(getVsyncPeriodFunction)),
    11. mThreadName(mVSyncSource->getName()) {
    12. LOG_ALWAYS_FATAL_IF(getVsyncPeriodFunction == nullptr,
    13. "getVsyncPeriodFunction must not be null");
    14. mVSyncSource->setCallback(this);
    15. ...
    16. }

    所以,终于可以看到尽头了。最终其实就是调用到EventThread的onVSyncEvent方法:

    1. void EventThread::onVSyncEvent(nsecs_t timestamp, VSyncSource::VSyncData vsyncData) {
    2. std::lock_guard<std::mutex> lock(mMutex);
    3. LOG_FATAL_IF(!mVSyncState);
    4. mPendingEvents.push_back(makeVSync(mVSyncState->displayId, timestamp, ++mVSyncState->count,
    5. vsyncData.expectedPresentationTime,
    6. vsyncData.deadlineTimestamp));
    7. mCondition.notify_all();
    8. }

    这里我们看到,会生成一个VSync信号,加入到mPendingEvents集合中,并且发出通知,让threadMain去获取,从而完成了VSync信号的生产者流程。

    画了如下的surfaceFlinger结构图,方便理解(非完整版):

    五.APP层收到信号进行刷新

    本章讲的主要流程如下图红圈所示:

     

    5.1 APP端接受流程

    3.3小节中讲到,SurfaceFlinger会通过BitTube的方式传递给APP侧Vsync信号。发送vscyn信号的方法在DisplayEventReceiver.cpp中,而接收方法也在这个类当中。而具体调用方则是DisplayEventDispatcher.cpp中的dispatchVsync方法。流程如下图所示:

    5.2 dispathVsync分发流程

    上面在handleEvent中,processPendingEvents获取到了Vsync信号VsyncEventData后,交给dispatchVsync方法负责处理。

       dispatchVsync(vsyncTimestamp, vsyncDisplayId, vsyncCount, vsyncEventData);

    dispatchVsync方法的实现者是android_view_DisplayEventReceiver.cpp,如下:

    1. void NativeDisplayEventReceiver::dispatchVsync(nsecs_t timestamp, PhysicalDisplayId displayId,
    2. uint32_t count, VsyncEventData vsyncEventData) {
    3. JNIEnv* env = AndroidRuntime::getJNIEnv();
    4. ...
    5. jobject javaVsyncEventData = createJavaVsyncEventData(env, vsyncEventData);
    6. env->CallVoidMethod(receiverObj.get(), gDisplayEventReceiverClassInfo.dispatchVsync,
    7. timestamp, displayId.value, count, javaVsyncEventData);
    8. ...
    9. }

    我们可以看到,先是把VsyncEventData转换为java可以接受的jobject对象,然后通过CallVoidMethod方法通知到java层中DisplayEventReceiver.java中的dispatchVsync方法。

    5.3 java中流程流转

    首先DisplayEventReceiver中dispatchVsync方法被调用:

    1. // Called from native code.
    2. @SuppressWarnings("unused")
    3. private void dispatchVsync(long timestampNanos, long physicalDisplayId, int frame,
    4. VsyncEventData vsyncEventData) {
    5. onVsync(timestampNanos, physicalDisplayId, frame, vsyncEventData);
    6. }

    该方法中直接调用onVsync方法,调用到Choreographer.java中FrameDisplayEventReceiver下的onVsync方法:

    1. @Override
    2. public void onVsync(long timestampNanos, long physicalDisplayId, int frame,
    3. VsyncEventData vsyncEventData) {
    4. try {
    5. ...
    6. if (timestampNanos > now) {
    7. timestampNanos = now;
    8. }
    9. if (mHavePendingVsync) {
    10. } else {
    11. mHavePendingVsync = true;
    12. }
    13. mTimestampNanos = timestampNanos;
    14. mFrame = frame;
    15. mLastVsyncEventData = vsyncEventData;
    16. Message msg = Message.obtain(mHandler, this);
    17. msg.setAsynchronous(true);
    18. mHandler.sendMessageAtTime(msg, timestampNanos / TimeUtils.NANOS_PER_MS);
    19. } finally {
    20. Trace.traceEnd(Trace.TRACE_TAG_VIEW);
    21. }
    22. }

    onVsync方法中,主要判断时间。如果timestampNanos>now,则是用当前时间。所以还是以方法的调用时间为准。然后通过handle转发到主线程中执行。

    Message.obj=this,本身FrameDisplayEventReceiver又实现了Runnable接口,所以自然会执行FrameDisplayEventReceiver下的run方法:

    1. @Override
    2. public void run() {
    3. mHavePendingVsync = false;
    4. doFrame(mTimestampNanos, mFrame, mLastVsyncEventData);
    5. }

    这时候我们就看到,执行到了doFrame方法,而这个方法也是就是渲染流程的执行者。

    5.4 如何触发handleEvent流程?

    讲到这里,你或许有个疑问,上面流程中,如何执行到5.1中的handleEvent方法的呢?

    主要是下图所示的流程:

     

    如果你断点调试的时候,会发现下面所示的这个方法,竟然是主线程调用的:

    1. DisplayEventReceiver.java
    2. // Called from native code.
    3. @SuppressWarnings("unused")
    4. private void dispatchVsync(long timestampNanos, long physicalDisplayId, int frame,
    5. long frameTimelineVsyncId, long frameDeadline, long frameInterval) {
    6. onVsync(timestampNanos, physicalDisplayId, frame,
    7. new VsyncEventData(frameTimelineVsyncId, frameDeadline, frameInterval));
    8. }

    为什么用竟然呢?因为一般来看,应该是子线程等待接受SurfaceFlinger的信号,收到了信号后交给主线程处理,如果是主线程去等待,岂不是主线程阻塞了?

    这里使用looper.addFd()方法,在该方法中,用到了一个epoll_ctl的机制,即对FD文件进行监听,当FD改变时触发主线程的回调。如果处理完回调任务,则会进入epoll_wait的阻塞,继续监听。

    六.扩展问题

    问:高频次请求vsync信号,会突破60FPS的限制吗?

    答:不会。

    首先ViewRootImpl中做了一层处理,哪怕16ms改变了很多View的布局,最终执行到了scheduleTraversals方法时,因为有如下的判断,所以都只会执行一次vsync信号的请求和注册一次回调,直至收到VSYNC信号。

    1. void scheduleTraversals() {
    2. if (!mTraversalScheduled) {
    3. mTraversalScheduled = true;
    4. mTraversalBarrier = mHandler.getLooper().getQueue().postSyncBarrier();
    5. mChoreographer.postCallback(
    6. Choreographer.CALLBACK_TRAVERSAL, mTraversalRunnable, null);
    7. }
    8. }

    取消限制:

    1. void doTraversal() {
    2. if (mTraversalScheduled) {
    3. mTraversalScheduled = false;
    4. }

    其次,2.2小节中讲到,native请求VSYNC信号时也有一次限制,等到VSYNC信号时是不会再次发送请求的。

    1. status_t DisplayEventDispatcher::scheduleVsync() {
    2. if (!mWaitingForVsync) {
    3. ...
    4. status_t status = mReceiver.requestNextVsync();
    5. ...
    6. mWaitingForVsync = true;
    7. ...
    8. }
    9. return OK;
    10. }

    七.参考资料

    https://www.jianshu.com/p/6083c590521b

    https://www.jianshu.com/p/386bbb5fa29a //努比亚技术团队文章

    八.声明

    1.本文是原创,根据网上资料和阅读ASOP的源码之后得出的结论,如有问题,欢迎指出。

    2.图中涉及到的流程图如果想要高清大图或者pos格式的原图,可以私信我。

  • 相关阅读:
    日更【系统架构设计师知识总结2】指令系统(结合真题)
    制作rootfs镜像,通过fastboot烧录到x210开发板中验证
    经济型EtherCAT运动控制器(十):EtherCAT总线快速入门
    4-k8s-部署springboot项目简单实践
    正则表达式快速入门笔记
    谣言检测(PSIN)——《Divide-and-Conquer: Post-User Interaction Network for Fake News Detection on Social Media》
    RabbitMQ传统数据持久化和Lazy queue的区别
    见微知著,从两道有意思的 CSS 面试题,考察你的基础
    不可不知 | 一份来自官方的量化参赛指南
    后端面试很难吗 夺命10连问你能抗的住吗?
  • 原文地址:https://blog.csdn.net/AA5279AA/article/details/126118441