我一直以為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);