AndroidQ SurfaceFlinger進程對Vsync的接收與分發(上)

前面兩篇文章分析了應用層對Vsync的註冊與接收,收到Vsync之後應用層便開始View的繪製

我們先來回顧一下大致的流程:

  1. 首先應用層想要繪製UI,則需要向native層註冊接收下一個到來的Vsync,註冊的過程是通過EventThreadConnection的Bp端最終調用到SurfaceFlinger進程的EventThread的requestNextVsync函數
  2. EventThread是用來專門處理各種事件的,除了Vsync,還有Hotplug和ConfigChanged,EventThread有兩個,一個名字叫”app“,一個名字叫”sf“
  3. EventThreadConnection代表應用層到SurfaceFlinger進程的連接,每一個上層的ViewRootImpl都對應一個EventThreadConnection,因爲每個View視圖都需要Vsync來開啓繪製工作
  4. EventThread並不是一個線程,它的內部有一個線程,這個線程就是用來處理底層Vsync的接收以及分發的,這個線程是一個死循環,當它沒收到事件請求時會通過C++條件變量調用wait陷入等待狀態
  5. 應用層請求Vsync的過程其實就是通過這個條件變量調用notify喚醒EventThread內部這個線程,然後從mPendingEvents中獲取到Vsync信息分發給感興趣的進程

我們前兩篇文章大概就分析了這些,本篇文章就來探究mPendingEvents中的Vsync是哪來的,以及EventThread內部這個線程的工作原理

EventThread的創建是在SurfaceFlinger的init函數中

void SurfaceFlinger::init() {
	......
	    // start the EventThread
    mScheduler =
            getFactory().createScheduler([this](bool enabled) { setPrimaryVsyncEnabled(enabled); },
                                         mRefreshRateConfigs);
	mAppConnectionHandle =
            mScheduler->createConnection("app", mPhaseOffsets->getCurrentAppOffset(),
                                         resyncCallback,
                                         impl::EventThread::InterceptVSyncsCallback());
    mSfConnectionHandle = mScheduler->createConnection("sf", mPhaseOffsets->getCurrentSfOffset(),
                                                       resyncCallback, [this](nsecs_t timestamp) {
                                                           mInterceptor->saveVSyncEvent(timestamp);
                                                       });
	......
}

這個函數中首先創建了Scheduler,接着通過Scheduler創建了兩個Scheduler::ConnectionHandle,從名字能看出來,一個負責app處理,一個負責surfaceflinger處理,EventThread也會創建兩個,剛好對應這兩個ConnectionHandle

EventThread::EventThread(VSyncSource* src, std::unique_ptr<VSyncSource> uniqueSrc,
                         InterceptVSyncsCallback interceptVSyncsCallback, const char* threadName)
      : mVSyncSource(src),
        mVSyncSourceUnique(std::move(uniqueSrc)),
        mInterceptVSyncsCallback(std::move(interceptVSyncsCallback)),
        mThreadName(threadName) {
      ......
}

EventThread的構造函數裏面先不忙分析,先來看看它構造函數中初始化的mVSyncSource,類型爲VSyncSource,看它是如何創建的

回到前面創建Scheduler::ConnectionHandle的函數:

createConnection

sp<Scheduler::ConnectionHandle> Scheduler::createConnection(
        const char* connectionName, int64_t phaseOffsetNs, ResyncCallback resyncCallback,
        impl::EventThread::InterceptVSyncsCallback interceptCallback) {
    const int64_t id = sNextId++;
    std::unique_ptr<EventThread> eventThread =
            makeEventThread(connectionName, mPrimaryDispSync.get(), phaseOffsetNs,
                            std::move(interceptCallback));
    ......
    return mConnections[id]->handle;
}

std::unique_ptr<EventThread> Scheduler::makeEventThread(
        const char* connectionName, DispSync* dispSync, int64_t phaseOffsetNs,
        impl::EventThread::InterceptVSyncsCallback interceptCallback) {
    std::unique_ptr<VSyncSource> eventThreadSource =
            std::make_unique<DispSyncSource>(dispSync, phaseOffsetNs, true, connectionName);
    return std::make_unique<impl::EventThread>(std::move(eventThreadSource),
                                               std::move(interceptCallback), connectionName);
}

上面兩個函數就會創建VSyncSource並傳遞到EventThread中,

原來創建的是VSyncSource的子類DispSyncSourc,創建DispSyncSource時又需要一個DispSync,DispSync則是直接傳遞的mPrimaryDispSync.get()

那麼現在就需要搞清楚mPrimaryDispSync是什麼時候創建的

找到了,mPrimaryDispSync是在Scheduler的構造函數中創建的


Scheduler::Scheduler(impl::EventControlThread::SetVSyncEnabledFunction function,
                     const scheduler::RefreshRateConfigs& refreshRateConfig)
      : mHasSyncFramework(running_without_sync_framework(true)),
        mDispSyncPresentTimeOffset(present_time_offset_from_vsync_ns(0)),
        mPrimaryHWVsyncEnabled(false),
        mHWVsyncAvailable(false),
        mRefreshRateConfigs(refreshRateConfig) {
    // Note: We create a local temporary with the real DispSync implementation
    // type temporarily so we can initialize it with the configured values,
    // before storing it for more generic use using the interface type.
    auto primaryDispSync = std::make_unique<impl::DispSync>("SchedulerDispSync");
    primaryDispSync->init(mHasSyncFramework, mDispSyncPresentTimeOffset);
    mPrimaryDispSync = std::move(primaryDispSync);
	......
}

創建DispSync之後調用了它的init函數,來看看DispSync的構造函數

DispSync::DispSync(const char* name) : mName(name), mRefreshSkipCount(0) {
    // 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);
}

這裏面創建了一個線程DispSyncThread,這個線程構造函數中只是對一些值做了初始化,這個線程重點是它的threadLoop函數,這個函數現在先不忙看,等下分析了EventThread之後在回頭針對性看

好了EventThread的VSyncSource就創建好了,實際上是一個DispSyncSource對象,DispSyncSource內部有一個DispSync,DispSync內部有一個線程DispSyncThread,其實我們光看名字應該能夠猜測,這幾個類都是用來處理VSync的

接着回到EventThread的構造函數:

EventThread::EventThread(VSyncSource* src, std::unique_ptr<VSyncSource> uniqueSrc,
                         InterceptVSyncsCallback interceptVSyncsCallback, const char* threadName)
      : mVSyncSource(src),
        mVSyncSourceUnique(std::move(uniqueSrc)),
        mInterceptVSyncsCallback(std::move(interceptVSyncsCallback)),
        mThreadName(threadName) {
    ......
    mVSyncSource->setCallback(this);

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

     ......
}

這個函數有兩個重點,1.給VSyncSource設置回調,2.創建一個線程,並調用threadMain函數

首先看設置回調:

class VSyncSource {
public:
    class Callback {
    public:
        virtual ~Callback() {}
        virtual void onVSyncEvent(nsecs_t when) = 0;
    };
	.....    
}

這個回調的類型是VSyncSource::Callback,它只有一個函數onVSyncEvent,這個函數被EventThread實現了,也就是說會有某些情況發生之後EventThread會調用onVSyncEvent函數,我們根據這個函數的名字可以猜測一下可能是收到來自硬件的VSync後會回調此函數

回調設置之後會創建一個線程調用threadMain函數,這是EventThread核心函數,這個函數代碼很多,在看這個函數之前,我們先了解一下這個函數用到的重要變量的含義,主要有三個容器進行存取數據的操作,DisplayEventConsumers consumers,mPendingEvents,mDisplayEventConnections,它們都定義在EventThread.h中

//EventThread.h
using DisplayEventConsumers = std::vector<sp<EventThreadConnection>>;

std::deque<DisplayEventReceiver::Event> mPendingEvents GUARDED_BY(mMutex);

std::vector<wp<EventThreadConnection>> mDisplayEventConnections GUARDED_BY(mMutex);

GUARDED_BY用來保證線程安全,類似java同步鎖synchronized的用法

consumers類型爲DisplayEventConsumers,這是一個vector,裏面放的是EventThreadConnection

mPendingEvents是一個deque隊列,裏面放的是DisplayEventReceiver::Event

mDisplayEventConnections也是一個vector,裏面放的也是EventThreadConnection

這裏雖然consumers和mDisplayEventConnections都是存儲EventThreadConnection,但是consumers存儲的是請求了Vsync的connection,mDisplayEventConnections存儲的是所有和surfaceFlinger進程建立連接的connection

這三個重要容器看了之後再來看看mState這個變量,這是用來描述EventThread的線程狀態的,mState類型爲State,定義在EventThread.h中

 enum class State {
        Idle,
        Quit,
        SyntheticVSync,
        VSync,
    };

    State mState GUARDED_BY(mMutex) = State::Idle;

一共有4種狀態,Idle表示空閒,Quit表示退出,SyntheticVSync表示合成VSync(滅屏時會是這種狀態),VSync表示請求VSync

EventThread線程狀態看完之後再來看一個VSyncRequest

enum class VSyncRequest {
    None = -1,
    Single = 0,
    Periodic = 1,
    // Subsequent values are periods.
};

這個枚舉類用來表示VSync的請求類型,有三種,None表示當前沒有VSync請求,Single表示這是一次性VSync請求(請求一次,接收一次),Periodic表示這是週期性VSync請求(請求一次可以一直接收)

對threadMain函數中用到的重要變量有了基本瞭解之後,現在我們再來看這個函數:

void EventThread::threadMain(std::unique_lock<std::mutex>& lock) {
    //存儲EventThreadConnection的vector,consumers表示即將消費
    //事件的connection集合
    DisplayEventConsumers consumers;
    //只要不退出,就一直循環,相當於死循環
    while (mState != State::Quit) {
        //構造一個待分發的Event
        std::optional<DisplayEventReceiver::Event> event;

        // mPendingEvents是一個vector,存儲即將處理的
        //DisplayEventReceiver::Event
        if (!mPendingEvents.empty()) {
            //獲取頭部Event
            event = mPendingEvents.front();
            //並將頭部Event彈出
            mPendingEvents.pop_front();
            //根據Event的類型,做不同處理,我們只關心VSYNC類型
            switch (event->header.type) {
                case DisplayEventReceiver::DISPLAY_EVENT_HOTPLUG:
                    ......
                    break;

                case DisplayEventReceiver::DISPLAY_EVENT_VSYNC:
                    if (mInterceptVSyncsCallback) {
                        mInterceptVSyncsCallback(event->header.timestamp);
                    }
                    break;
            }
        }
        //是否有vsync請求,默認false
        bool vsyncRequested = false;

        // 從mDisplayEventConnections中查詢應該接收Event的
        //EventThreadConnection,這是個vector遍歷操作
        auto it = mDisplayEventConnections.begin();
        while (it != mDisplayEventConnections.end()) {
            //弱指針升級強指針,當對象已經銷燬或者準備銷燬則返回false
            if (const auto connection = it->promote()) {
                //如果有一個connection的vsyncRequest不爲None則
                //vsyncRequested爲true
                vsyncRequested |= connection->vsyncRequest != VSyncRequest::None;
                //如果event不爲空並且shouldConsumeEvent返回true
                //則將connection加入到consumers,等待消費event,
                //shouldConsumeEvent的實現很簡單,對於VSYNC類型的事件,
                //只要VSyncRequest的類型不是None就返回true
                if (event && shouldConsumeEvent(*event, connection)) {
                   //加入consumers
                    consumers.push_back(connection);
                }

                ++it;
            } else {
               //如果connections已經銷燬則移除它
                it = mDisplayEventConnections.erase(it);
            }
        }
      
        if (!consumers.empty()) {
             //如果consumers不爲空則調用dispatchEvent
             //爲consumers中的每個connection分發事件
             //後面分析...
            dispatchEvent(*event, consumers);
            //分發之後清空consumers
            consumers.clear();
        }

        State nextState;
        //如果有vsync的請求
        if (mVSyncState && vsyncRequested) {
            //判斷是SyntheticVSync還是VSync類型的VSync
            //mVSyncState->synthetic在滅屏時被賦值爲true,亮屏
            //時爲false
            nextState = mVSyncState->synthetic ? State::SyntheticVSync : State::VSync;
        } else {
            ALOGW_IF(!mVSyncState, "Ignoring VSYNC request while display is disconnected");
            //沒有vsync則狀態爲State::Idle
            nextState = State::Idle;
        }
        //兩個狀態不等說明有兩種可能,1.從State::VSync變爲其他
        //2.從其他變爲State::VSync
        if (mState != nextState) {
            //情況1
            if (mState == State::VSync) {
                //後面分析...
                mVSyncSource->setVSyncEnabled(false);
                //情況2
            } else if (nextState == State::VSync) {
                mVSyncSource->setVSyncEnabled(true);
            }

            mState = nextState;
        }
        //如果有事件則繼續循環
        if (event) {
            continue;
        }
        // 沒有事件並且當前狀態爲State::Idle
        if (mState == State::Idle) {
            //則通過條件變量陷入等待
            mCondition.wait(lock);
        } else {
            //如果沒有事件並且當前狀態不爲空閒,這種情況是硬件不知什麼原因沒
            //有發送VSync上來,需要僞造VSync信號,頻率爲滅屏時16ms,亮屏
            //1000ms
            const auto timeout = mState == State::SyntheticVSync ? 16ms : 1000ms;
            if (mCondition.wait_for(lock, timeout) == std::cv_status::timeout) {
                //將僞造的VSync放入mPendingEvents,準備分發
                mPendingEvents.push_back(makeVSync(mVSyncState->displayId,
                                                   systemTime(SYSTEM_TIME_MONOTONIC),
                                                   ++mVSyncState->count));
            }
        }
    }
}

threadMain函數大概分析完了,代碼是挺多的,仔細看看註釋,結合前面單獨對重要數據的分析,會發現邏輯是比較簡單,總結一下:

  1. threadMain首先會開啓一個死循環,這個循環會一直處理事件
  2. 從mPendingEvents頭部獲取VSYNC事件Event
  3. 遍歷mDisplayEventConnections,找到其中所有vsyncRequest不爲None的connection,並將這些connection放入consumers
  4. 調用dispatchEvent(*event, consumers)分發事件,事件會分發給consumers中的所有connection
  5. 根據mState和nextState的對比,選擇setVSyncEnabled(false)還是(true),當從State::VSync變爲其他狀態時調用setVSyncEnabled(false),當從其他狀態變爲State::VSync時調用setVSyncEnabled(true),mState和nextState的對比其實是起到一個開關作用
  6. 如果沒有事件並且線程狀態爲State::Idle,則通過條件變量mCondition讓線程陷入等待,如果沒有事件並且線程狀態不爲State::Idle時則需要僞造VSync發送給請求者

前面兩篇文章分析了應用層想要進行UI繪製則需要向surfaceFlinger進程請求VSync,等待下一個VSync到來之後通知應用進行繪製,應用層請求VSync的過程就是通過條件變量的notify函數,喚醒threadMain中陷入等待的這個死循環,剛剛threadMain函數的分析又知道了這個死循環主要工作就是從mPendingEvents獲取到事件,然後調用dispatchEvent函數分發給感興趣的connection,何爲感興趣的connection?就是它的vsyncRequest不爲None,dispatchEvent函數就會將

到這裏還遺留了幾個關鍵地方沒有分析,1.mPendingEvents裏的事件是怎麼來的,2.setVSyncEnabled函數的具體作用

我們先來看setVSyncEnabled這個函數的具體作用,這個函數定義在DispSyncSource中,DispSyncSource我們前面分析過,是在創建EventThread的時候創建的,並且DispSyncSource內部還創建了一個DispSync,DispSync內部開啓了一個線程DispSyncThread,這個線程有個重要的threadLoop函數我們還留着沒分析
先看這個函數:

DispSyncSource.setVSyncEnabled

void DispSyncSource::setVSyncEnabled(bool enable) {
    std::lock_guard lock(mVsyncMutex);
    if (enable) {
        status_t err = mDispSync->addEventListener(mName, mPhaseOffset,
                                                   static_cast<DispSync::Callback*>(this),
                                                   mLastCallbackTime);
        ......
    } else {
        status_t err = mDispSync->removeEventListener(static_cast<DispSync::Callback*>(this),
                                                      &mLastCallbackTime);
        ......
    }
    mEnabled = enable;
}

這個函數其實就是添加和移除監聽器,那麼這個監聽器到底在監聽什麼?監聽到了之後又調用它的哪個回調函數?
回調哪個函數這很簡單,我們看看DispSync.h就知道了

class DispSync {
public:
    class Callback {
    public:
        Callback() = default;
        virtual ~Callback();
        virtual void onDispSyncEvent(nsecs_t when) = 0;
		......        
}

就是這個函數onDispSyncEvent,也就是說當通過setVSyncEnabled添加的監聽器,監聽到某件事發生之後就會回調DispSyncSource的onDispSyncEvent函數,那現在就需要找到添加的這個監聽器在監聽什麼?

來看看DispSync添加監聽器之後做了什麼

mDispSync->addEventListener

status_t addEventListener(const char* name, nsecs_t phase, DispSync::Callback* callback,
                              nsecs_t lastCallbackTime) {
 		...

        for (size_t i = 0; i < mEventListeners.size(); i++) {
            if (mEventListeners[i].mCallback == callback) {
                return BAD_VALUE;
            }
        }

        EventListener listener;
        listener.mName = name;
        listener.mPhase = phase;
        listener.mCallback = callback;
        .....
        mEventListeners.push_back(listener);

        mCond.signal();

        return NO_ERROR;
    }

我省略一大段EventListener time的計算,不想去分析了,剩下的代碼無非就是根據添加的監聽callback,name等構造一個EventListener,然後存儲到mEventListeners這個Vector中,mCond.signal類似條件變量,也是一個喚醒/等待機制,那它是要喚醒什麼呢?

前面DispSync創建時就開啓了一個線程DispSyncThread,這個線程也類似EventThread內部的線程,是一個死循環,這個線程是真正分發Vsync信號的線程,所有應用程序以及surfaceFlinger註冊的Vsync都是通過這個線程的死循環中分發出去的,限於篇幅,關於DispSyncThread的相關分析留到下一篇文章

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章