App/Sf的Vsync部分源碼流程結(jié)合perfetto/systrace分析

hi,粉絲朋友們:
本節(jié)將使用perfetto的trace來鞏固Vsync的源碼分析的部分的流程。
具體抓取trace方法及相關(guān)操作建議:
a.抓取trace期間需要主要不能讓畫面一直刷新,因?yàn)檫@樣一直刷新不方便看vsync的結(jié)束和開始
b.建議選著桌面,滑動(dòng)桌面一下后停止1左右,再繼續(xù)滑動(dòng),盡量讓抓取的trace可以有如下圖的間隔效果
c.需要在surfaceflinger中額外補(bǔ)充自己加的一些ATRACE代碼方便追蹤流程


1.png

1、app請求Vsync部分

這里我們回憶一下app的Vsync的申請,一般都是app主動(dòng)申請的,一般都是應(yīng)用端
Choreographer#scheduleVsyncLocked方法跨進(jìn)程調(diào)用到Surfaceflinger端的requestNextVsync方法,具體trace如下圖

2.png

surfaceflinger作為服務(wù)端如下:


3.png

所有的Vsync邏輯其實(shí)就是從SurfaceFlinger的requestNextVsync方法開始的:

binder::Status EventThreadConnection::requestNextVsync() {
    ATRACE_CALL();
    //這里加個(gè)ATRACE標(biāo)準(zhǔn)方便確定是app申請還是appSf申請的Vsync
    ATRACE_BEGIN(((impl::EventThread*)mEventThread)->toNameString());
    mEventThread->requestNextVsync(this);
    ATRACE_END();
    return binder::Status::ok();
}

調(diào)用到了 mEventThread->requestNextVsync(this);
代碼如下

void EventThread::requestNextVsync(const sp<EventThreadConnection>& connection) {
    ATRACE_NAME("EventThread::requestNextVsync");
    if (connection->resyncCallback) {
        connection->resyncCallback();
    }

    std::lock_guard<std::mutex> lock(mMutex);

    if (connection->vsyncRequest == VSyncRequest::None) { //如果這個(gè)是第一次申請進(jìn)入一般這里就是None
        connection->vsyncRequest = VSyncRequest::Single;
        ATRACE_NAME("connection->vsyncRequest None  notify_all");
        mCondition.notify_all();//第一次則會(huì)通過mCondition喚醒等待
    } else if (connection->vsyncRequest == VSyncRequest::SingleSuppressCallback) { //這里代表前一次剛剛已經(jīng)進(jìn)入vsync,準(zhǔn)備進(jìn)入停止回調(diào)狀態(tài)
        ATRACE_NAME("connection->vsyncRequest SingleSuppressCallback ");
        connection->vsyncRequest = VSyncRequest::Single; //這里不需要喚醒,代表thread運(yùn)行等待vsync,需要靠vsync時(shí)間到了才喚醒
    }
}

這里都會(huì)吧vsyncRequest變變成Single,最重要mCondition.notify_all()會(huì)喚醒一直等待的EventThread的線程,讓他繼續(xù)執(zhí)行:
這里喚醒也可以通過perfetto看出來:


4.png

對于的代碼:


void EventThread::threadMain(std::unique_lock<std::mutex>& lock) {
    DisplayEventConsumers consumers;

    while (mState != State::Quit) {
    
         if (!mPendingEvents.empty()) {//檢測是否有mPendingEvent,遍歷各個(gè)Event,
            event = mPendingEvents.front();
            mPendingEvents.pop_front();

            switch (event->header.type) {
                case DisplayEventReceiver::DISPLAY_EVENT_HOTPLUG:
                    if (event->hotplug.connected && !mVSyncState) {
                        mVSyncState.emplace(event->header.displayId);
                    } else if (!event->hotplug.connected && mVSyncState &&
                               mVSyncState->displayId == event->header.displayId) {
                        mVSyncState.reset();
                    }
                    break;

                case DisplayEventReceiver::DISPLAY_EVENT_VSYNC:
                    if (mInterceptVSyncsCallback) {
                        mInterceptVSyncsCallback(event->header.timestamp);
                    }
                    break;
            }
        }
        

        bool vsyncRequested = false;//初始化為false

        // Find connections that should consume this event.
        auto it = mDisplayEventConnections.begin();
        while (it != mDisplayEventConnections.end()) {//遍歷一下所有的connection,和EventTread綁定的app鏈接
            if (const auto connection = it->promote()) {
                vsyncRequested |= connection->vsyncRequest != VSyncRequest::None;//這里會(huì)檢測一下是前面設(shè)置過的request是不是還是None,明顯前面設(shè)置成了Single

                if (event && shouldConsumeEvent(*event, connection)) {//這里會(huì)判斷當(dāng)前event是否要讓這個(gè)connection消費(fèi)
                    consumers.push_back(connection);
                    ATRACE_FORMAT("shouldConsumeEvent consumers push %s",toString(*connection).c_str());
                }

                ++it;
            } else {
                it = mDisplayEventConnections.erase(it);
            }
        }

        if (!consumers.empty()) {//進(jìn)行相關(guān)的事件派發(fā)
            dispatchEvent(*event, consumers);
            consumers.clear();
        }
        ATRACE_FORMAT("vsyncRequested = %d",vsyncRequested);
        State nextState;
        //設(shè)置下一個(gè)nextstate,這里注意nextstate很關(guān)鍵,如果沒有vsyncRequested,那么就nextstate就一定為Idle
        if (mVSyncState && vsyncRequested) {
            nextState = mVSyncState->synthetic ? State::SyntheticVSync : State::VSync;
        } else {
            ALOGW_IF(!mVSyncState, "Ignoring VSYNC request while display is disconnected");
            nextState = State::Idle;
        }
        //nextState和當(dāng)前state進(jìn)行比較不相等進(jìn)入
        if (mState != nextState) {
            if (mState == State::VSync) {//如果當(dāng)前是vsync,那么nextState不是Vsync了說明vsync要停止
                ATRACE_NAME("mVSyncSource->setVSyncEnabled(false)");
                mVSyncSource->setVSyncEnabled(false);
            } else if (nextState == State::VSync) {//mState當(dāng)前不是Vsync,下一個(gè)state是Vsync,就會(huì)進(jìn)入以下關(guān)鍵方法
                ATRACE_NAME("mVSyncSource->setVSyncEnabled(true)");
                mVSyncSource->setVSyncEnabled(true);//調(diào)用啟動(dòng)vsync相關(guān)
            }
            //上面操作完成就代表狀態(tài)已經(jīng)切換
            mState = nextState;
        }

        if (event) {//如果有event不會(huì)進(jìn)入下面的wait而是會(huì)繼續(xù)從頭開始執(zhí)行
            continue;
        }

        // Wait for event or client registration/request.
        if (mState == State::Idle) {
            mCondition.wait(lock);//開始長時(shí)間沒有vsync申請,就在這等待,第一次app申請時(shí)候就會(huì)喚醒這里
        } else {
                 // Generate a fake VSYNC after a long timeout in case the driver stalls. When the
            // display is off, keep feeding clients at 60 Hz.
            const std::chrono::nanoseconds timeout =
                    mState == State::SyntheticVSync ? 16ms : 1000ms;
                    //進(jìn)行超時(shí)等待
            if (mCondition.wait_for(lock, timeout) == std::cv_status::timeout) {
             //省略
            }
        }

    }
}

EventThread的執(zhí)行情況如下:


5.png

這里發(fā)現(xiàn)主要業(yè)務(wù)在 mVSyncSource->setVSyncEnabled(true)代碼中,這里面開啟了一系列的vsync計(jì)算和定時(shí)任務(wù)

大概上面可以看出調(diào)用棧如下:
VSyncSource->setVSyncEnabled(true)
----》 VSyncDispatchTimerQueue::schedule
----------》rearmTimerSkippingUpdateFor
--------------》setTimer
這樣就完成了設(shè)置定時(shí)觸發(fā)操作,具體這里不進(jìn)行詳細(xì)講述定時(shí)這部分,因?yàn)檩^為復(fù)雜需要單獨(dú)章節(jié),這里大家只要知道最后獲取了自己app的vsync觸發(fā)時(shí)間targetTime,定時(shí)器設(shè)置了到時(shí)間就觸發(fā),回調(diào)相關(guān)的timeCallback方法。
到此就EventThread就執(zhí)行到了等待定時(shí)等待狀態(tài),等待定時(shí)時(shí)間的到來。

2、Vsync時(shí)間到了后觸發(fā)timeCallback

上面步驟的定時(shí)器觸發(fā)后,回調(diào)執(zhí)行是在單獨(dú)的TimerDispatch線程,具體trace的體現(xiàn)如下:


7.png

來看看timeCallback里面又干啥了,代碼如下:

void VSyncDispatchTimerQueue::timerCallback() {
    ATRACE_CALL();
   
    std::vector<Invocation> invocations;
    {
      //遍歷3個(gè)vsync,app,sf,appSf
        for (auto it = mCallbacks.begin(); it != mCallbacks.end(); it++) {
            auto& callback = it->second;
            auto const wakeupTime = callback->wakeupTime();
            if (!wakeupTime) {//如果沒有wakupTime直接下一個(gè),因?yàn)閴焊鶝]有vsync的任何申請蹤跡
                continue;
            }

            auto const readyTime = callback->readyTime();
            auto const lagAllowance = std::max(now - mIntendedWakeupTime, static_cast<nsecs_t>(0));
            //判斷的wakeupTime是不是比(mIntendedWakeupTime + mTimerSlack + lagAllowance)小,正常第一app請求肯定會(huì)進(jìn)入這里
            if (*wakeupTime < mIntendedWakeupTime + mTimerSlack + lagAllowance) {
                callback->executing();
                invocations.emplace_back(Invocation{callback, *callback->lastExecutedVsyncTarget(),
                                                    *wakeupTime, *readyTime});
            }
        }

        mIntendedWakeupTime = kInvalidTime;//設(shè)置一個(gè)無窮大的值
        rearmTimer(mTimeKeeper->now());//重新準(zhǔn)備設(shè)置定時(shí)器
    }

    for (auto const& invocation : invocations) {//開始回調(diào)上面獲取的callback
        invocation.callback->callback(invocation.vsyncTimestamp, invocation.wakeupTimestamp,
                                      invocation.deadlineTimestamp);
    }
}
8.png

主要干的幾件事如下:

1、遍歷3個(gè)類型vsync看看誰是有定時(shí)任務(wù)的,比較wakeupTime和intentedTime符合回調(diào)情況
2、符合回調(diào)情況的,會(huì)調(diào)用executing清除定時(shí)器,和wakeupTime,并吧intentedTime設(shè)置成很大數(shù)字
3、繼續(xù)下一個(gè)rearmTimer定時(shí)任務(wù)
4、回調(diào)相關(guān)類型vsync,vsync到來

上面四個(gè)任務(wù)就是TimeDispatch完成的。
這里要注意一下mCallbacks這個(gè)變量哪來的,是怎么對應(yīng)剛好就是app,appSf,sf,3個(gè)vsync的呢?
mCallbacks都是通過這個(gè)方法register來注冊的:

VSyncDispatchTimerQueue::CallbackToken VSyncDispatchTimerQueue::registerCallback(
        Callback callback, std::string callbackName) {
    std::lock_guard lock(mMutex);
    return CallbackToken{
            mCallbacks
                    .emplace(++mCallbackToken,//這里構(gòu)造出來了VSyncDispatchTimerQueueEntry的實(shí)體
                             std::make_shared<VSyncDispatchTimerQueueEntry>(std::move(callbackName),
                                                                            std::move(callback),
                                                                            mMinVsyncDistance))
                    .first->first};
}

那么什么地方調(diào)用注冊呢?實(shí)在構(gòu)造VSyncCallbackRegistration時(shí)候

VSyncCallbackRegistration::VSyncCallbackRegistration(VSyncDispatch& dispatch,
                                                     VSyncDispatch::Callback callback,
                                                     std::string callbackName)
      : mDispatch(dispatch),
      //給mToken賦值時(shí)候,直接調(diào)用的注冊callback返回的token
        mToken(dispatch.registerCallback(std::move(callback), std::move(callbackName))),
        mValidToken(true) {}

那么這個(gè)VSyncCallbackRegistration是在什么時(shí)候構(gòu)造的呢?

對于sf是在MessageQueue中進(jìn)行的:

void MessageQueue::initVsync(scheduler::VSyncDispatch& dispatch,
                             frametimeline::TokenManager& tokenManager,
                             std::chrono::nanoseconds workDuration) {
    setDuration(workDuration);
    mVsync.tokenManager = &tokenManager;
    //構(gòu)造VSyncCallbackRegistration
    mVsync.registration = std::make_unique<
            scheduler::VSyncCallbackRegistration>(dispatch,
                                                  std::bind(&MessageQueue::vsyncCallback, this,
                                                            std::placeholders::_1,
                                                            std::placeholders::_2,
                                                            std::placeholders::_3),
                                                  "sf");
}

對于EventThread如下代碼進(jìn)行的:

  CallbackRepeater(VSyncDispatch& dispatch, VSyncDispatch::Callback cb, const char* name,
                     std::chrono::nanoseconds workDuration, std::chrono::nanoseconds readyDuration,
                     std::chrono::nanoseconds notBefore)
          : mName(name),
            mCallback(cb),
            //構(gòu)造VSyncCallbackRegistration
            mRegistration(dispatch,
                          std::bind(&CallbackRepeater::callback, this, std::placeholders::_1,
                                    std::placeholders::_2, std::placeholders::_3),
                          mName),
            mStarted(false),
            mWorkDuration(workDuration),
            mReadyDuration(readyDuration),
            mLastCallTime(notBefore) {}

那么上面就知曉各自的callback在哪里了。

接下來這里重點(diǎn)關(guān)注一下回調(diào)vsync部分的任務(wù),app類型的vsync回調(diào)任務(wù)代碼如下:
frameworks/native/services/surfaceflinger/Scheduler/DispSyncSource.cpp的CallbackRepeater的callback方法:

  void callback(nsecs_t vsyncTime, nsecs_t wakeupTime, nsecs_t readyTime) {
        ATRACE_CALL();
        //調(diào)用mCallback方法,其實(shí)就是DispSyncSource::onVsyncCallback
        mCallback(vsyncTime, wakeupTime, readyTime);

        {
            std::lock_guard lock(mMutex);
            if (!mStarted) {//注意一下這個(gè)值哈,和前面的EventThread的中有停止Vsync有關(guān)系
                ATRACE_NAME("callback return not  mRegistration.schedule");
                return;
            }
            auto const scheduleResult =
                    mRegistration.schedule({.workDuration = mWorkDuration.count(),
                                            .readyDuration = mReadyDuration.count(),
                                            .earliestVsync = vsyncTime});
            LOG_ALWAYS_FATAL_IF(!scheduleResult.has_value(), "Error rescheduling callback");
        }
    }


這里的mCallback在哪里賦值的呢?

DispSyncSource::DispSyncSource(VSyncDispatch& vSyncDispatch, VSyncTracker& vSyncTracker,
                               std::chrono::nanoseconds workDuration,
                               std::chrono::nanoseconds readyDuration, bool traceVsync,
                               const char* name)
      : mName(name),
        mValue(base::StringPrintf("VSYNC-%s", name), 0),
        mTraceVsync(traceVsync),
        mVsyncOnLabel(base::StringPrintf("VsyncOn-%s", name)),
        mVSyncTracker(vSyncTracker),
        mWorkDuration(base::StringPrintf("VsyncWorkDuration-%s", name), workDuration),
        mReadyDuration(readyDuration) {
        //這里進(jìn)行了關(guān)鍵的DispSyncSource::onVsyncCallback傳遞到CallbackRepeater對象
    mCallbackRepeater =
            std::make_unique<CallbackRepeater>(vSyncDispatch,
                                               std::bind(&DispSyncSource::onVsyncCallback, this,
                                                         std::placeholders::_1,
                                                         std::placeholders::_2,
                                                         std::placeholders::_3),
                                               name, workDuration, readyDuration,
                                               std::chrono::steady_clock::now().time_since_epoch());
}

//這里的第二個(gè)參數(shù)就是VSyncDispatch::Callback
    CallbackRepeater(VSyncDispatch& dispatch, VSyncDispatch::Callback cb, const char* name,
                     std::chrono::nanoseconds workDuration, std::chrono::nanoseconds readyDuration,
                     std::chrono::nanoseconds notBefore)
          : mName(name),
            mCallback(cb),
            mRegistration(dispatch,
                          std::bind(&CallbackRepeater::callback, this, std::placeholders::_1,
                                    std::placeholders::_2, std::placeholders::_3),
                          mName),
            mStarted(false),
            mWorkDuration(workDuration),
            mReadyDuration(readyDuration),
            mLastCallTime(notBefore) {}

重點(diǎn)看看 DispSyncSource::onVsyncCallback方法:

void DispSyncSource::onVsyncCallback(nsecs_t vsyncTime, nsecs_t targetWakeupTime,
                                     nsecs_t readyTime) {
    ATRACE_CALL();
    VSyncSource::Callback* callback;
    {
        std::lock_guard lock(mCallbackMutex);
        callback = mCallback;
    }
    if (mTraceVsync) {
        mValue = (mValue + 1) % 2; //這里就是前面講解的vsync的方波圖展示部分靠這里
    }

    if (callback != nullptr) {//這里關(guān)鍵一步會(huì)調(diào)用到EventTread中
        callback->onVSyncEvent(targetWakeupTime, {vsyncTime, readyTime});
    }
}


void EventThread::onVSyncEvent(nsecs_t timestamp, VSyncSource::VSyncData vsyncData) {
    std::lock_guard<std::mutex> lock(mMutex);
    //注意這里進(jìn)行了PendingEvents的插入
    mPendingEvents.push_back(makeVSync(mVSyncState->displayId, timestamp, ++mVSyncState->count,
                                       vsyncData.expectedPresentationTime,
                                       vsyncData.deadlineTimestamp));
    mCondition.notify_all();//進(jìn)行線程喚醒,又切換回了EventThread工作了
}

9.png

但是這里喚醒App的EventThread后trace中沒看到具體干啥活,因?yàn)槲覀儧]有加相關(guān)ATRACE,加上一下相關(guān)TRACE如下:


10.png

明顯看到這里其實(shí)就是開始派發(fā)Vsync相關(guān)的Event到app端。

callback這里除了onVsyncCallback之外,下一步就是執(zhí)行新的一次schedule進(jìn)行相關(guān)的定時(shí)觸發(fā)Vsync任務(wù)。
代碼就是上面callback方法的

  auto const scheduleResult =
                    mRegistration.schedule({.workDuration = mWorkDuration.count(),
                                            .readyDuration = mReadyDuration.count(),
                                            .earliestVsync = vsyncTime});

這里面又回到最開的是設(shè)置定時(shí)器任務(wù)了,啟動(dòng)下一個(gè)vsync的定時(shí),這里其實(shí)就可以知道,也就是app發(fā)起第一次的vsync請求,一般都會(huì)有兩個(gè)vsync定時(shí)任務(wù)哈。

3、app的vsync繼續(xù)請求和sf的vsync申請

針對上面分析的已經(jīng)知道了第一次的app請求vsync情況,但是一般app都是會(huì)很多次的vsync連續(xù)請求,因?yàn)楸容^少見就一次刷新情況。那么看看產(chǎn)生連續(xù)的vsync請求會(huì)是什么樣。

11.png

明顯看到第二次的requestVsync就和 第一次不一樣了,這個(gè)時(shí)候的并沒有喚醒a(bǔ)pp的EventThread線程。因?yàn)榍懊娲a就說了這個(gè)情況

void EventThread::requestNextVsync(const sp<EventThreadConnection>& connection) {
  
    if (connection->vsyncRequest == VSyncRequest::None) { //如果這個(gè)是第一次申請進(jìn)入一般這里就是None
        connection->vsyncRequest = VSyncRequest::Single;
        ATRACE_NAME("connection->vsyncRequest None  notify_all");
        mCondition.notify_all();//第一次則會(huì)通過mCondition喚醒等待
    } else if (connection->vsyncRequest == VSyncRequest::SingleSuppressCallback) { //這里代表前一次剛剛已經(jīng)進(jìn)入vsync,準(zhǔn)備進(jìn)入停止回調(diào)狀態(tài)
        ATRACE_NAME("connection->vsyncRequest SingleSuppressCallback ");
        connection->vsyncRequest = VSyncRequest::Single; //這里不需要喚醒,代表thread運(yùn)行等待vsync,需要靠vsync時(shí)間到了才喚醒
    }
}

也就是一旦Vsync的定時(shí)器啟動(dòng)后,EventThread的線程就會(huì)阻塞,知道定時(shí)器時(shí)間到了才會(huì)繼續(xù)執(zhí)行,后面的app的requestVsync根本不會(huì)喚醒。

那么他的喚醒靠誰呢?當(dāng)然是靠第一次timeCallback時(shí)候的定時(shí)器觸發(fā)啦

12.png

那么app的vsync就是這樣循環(huán)只要不斷有app的requestVsync,那么SurfaceFlinger的Vsync呢?

首先我們得知道sf的vsync也是由app層面進(jìn)行queuebuffer后,通過跨進(jìn)程setTransactionState方法調(diào)用到SurfaceFlinger端,SurfaceFlinger端會(huì)檢測transation是否有相關(guān)的變化,有變化則觸發(fā)申請vsync信號:

void SurfaceFlinger::setTransactionFlags(uint32_t mask, TransactionSchedule schedule,
                                         const sp<IBinder>& applyToken, FrameHint frameHint) {
    ATRACE_CALL();
    modulateVsync(&VsyncModulator::setTransactionSchedule, schedule, applyToken);
    std::atomic<int32_t> tmp =  getTransactionFlags();
    if (const bool scheduled = mTransactionFlags.fetch_or(mask) & mask; !scheduled) {
        ATRACE_BEGIN("scheduleCommit");
        scheduleCommit(frameHint);//申請vsync
        ATRACE_END();
    }
}

void SurfaceFlinger::scheduleCommit(FrameHint hint) {
   //省略部分
    mScheduler->scheduleFrame();
}

void MessageQueue::scheduleFrame() {
  //調(diào)用到了registration->schedule
    mVsync.scheduledFrameTime =
            mVsync.registration->schedule({.workDuration = mVsync.workDuration.get().count(),
                                           .readyDuration = 0,
                                           .earliestVsync = mVsync.lastCallbackTime.count()});
}
//下面是VSyncCallbackRegistration的schedule
ScheduleResult VSyncCallbackRegistration::schedule(VSyncDispatch::ScheduleTiming scheduleTiming) {
    if (!mValidToken) {
        return std::nullopt;
    }
    return mDispatch.get().schedule(mToken, scheduleTiming);
}

上面的調(diào)用關(guān)系都很簡單,沒啥業(yè)務(wù),直到調(diào)用到了dispatch的schedule才是核心

ScheduleResult VSyncDispatchTimerQueue::schedule(CallbackToken token,
                                                 ScheduleTiming scheduleTiming) {
    ScheduleResult result;
    {
       //這里又會(huì)調(diào)用到callback的schedule,其實(shí)就另一個(gè)重載方法,這里會(huì)獲取出具體的wakeupTime等,是核心部分
        result = callback->schedule(scheduleTiming, mTracker, now);
        //這里會(huì)判斷上面計(jì)算的wakeupTime是否小于mIntendedWakeupTime,小于才需要重新定時(shí),如果大于就不需要了,直接return
        if (callback->wakeupTime() < mIntendedWakeupTime - mTimerSlack) {
            rearmTimerSkippingUpdateFor(now, it);//啟動(dòng)定時(shí)任務(wù)相關(guān)
        }
    }

    return result;
}

來看看核心方法callback->schedule是怎么計(jì)算的這個(gè)wakeup等重要參數(shù)的:


ScheduleResult VSyncDispatchTimerQueueEntry::schedule(VSyncDispatch::ScheduleTiming timing,
                                                      VSyncTracker& tracker, nsecs_t now) {
    //核心方法,給一個(gè)時(shí)間點(diǎn),然后可以獲取到這個(gè)時(shí)間點(diǎn)對于的硬件vsync,即上屏的vsync時(shí)間點(diǎn)就是nextVsyncTime
    auto nextVsyncTime = tracker.nextAnticipatedVSyncTimeFrom(
            std::max(timing.earliestVsync, now + timing.workDuration + timing.readyDuration));
    //通過nextVsyncTime來獲取喚醒時(shí)間部分
    auto nextWakeupTime = nextVsyncTime - timing.workDuration - timing.readyDuration;
      //省略
    //上面計(jì)算出來的時(shí)間,然后包裝到mArmedInfo中
    mArmedInfo = {nextWakeupTime, nextVsyncTime, nextReadyTime};
    //返回時(shí)間點(diǎn)
    return getExpectedCallbackTime(nextVsyncTime, timing);
}
//其實(shí)是返回wakeuptime
nsecs_t getExpectedCallbackTime(nsecs_t nextVsyncTime,
                                const VSyncDispatch::ScheduleTiming& timing) {
    return nextVsyncTime - timing.readyDuration - timing.workDuration;
}

核心方法是nextAnticipatedVSyncTimeFrom,這個(gè)方法很復(fù)雜,大家先把他當(dāng)做個(gè)功能黑盒,后面會(huì)帶大家詳細(xì)分析。

所以Sf接收到跨進(jìn)程transaction的請求后申請vsync,計(jì)算出來的vsync時(shí)間,從而得出wakeupTime,一般這里的wakeupTime會(huì)大于前面app Vsync時(shí)候定時(shí)的wakeupTime,所以這里不會(huì)進(jìn)行任何的定時(shí)。
結(jié)合trace看看vsync的情況:
sf的vsync申請觸發(fā)部分情況:


13.png

和app vsync一起合作的解釋部分:


14.png

這里展開一下app ,sf都被回調(diào)的trace,對應(yīng)的代碼就是上面的timeCallback方法:

15.png

4、app vsync結(jié)束部分

vsync有申請就肯定有結(jié)束,不可能app沒有申請情況下,vsync還一直不斷的運(yùn)行,這樣對于系統(tǒng)的功耗影響巨大,而且也是無用功,所以vsync堅(jiān)持的原則就是有需要用時(shí)候app主動(dòng)申請,不需要了就停止。
上面只分析了vsync怎么開始的,接下來分析vsync的結(jié)束部分邏輯

16.png

邏輯是如下情況:
時(shí)間到了timeCallback
-----》在onVsyncCallback里面會(huì)喚醒EventThread
-------》EventThread運(yùn)行,但是因?yàn)闆]有app進(jìn)行requestVsync了,所以vsyncRequest = 0
-----》EventThread繼續(xù)執(zhí)行時(shí)候發(fā)現(xiàn)沒有vsyncRequest,故需要調(diào)用setVsyncEnbale(false)關(guān)閉定時(shí)
關(guān)閉定時(shí)器步驟trace:


17.png

該部分對應(yīng)核心代碼回顧:
app的EventThread執(zhí)行時(shí)候,會(huì)把vsyncRequest變成0,代表沒有app的vsync請求了

void EventThread::threadMain(std::unique_lock<std::mutex>& lock) {
    DisplayEventConsumers consumers;

    while (mState != State::Quit) {
        std::optional<DisplayEventReceiver::Event> event;
        ATRACE_FORMAT("threadMain");


        bool vsyncRequested = false;

        // Find connections that should consume this event.
        auto it = mDisplayEventConnections.begin();
        while (it != mDisplayEventConnections.end()) {
            if (const auto connection = it->promote()) {
            //這里會(huì)進(jìn)行遍歷connection,有vsync那么就為true,沒有就是false
                vsyncRequested |= connection->vsyncRequest != VSyncRequest::None;
                //注意這里會(huì)對每個(gè)connection的vsyncRequest進(jìn)行改變,注意這里的需要event不為null
                if (event && shouldConsumeEvent(*event, connection)) {
                    consumers.push_back(connection);

                }

                ++it;
            } else {
                it = mDisplayEventConnections.erase(it);
            }
        }
        }

//這個(gè)方法里面會(huì)改變每個(gè)connection的vsyncRequest
bool EventThread::shouldConsumeEvent(const DisplayEventReceiver::Event& event,
                                     const sp<EventThreadConnection>& connection) const {
    switch (event.header.type) {


        case DisplayEventReceiver::DISPLAY_EVENT_MODE_CHANGE: {
            return connection->mEventRegistration.test(
                    ISurfaceComposer::EventRegistration::modeChanged);
        }

        case DisplayEventReceiver::DISPLAY_EVENT_VSYNC:
            switch (connection->vsyncRequest) {
                case VSyncRequest::None:
                    return false;
                    //第一次SingleSuppressCallback后,就改成None
                case VSyncRequest::SingleSuppressCallback:
                    connection->vsyncRequest = VSyncRequest::None;
                    return false;
                case VSyncRequest::Single: {
                    if (throttleVsync()) {
                        return false;
                    }
                    //第一次Single后,就改成SingleSuppressCallback
                    connection->vsyncRequest = VSyncRequest::SingleSuppressCallback;
                    return true;
                }
                case VSyncRequest::Periodic:
                    if (throttleVsync()) {
                        return false;
                    }
                    return true;
                default:
                    return event.vsync.count % vsyncPeriod(connection->vsyncRequest) == 0;
            }

    }
}

總結(jié)如下:
1、EventThread最核心的vsyncRequest是app進(jìn)行requestVsync進(jìn)行改變成Single
2、vsync定時(shí)時(shí)間到會(huì)回調(diào)觸發(fā)EventThread加入個(gè)event,event就是來派發(fā)Vsync事件給具體的connection即app,通過socket方式
3、消費(fèi)了event同時(shí),需要吧前面app設(shè)置的vsyncRequest變成SingleSuppressCallback
4、下次如果vsync再次觸發(fā),但是沒見到新的app吧vsyncRequest變成Single,如果還是上次的SingleSuppressCallback,那么vsyncRequest就變成了None,變成None之后就會(huì)調(diào)用 mVSyncSource->setVSyncEnabled(false)關(guān)閉vsync

本文章對應(yīng)視頻手把手教你學(xué)framework:
hal+perfetto+surfaceflinger
https://mp.weixin.qq.com/s/LbVLnu1udqExHVKxd74ILg

18.png

私聊作者+v(androidframework007)

七件套專題:


6.png

點(diǎn)擊這里 https://mp.weixin.qq.com/s/Qv8zjgQ0CkalKmvi8tMGaw

視頻:https://www.bilibili.com/video/BV1wc41117L4/

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡書系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容