Android6.0 VSync信号如何到用户进程

在http://blog.csdn.net/kc58236582/article/details/52763534博客的VSync信号的分发过程那节中我们已经详细分析了VSync信号的分发过程,其中EventThread主要就是发送VSync信号。


一、DisplayEventReceiver.java

这里我们先从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子类

我们再看看有哪些类实现了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);
        }
    }




你可能感兴趣的:(android显示系统,android,WMS)