app 进程接收 vsync 信号

151 阅读2分钟

鉴于 app 进程请求 vsync 信号 讲到的 DisplayEventReceiver

  1. 它内部有 mEventConnection, 作为 binder 客户端,调用 SurfaceFlinger 的服务发起 Vsync 请求
  2. 内部有 mDataChannel 负责接收 Vsync 信号

1. mDataChannel

接收 SurfaceFlinger 发送来的 Vsync 消息

  1. 创建:构造函数中创建
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 信号

  1. 这样当有 Vsync 信号来时,主线程的 looper 被唤醒
  2. 进而回调 mLooper->addFd(mReceiver.getFd(), 0, Looper::EVENT_INPUT, this, NULL);设置的 callback,//callback(LooperCallback) == this
  3. 即 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操作