鉴于 app 进程请求 vsync 信号 讲到的 DisplayEventReceiver
- 它内部有 mEventConnection, 作为 binder 客户端,调用 SurfaceFlinger 的服务发起 Vsync 请求
- 内部有 mDataChannel 负责接收 Vsync 信号
1. mDataChannel
接收 SurfaceFlinger 发送来的 Vsync 消息
- 创建:构造函数中创建
sp<ISurfaceComposer> sf(ComposerService::getComposerService());
if (sf != NULL) {
//创建与 SurfaceFlinger 通信的桥梁,mEventConnection 主要是发消息给 SurfaceFlinger
mEventConnection = sf->createDisplayEventConnection(vsyncSource);
if (mEventConnection != NULL) {
mDataChannel = std::make_unique<gui::BitTube>();
//创建 mDataChannel
mEventConnection->stealReceiveChannel(mDataChannel.get());
}
}
1.1 通过 mEventConnection 这个 binder 客户端获取到服务器端生成的 gui::BitTube
1.2 gui::BitTube 本质是个 socketpair
1.3 这里 stealReceiveChannel 拿到的是 socket 的 receive fd
1.4 客户端直接监听这个 receive fd 即可,这样当SurfaceFlinger 触发 Vsync 信号时,直接通过这个 socket 的 send fd 发送消息就行
那我们是在哪里监听这个 receive fd 的呢
2. 监听 DisplayEventReceiver 的 socket
在 app 进程请求 vsync 信号 讲到的直接使用 DisplayEventReceiver 的是 DisplayEventDispatcher.cpp, 它里面有个成员属性 DisplayEventReceiver mReceiver;
status_t DisplayEventDispatcher::initialize() {
status_t result = mReceiver.initCheck();
if (result) {
ALOGW("Failed to initialize display event receiver, status=%d", result);
return result;
}
int rc = mLooper->addFd(mReceiver.getFd(), 0, Looper::EVENT_INPUT, this, NULL);
if (rc < 0) {
return UNKNOWN_ERROR;
}
return OK;
}
它在 initialize 的时候把通过 Looper 监听这个fd,而这个 looper 就是 app 的主线程的 looper
3. 接收 Vsync 信号
- 这样当有 Vsync 信号来时,主线程的 looper 被唤醒
- 进而回调 mLooper->addFd(mReceiver.getFd(), 0, Looper::EVENT_INPUT, this, NULL);设置的 callback,//callback(LooperCallback) == this
- 即 DisplayEventDispatcher 的 handleEvent
int DisplayEventDispatcher::handleEvent(int, int events, void*) {
if (processPendingEvents(&vsyncTimestamp, &vsyncDisplayId, &vsyncCount)) {
dispatchVsync(vsyncTimestamp, vsyncDisplayId, vsyncCount);
}
return 1; // keep the callback
}
进而回到 NativeDisplayEventReceiver 的 dispatchVsync
void NativeDisplayEventReceiver::dispatchVsync(nsecs_t timestamp, int32_t id,
uint32_t count) {
JNIEnv* env = AndroidRuntime::getJNIEnv();
//取出 java 层的 DisplayEventReceiver,反射调用它的 dispatchVsync方法
//再次回到 FrameDisplayEventReceiver 的 onVsync 回调
ScopedLocalRef<jobject> receiverObj(env, jniGetReferent(env, mReceiverWeakGlobal));
if (receiverObj.get()) {
env->CallVoidMethod(receiverObj.get(),
gDisplayEventReceiverClassInfo.dispatchVsync, timestamp, id, count);
}
mMessageQueue->raiseAndClearException(env, "dispatchVsync");
}
最终回到 Choreography 中的 doFrame 方法,进行 doCallbacks操作