天天看點

Android VSYNC事件傳遞流程

我一直以為DisplayEventReceiver是跟Input一樣,通過BitTube的兩個socket進行跨程序的通信,也就是SF-APP之間的通信,但實際上不是的。

實際上的邏輯是,每次VSYNC事件到來從HAL的線程調之後,

01-01 00:35:01.163  2963  3017 D SurfaceFlinger: onVSyncEvent

EventThread會将這個vsync事件記錄到自己的mVSyncEvent中,并釋放Condition鎖。

void EventThread::onVSyncEvent(nsecs_t timestamp) {

    ALOGD("EventThread::onVSyncEvent");

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

    mVSyncEvent[0].header.type = DisplayEventReceiver::DISPLAY_EVENT_VSYNC;

    mVSyncEvent[0].header.id = 0;

    mVSyncEvent[0].header.timestamp = timestamp;

    mVSyncEvent[0].vsync.count++;

    mCondition.notify_all();

}

然後在EventThread一直threadLoop的waitForEvent函數中,此時如果有有效的connection連接配接的話就會真正拿到這個事件。前面的邏輯是判斷mDisplayEventConnections清單裡面是不是存在有效的Connection。

if (mCondition.wait_for(*lock, timeout) == std::cv_status::timeout) {

    if (!softwareSync) {

        ALOGW("Timed out waiting for hw vsync; faking it");

    }

    // FIXME: how do we decide which display id the fake

    // vsync came from ?

    ALOGD("EventThread::waitForEventLocked get new vsyncevent and release mCondition")

    mVSyncEvent[0].header.type = DisplayEventReceiver::DISPLAY_EVENT_VSYNC;

    mVSyncEvent[0].header.id = DisplayDevice::DISPLAY_PRIMARY;

    mVSyncEvent[0].header.timestamp = systemTime(SYSTEM_TIME_MONOTONIC);

    mVSyncEvent[0].vsync.count++;

}

由于正常情況下,至少會存在一個MessageQueue setEventThread時建立一個EventConnection。

    mEventThread = eventThread;

    mEvents = eventThread->createEventConnection();

    mEvents->stealReceiveChannel(&mEventTube);

    mLooper->addFd(mEventTube.getFd(), 0, Looper::EVENT_INPUT, MessageQueue::cb_eventReceiver,

                   this);

而應用app側在建立Choreographer時,會建立FrameDisplayEventReceiver,FrameDisplayEventReceiver繼承DisplayEventReceiver。通過jni函數nativeInit繼續建立NativeDisplayEventReceiver,并調用其父類DisplayEventDispatcher initialize進行初始化。

    private Choreographer(Looper looper, int vsyncSource) {

        mLooper = looper;

        mHandler = new FrameHandler(looper);

        mDisplayEventReceiver = USE_VSYNC

                ? new FrameDisplayEventReceiver(looper, vsyncSource)

                : null;

    sp<NativeDisplayEventReceiver> receiver = new NativeDisplayEventReceiver(env,

            receiverWeak, messageQueue, vsyncSource);

    status_t status = receiver->initialize();

DisplayEventDispatcher構造時會建立成員DisplayEventDispatcher,然後再在initialize裡面,将receiveFd也放到應用主線程的Looper中進行監聽。

status_t DisplayEventDispatcher::initialize() {

    status_t result = mReceiver.initCheck();

    if (result) {

        ALOGW("Failed to initialize display event receiver, status=%d", result);

        return result;

    }

    ALOGW("DisplayEventDispatcher::initialize addFd %d ", mReceiver.getFd());

    int rc = mLooper->addFd(mReceiver.getFd(), 0, Looper::EVENT_INPUT,

            this, NULL);

    if (rc < 0) {

        return UNKNOWN_ERROR;

    }

    return OK;

}

DisplayEventDispatcher在建立時也會預設通過sf建立一個EventConnection.

DisplayEventReceiver::DisplayEventReceiver(ISurfaceComposer::VsyncSource vsyncSource) {

    sp<ISurfaceComposer> sf(ComposerService::getComposerService());

    if (sf != NULL) {

        mEventConnection = sf->createDisplayEventConnection(vsyncSource);

        if (mEventConnection != NULL) {

            mDataChannel = std::make_unique<gui::BitTube>();

            ALOGD("DisplayEventReceiver init stealReceiveChannel %d", getFd());

            mEventConnection->stealReceiveChannel(mDataChannel.get());

        }

    }

}

這樣再回到EventThread線程,在waitForEvent拿到VSYNC事件之後,就會周遊signalConnections将VSYNC event post過去,這樣SF和各個應用的Choreographer都收到了VYSNC事件。并非是之前了解的SF再把這個事件通過一個Bittub傳給應用端,是以一直也找不到設定sendFd的地方。

const size_t count = signalConnections.size();

for (size_t i = 0; i < count; i++) {

    const sp<Connection>& conn(signalConnections[i]);

    ALOGD("EventThread:::threadMain conn->postEvent %p", conn);

    // now see if we still need to report this event

    status_t err = conn->postEvent(event);