在http://blog.csdn.net/kc58236582/article/details/52763534博客的VSync信号的分发过程那节中我们已经详细分析了VSync信号的分发过程,其中EventThread主要就是发送VSync信号。
这里我们先从DisplayEventReceiver这个java类来分析:
我们先看其构造函数,直接调用了nativeInit native函数
public DisplayEventReceiver(Looper looper) {
if (looper == null) {
throw new IllegalArgumentException("looper must not be null");
}
mMessageQueue = looper.getQueue();
mReceiverPtr = nativeInit(new WeakReference(this), mMessageQueue);
mCloseGuard.open("dispose");
}
这个native函数是在android_view_DisplayEventReceiver.cpp中,我们来看下,它新建了一个NativeDisplayEventReceiver类
static jlong nativeInit(JNIEnv* env, jclass clazz, jobject receiverWeak,
jobject messageQueueObj) {
sp messageQueue = android_os_MessageQueue_getMessageQueue(env, messageQueueObj);
if (messageQueue == NULL) {
jniThrowRuntimeException(env, "MessageQueue is not initialized.");
return 0;
}
sp receiver = new NativeDisplayEventReceiver(env,
receiverWeak, messageQueue);
status_t status = receiver->initialize();
if (status) {
String8 message;
message.appendFormat("Failed to initialize display event receiver. status=%d", status);
jniThrowRuntimeException(env, message.string());
return 0;
}
receiver->incStrong(gDisplayEventReceiverClassInfo.clazz); // retain a reference for the object
return reinterpret_cast(receiver.get());
}
在NativeDisplayEventReceiver 对象中又有一个c层的DisplayEventReceiver对象,其在NativeDisplayEventReceiver 中变量为mReceiver
class NativeDisplayEventReceiver : public LooperCallback {
public:
NativeDisplayEventReceiver(JNIEnv* env,
jobject receiverWeak, const sp& messageQueue);
status_t initialize();
void dispose();
status_t scheduleVsync();
protected:
virtual ~NativeDisplayEventReceiver();
private:
jobject mReceiverWeakGlobal;
sp mMessageQueue;
DisplayEventReceiver mReceiver;
我们来看它的构造函数,直接在构造函数中利用getComposerService来和SurfaceFlinger通信来获取一个DisplayEventConnection
DisplayEventReceiver::DisplayEventReceiver() {
sp sf(ComposerService::getComposerService());
if (sf != NULL) {
mEventConnection = sf->createDisplayEventConnection();
if (mEventConnection != NULL) {
mDataChannel = mEventConnection->getDataChannel();
}
}
}
我们来看下SurfaceFlinger中这个函数,这个函数之前我们分析过就是调用了EventThread的createEventConnection。
sp SurfaceFlinger::createDisplayEventConnection() {
return mEventThread->createEventConnection();
}
我们再回到DisplayEventReceiver的构造函数中,得到DisplayEventConnection后,我们再调用其getDataChannel函数来获取BitTube(通信方式)。
在nativeInit中,新建了一个NativeDisplayEventReceiver后,调用了其initialize函数,这个函数先调用DisplayEventReceiver的initCheck看是否有错,然后就利用Looper的addFd,设置回调。其fd就是DisplayEventReceiver的fd,也就是SurfaceFlinger那边的EventThread有VSync信号过来,最终回调这里的回调函数。
status_t NativeDisplayEventReceiver::initialize() {
status_t result = mReceiver.initCheck();
if (result) {
ALOGW("Failed to initialize display event receiver, status=%d", result);
return result;
}
int rc = mMessageQueue->getLooper()->addFd(mReceiver.getFd(), 0, Looper::EVENT_INPUT,
this, NULL);
if (rc < 0) {
return UNKNOWN_ERROR;
}
return OK;
}
我们来看下DisplayEventReceiver的initCheck函数就是看mDataChannel(BitTube)是否为空 和getFd函数获取其fd。
status_t DisplayEventReceiver::initCheck() const {
if (mDataChannel != NULL)
return NO_ERROR;
return NO_INIT;
}
int DisplayEventReceiver::getFd() const {
if (mDataChannel == NULL)
return NO_INIT;
return mDataChannel->getFd();
}
而最终在addFd中注册的回调时this,这个我们之前在分析Looper的时候分析过,也就是会调用这个类的handleEvent函数,在这个函数中调用dispatchVsync继续分发VSync信号。
int NativeDisplayEventReceiver::handleEvent(int receiveFd, int events, void* data) {
......
nsecs_t vsyncTimestamp;
int32_t vsyncDisplayId;
uint32_t vsyncCount;
if (processPendingEvents(&vsyncTimestamp, &vsyncDisplayId, &vsyncCount)) {
ALOGV("receiver %p ~ Vsync pulse: timestamp=%" PRId64 ", id=%d, count=%d",
this, vsyncTimestamp, vsyncDisplayId, vsyncCount);
mWaitingForVsync = false;
dispatchVsync(vsyncTimestamp, vsyncDisplayId, vsyncCount);
}
return 1; // keep the callback
}
这里是利用jni反调了DisplayEventReceiver java类的dispatchVsync函数。
void NativeDisplayEventReceiver::dispatchVsync(nsecs_t timestamp, int32_t id, uint32_t count) {
JNIEnv* env = AndroidRuntime::getJNIEnv();
ScopedLocalRef receiverObj(env, jniGetReferent(env, mReceiverWeakGlobal));
if (receiverObj.get()) {
ALOGV("receiver %p ~ Invoking vsync handler.", this);
env->CallVoidMethod(receiverObj.get(),
gDisplayEventReceiverClassInfo.dispatchVsync, timestamp, id, count);
ALOGV("receiver %p ~ Returned from vsync handler.", this);
}
mMessageQueue->raiseAndClearException(env, "dispatchVsync");
}
我们再来看看DisplayEventReceiver java类的dispatchVsync函数,调用了onVsync函数。
private void dispatchVsync(long timestampNanos, int builtInDisplayId, int frame) {
onVsync(timestampNanos, builtInDisplayId, frame);
}
而这个onVsync是一个空函数,具体在其子类中实现了。
我们再看看有哪些类实现了DisplayEventReceiver类
就看到在Choreographer.java中有如下 FrameDisplayEventReceiver 内部类的实现,这个主要是WMS中使用。
private final class FrameDisplayEventReceiver extends DisplayEventReceiver
implements Runnable {
private boolean mHavePendingVsync;
private long mTimestampNanos;
private int mFrame;
public FrameDisplayEventReceiver(Looper looper) {
super(looper);
}
@Override
public void onVsync(long timestampNanos, int builtInDisplayId, int frame) {
// Ignore vsync from secondary display.
// This can be problematic because the call to scheduleVsync() is a one-shot.
// We need to ensure that we will still receive the vsync from the primary
// display which is the one we really care about. Ideally we should schedule
// vsync for a particular display.
// At this time Surface Flinger won't send us vsyncs for secondary displays
// but that could change in the future so let's log a message to help us remember
// that we need to fix this.
if (builtInDisplayId != SurfaceControl.BUILT_IN_DISPLAY_ID_MAIN) {
Log.d(TAG, "Received vsync from secondary display, but we don't support "
+ "this case yet. Choreographer needs a way to explicitly request "
+ "vsync for a specific display to ensure it doesn't lose track "
+ "of its scheduled vsync.");
scheduleVsync();
return;
}
// Post the vsync event to the Handler.
// The idea is to prevent incoming vsync events from completely starving
// the message queue. If there are no messages in the queue with timestamps
// earlier than the frame time, then the vsync event will be processed immediately.
// Otherwise, messages that predate the vsync event will be handled first.
long now = System.nanoTime();
if (timestampNanos > now) {
Log.w(TAG, "Frame time is " + ((timestampNanos - now) * 0.000001f)
+ " ms in the future! Check that graphics HAL is generating vsync "
+ "timestamps using the correct timebase.");
timestampNanos = now;
}
if (mHavePendingVsync) {
Log.w(TAG, "Already have a pending vsync event. There should only be "
+ "one at a time.");
} else {
mHavePendingVsync = true;
}
mTimestampNanos = timestampNanos;
mFrame = frame;
Message msg = Message.obtain(mHandler, this);
msg.setAsynchronous(true);
mHandler.sendMessageAtTime(msg, timestampNanos / TimeUtils.NANOS_PER_MS);
}
@Override
public void run() {
mHavePendingVsync = false;
doFrame(mTimestampNanos, mFrame);
}
}