AndroidQ 应用层Vsync信号的注册与接收(上)

上一篇文章我们分析了UI刷新机制,知道了Android UI刷新是在接收到Vsync信号之后才进行的,接着我准备继续分析Vsync如何向native层注册以及native层如何将Vsync发到上层,这部分比较复杂,我准备分两篇文章来分析,主要就是两个native函数:nativeInit和nativeScheduleVsync

根据上一篇文章,我们知道每当UI请求重绘时会调用Choreographer中的DisplayEventReceiver类的nativeScheduleVsync向native层注册监听Vsync,并且当下一个Vsync到来时会回调DisplayEventReceiver的onVsync方法,可以看出来DisplayEventReceiver这个类就是处理Vsync相关的核心

我们就从DisplayEventReceiver的创建开始分析,DisplayEventReceiver是个抽象类,它的实现类FrameDisplayEventReceiver在Choreographer的构造方法中初始化的

Choreographer

private Choreographer(Looper looper, int vsyncSource) {
        //UI线程的looper
        mLooper = looper;
        mHandler = new FrameHandler(looper);
        //USE_VSYNC为true,使用VSYNC
        mDisplayEventReceiver = USE_VSYNC
                ? new FrameDisplayEventReceiver(looper, vsyncSource)
                : null;
        mLastFrameTimeNanos = Long.MIN_VALUE;
        //Android默认60FPS,mFrameIntervalNanos为16.6
        mFrameIntervalNanos = (long)(1000000000 / getRefreshRate());
        mCallbackQueues = new CallbackQueue[CALLBACK_LAST + 1];
        for (int i = 0; i <= CALLBACK_LAST; i++) {
            mCallbackQueues[i] = new CallbackQueue();
        }
        // b/68769804: For low FPS experiments.
        setFPSDivisor(SystemProperties.getInt(ThreadedRenderer.DEBUG_FPS_DIVISOR, 1));
    }

Choreographer构造中做一些重要的初始化工作,我们这里注意一下vsyncSource这个值

DisplayEventReceiver中定义了如下两个常量,代表VSYNC的两种使用,APP和SurfaceFlinger,这里传递到native层的是VSYNC_SOURCE_APP这种,即APP层请求的VSYNC

 /**
     * When retrieving vsync events, this specifies that the vsync event should happen at the normal
     * vsync-app tick.
     * 

* Needs to be kept in sync with frameworks/native/include/gui/ISurfaceComposer.h */ public static final int VSYNC_SOURCE_APP = 0; /** * When retrieving vsync events, this specifies that the vsync event should happen whenever * Surface Flinger is processing a frame. *

* Needs to be kept in sync with frameworks/native/include/gui/ISurfaceComposer.h */ public static final int VSYNC_SOURCE_SURFACE_FLINGER = 1;

FrameDisplayEventReceiver的构造方法中显式调用了父类DisplayEventReceiver的构造方法:

public DisplayEventReceiver(Looper looper, int vsyncSource) {
        if (looper == null) {
            throw new IllegalArgumentException("looper must not be null");
        }

        mMessageQueue = looper.getQueue();
        mReceiverPtr = nativeInit(new WeakReference<DisplayEventReceiver>(this), mMessageQueue,
                vsyncSource);

        mCloseGuard.open("dispose");
    }

调用nativeInit,将主线程的MessageQueue传递了过去

static jlong nativeInit(JNIEnv* env, jclass clazz, jobject receiverWeak,
        jobject messageQueueObj, jint vsyncSource) {
        //根据java层messageQueue的到native层messageQueue
    sp<MessageQueue> messageQueue = android_os_MessageQueue_getMessageQueue(env, messageQueueObj);
    if (messageQueue == NULL) {
        jniThrowRuntimeException(env, "MessageQueue is not initialized.");
        return 0;
    }
    //步骤1
    sp<NativeDisplayEventReceiver> receiver = new NativeDisplayEventReceiver(env,
            receiverWeak, messageQueue, vsyncSource);
    //步骤2
    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<jlong>(receiver.get());
}

这个方法重点就两部分,步骤1:创建NativeDisplayEventReceiver,步骤2:调用其initialize方法

我们首先看步骤1:

NativeDisplayEventReceiver::NativeDisplayEventReceiver(JNIEnv* env,
        jobject receiverWeak, const sp<MessageQueue>& messageQueue, jint vsyncSource) :
        DisplayEventDispatcher(messageQueue->getLooper(),
                static_cast<ISurfaceComposer::VsyncSource>(vsyncSource)),
        mReceiverWeakGlobal(env->NewGlobalRef(receiverWeak)),
        mMessageQueue(messageQueue) {
    ALOGV("receiver %p ~ Initializing display event receiver.", this);
}

NativeDisplayEventReceiver构造方法中调用了父类DisplayEventDispatcher的构造方法,并且将java层传递下来的VSYNC_SOURCE_APP强转为了ISurfaceComposer::VsyncSource传递给了DisplayEventDispatcher,
VsyncSource是枚举类型,VSYNC_SOURCE_APP为0,所以就相当于强转为了eVsyncSourceApp,代表由APP层请求的Vsync

class ISurfaceComposer: public IInterface {
			...
	enum VsyncSource {
        eVsyncSourceApp = 0,
        eVsyncSourceSurfaceFlinger = 1
    };
			...
}

我们看DisplayEventDispatcher构造方法中将vsyncSource赋值给了mReceiver

DisplayEventDispatcher::DisplayEventDispatcher(const sp<Looper>& looper,
        ISurfaceComposer::VsyncSource vsyncSource) :
        mLooper(looper), mReceiver(vsyncSource), mWaitingForVsync(false) {
    ALOGV("dispatcher %p ~ Initializing display event dispatcher.", this);
}

mReceiver是DisplayEventReceiver类型,这里相当与调用DisplayEventReceiver的构造函数进行初始化

DisplayEventReceiver::DisplayEventReceiver(ISurfaceComposer::VsyncSource vsyncSource) {
    //步骤1
    sp<ISurfaceComposer> sf(ComposerService::getComposerService());
    if (sf != nullptr) {
        //步骤2
        mEventConnection = sf->createDisplayEventConnection(vsyncSource);
        if (mEventConnection != nullptr) {
            //步骤3
            mDataChannel = std::make_unique<gui::BitTube>();
               //步骤4
            mEventConnection->stealReceiveChannel(mDataChannel.get());
        }
    }
}

DisplayEventReceiver的构造函数做的事情非常重要,且比较复杂,主要是建立应用层与SurfaceFlinger的连接,这里分为四个步骤来分析

步骤1:获取SurfaceFlinger服务

sp sf(ComposerService::getComposerService());

ComposerService::getComposerService()

/*static*/ sp<ISurfaceComposer> ComposerService::getComposerService() {
    ComposerService& instance = ComposerService::getInstance();
    Mutex::Autolock _l(instance.mLock);
    if (instance.mComposerService == nullptr) {
        ComposerService::getInstance().connectLocked();
        assert(instance.mComposerService != nullptr);
        ALOGD("ComposerService reconnected");
    }
    return instance.mComposerService;
}

这个函数定义在SurfaceComposerClient.cpp中,这个函数中调用了ComposerService的connectLocked函数

connectLocked

void ComposerService::connectLocked() {
    const String16 name("SurfaceFlinger");
    while (getService(name, &mComposerService) != NO_ERROR) {
        usleep(250000);
    }
    assert(mComposerService != nullptr);

    // 创建死亡回调
    ......
}

connectLocked函数的作用很简单,获取SurfaceFlinger服务,保存在ComposerService的mComposerService中,其实获取的是SurfaceFlinger的Bp端BpSurfaceComposer,SurfaceFlinger的是它的Bn端BnSurfaceComposer的子类

接着看步骤2:通过Binder实现跨进程调用,最终到SurfaceFlinger中,
mEventConnection = sf->createDisplayEventConnection(vsyncSource);

createDisplayEventConnection

virtual sp<IDisplayEventConnection> createDisplayEventConnection(VsyncSource vsyncSource)
    {
        .....
        err = remote()->transact(
                BnSurfaceComposer::CREATE_DISPLAY_EVENT_CONNECTION,
                data, &reply);
       ......
       lt = interface_cast<IDisplayEventConnection>(reply.readStrongBinder());
        return result;
    }

需要注意最终从SurfaceFlinger返回的也是EventThreadConnection的Bp端BpDisplayEventConnection,EventThreadConnection继承自BnDisplayEventConnection

好了,来看SurfaceFlinger的createDisplayEventConnection函数,传递的参数是eVsyncSourceApp = 0,应用层请求的Vsync
mEventConnection = sf->createDisplayEventConnection(vsyncSource);

createDisplayEventConnection

sp<IDisplayEventConnection> SurfaceFlinger::createDisplayEventConnection(
        ISurfaceComposer::VsyncSource vsyncSource) {
    auto resyncCallback = mScheduler->makeResyncCallback([this] {
        Mutex::Autolock lock(mStateLock);
        return getVsyncPeriod();
    });
    
    const auto& handle =
            vsyncSource == eVsyncSourceSurfaceFlinger ? mSfConnectionHandle : mAppConnectionHandle;

    return mScheduler->createDisplayEventConnection(handle, std::move(resyncCallback));
}

这个函数我们首先来看mScheduler->makeResyncCallback,mScheduler是Scheduler类型,在SurfaceFlinger的init中创建的,这里会创建一个resyncCallback,类型为ResyncCallback,定义在EventThread.cpp中,std::function这是个新API

using ResyncCallback = std::function<void()>;

大致功能是将一段可执行代码封装到ResyncCallback中,仅从功能上看,和函数指针作用类似

ResyncCallback Scheduler::makeResyncCallback(GetVsyncPeriod&& getVsyncPeriod) {
    std::weak_ptr<VsyncState> ptr = mPrimaryVsyncState;
    return [ptr, getVsyncPeriod = std::move(getVsyncPeriod)]() {
        if (const auto vsync = ptr.lock()) {
            vsync->resync(getVsyncPeriod);
        }
    };
}

接着得到handle的类型,因为一开始传递的就是App请求的Vsync,所以handle为mAppConnectionHandle,它的类型为sp mAppConnectionHandle;看名字这是用来处理Vsync到APP的连接的,它也是在SurfaceFlinger的init中创建的,我们来大概看看它的创建:

void SurfaceFlinger::init() {
	......
	mScheduler =
            getFactory().createScheduler([this](bool enabled) { setPrimaryVsyncEnabled(enabled); },
                                         mRefreshRateConfigs);
    auto resyncCallback =
            mScheduler->makeResyncCallback(std::bind(&SurfaceFlinger::getVsyncPeriod, this));

    mAppConnectionHandle =
            mScheduler->createConnection("app", mPhaseOffsets->getCurrentAppOffset(),
                                         resyncCallback,
                                         impl::EventThread::InterceptVSyncsCallback());
	......	
}

调用mScheduler的createConnection函数创建的,它的名字是"app",

createConnection

sp<Scheduler::ConnectionHandle> Scheduler::createConnection(
        const char* connectionName, int64_t phaseOffsetNs, ResyncCallback resyncCallback,
        impl::EventThread::InterceptVSyncsCallback interceptCallback) {
    //id从0累加
    const int64_t id = sNextId++;
    ALOGV("Creating a connection handle with ID: %" PRId64 "\n", id);
     //创建对应connectionName名字的EventThread
    std::unique_ptr<EventThread> eventThread =
            makeEventThread(connectionName, mPrimaryDispSync.get(), phaseOffsetNs,
                            std::move(interceptCallback));
    //创建EventThreadConnection
    auto eventThreadConnection =
            createConnectionInternal(eventThread.get(), std::move(resyncCallback));
    //创建ConnectionHandle,与id对应
    mConnections.emplace(id,
                         std::make_unique<Connection>(new ConnectionHandle(id),
                                                      eventThreadConnection,
                                                      std::move(eventThread)));
    //返回”app“的ConnectionHandle
    return mConnections[id]->handle;
}

createConnection这个函数在SurfaceFlinger中调用了两次,一次是创建"app"的Connection,一次是创建"sf"的Connection,我们可以理解为创建两套连接,一套给app使用,一套个surfaceFlinger使用,两套连接的用connectionName以及id进行标识,(id为0,connectionName等于”app“的)与(id为1,connectionName等于”sf“的)

createConnection函数根据connectionName创建EventThread,根据EventThread创建EventThreadConnection,然后创建ConnectionHandle,根据ConnectionHandle,EventThreadConnection,EventThread最终创建Connection,并以id为key,Connection为value加入到mConnections的map中,最终返回”app“的ConnectionHandle,这些类的创建肯定初始化了很多重要过程,我们这里不去一一分析,只要知道后面用的时候有创建过这些类

mAppConnectionHandle的创建过程我们大致看了下,知道了这是一个”app“的ConnectionHandle,

接着我们继续看:mScheduler->createDisplayEventConnection(handle, std::move(resyncCallback));

sp<IDisplayEventConnection> Scheduler::createDisplayEventConnection(
        const sp<Scheduler::ConnectionHandle>& handle, ResyncCallback resyncCallback) {
    RETURN_VALUE_IF_INVALID(nullptr);
    return createConnectionInternal(mConnections[handle->id]->thread.get(),
                                    std::move(resyncCallback));
}

调用createConnectionInternal,handle->id用于标识这套连接是app还是surfaceFlinger

createConnectionInternal

sp<EventThreadConnection> Scheduler::createConnectionInternal(EventThread* eventThread,
                                                              ResyncCallback&& resyncCallback) {
    return eventThread->createEventConnection(std::move(resyncCallback));
}

调用EventThread的createEventConnection函数

createEventConnection

sp<EventThreadConnection> EventThread::createEventConnection(ResyncCallback resyncCallback) const {
    return new EventThreadConnection(const_cast<EventThread*>(this), std::move(resyncCallback));
}

创建了一个EventThreadConnection对象,看下它的构造函数

EventThreadConnection::EventThreadConnection(EventThread* eventThread,
                                             ResyncCallback resyncCallback)
      : resyncCallback(std::move(resyncCallback)),
        mEventThread(eventThread),
        mChannel(gui::BitTube::DefaultSize) {}

构造函数中最重要的就是创建了mChannel,mChannel是gui::BitTube类型
接着看gui::BitTube的构造函数:这里传递的DefaultSize为4kb,
定义在BitTube.h中:
// creates a BitTube with a default (4KB) send buffer
struct DefaultSizeType {};
static constexpr DefaultSizeType DefaultSize{};


BitTube::BitTube(size_t bufsize) {
    init(bufsize, bufsize);
}

init

void BitTube::init(size_t rcvbuf, size_t sndbuf) {
    int sockets[2];
    if (socketpair(AF_UNIX, SOCK_SEQPACKET, 0, sockets) == 0) {
        size_t size = DEFAULT_SOCKET_BUFFER_SIZE;
        setsockopt(sockets[0], SOL_SOCKET, SO_RCVBUF, &rcvbuf, sizeof(rcvbuf));
        setsockopt(sockets[1], SOL_SOCKET, SO_SNDBUF, &sndbuf, sizeof(sndbuf));
        // since we don't use the "return channel", we keep it small...
        setsockopt(sockets[0], SOL_SOCKET, SO_SNDBUF, &size, sizeof(size));
        setsockopt(sockets[1], SOL_SOCKET, SO_RCVBUF, &size, sizeof(size));
        fcntl(sockets[0], F_SETFL, O_NONBLOCK);
        fcntl(sockets[1], F_SETFL, O_NONBLOCK);
        mReceiveFd.reset(sockets[0]);
        mSendFd.reset(sockets[1]);
    } else {
        mReceiveFd.reset();
        ALOGE("BitTube: pipe creation failed (%s)", strerror(errno));
    }
}

init函数主要是通过socketpair函数创建一对socket

socketpair()函数用于创建一对无名的、相互连接的socket
如果成功,则返回0,创建好的socket分别是sv[0]和sv[1];否则返回-1

  1. 这对socket可以用于全双工通信,每一个socket既可以读也可以写。例如,可以往sv[0]中写,从sv[1]中读,或者从sv[1]中写,从sv[0]中读。
  2. 如果往一个socket(如sv[0])中写入后,再从该socket读时会阻塞,只能在另一个socket中(sv[1])上读成功;
  3. 读、写操作可以位于同一个进程,也可以分别位于不同的进程。

通过socketpair创建好了一对socket之后,再通过setsockopt对socket进行设置,再调用fcntl函数针对socket描述符提供控制,不用管具体干嘛的,
最后我们看mReceiveFd.reset(sockets[0]),mSendFd.reset(sockets[1]);建立Fd与socket的关联,很明显这一对sockets一个用来接受消息,一个用来发送消息,到这里我们可以猜测,Vsync到来的时候通过mSendFd写入消息,然后app监听mReceiveFd接受消息,就完成了app对Vsync的接收,需要注意一点,此时的mReceiveFd依然还在SurfaceFlinger进程,app端要使用肯定是需要回传回去的,但是步骤2的调用已经结束,没看到那里返回mReceiveFd的,那么我们接着往后分析看看

我们总结一下步骤2:
mEventConnection = sf->createDisplayEventConnection(vsyncSource);
步骤2其实就是根据vsyncSource,得到此Vsync请求来自app,然后创建一套app的连接,其实最终就是创建一对socket用来进行进程间通信,类似的还有Input系统,也是通过一对socket来连接app和InputDispatcher

我们接着之前分了四个步骤的代码进行分析:

DisplayEventReceiver::DisplayEventReceiver(ISurfaceComposer::VsyncSource vsyncSource) {
    //步骤1   获取SurfaceFlinger服务
    sp<ISurfaceComposer> sf(ComposerService::getComposerService());
    if (sf != nullptr) {
        //步骤2  创建一对socket连接
        mEventConnection = sf->createDisplayEventConnection(vsyncSource);
        if (mEventConnection != nullptr) {
            //步骤3  获得gui::BitTube对象
            mDataChannel = std::make_unique<gui::BitTube>();
               //步骤4
            mEventConnection->stealReceiveChannel(mDataChannel.get());
        }
    }
}

我们已经分析完了步骤1,步骤2,步骤3比较简单,就是获得gui::BitTube对象,来看步骤4:
mEventConnection->stealReceiveChannel(mDataChannel.get());

我们步骤2分析过mEventConnection是从SurfaceFlinger返回的Binder Bp端,BpDisplayEventConnection,那么先看看Bp端的调用

stealReceiveChannel

class BpDisplayEventConnection : public SafeBpInterface<IDisplayEventConnection> {
public:
    ......
    status_t stealReceiveChannel(gui::BitTube* outChannel) override {
        return callRemote<decltype(
                &IDisplayEventConnection::stealReceiveChannel)>(Tag::STEAL_RECEIVE_CHANNEL,
                                                                outChannel);
    }
 }

这个方法里面的语法我不太清楚,但既然是Binder通信,最终一定是调到BnDisplayEventConnection中去了,Tag为STEAL_RECEIVE_CHANNEL,类似Binder的code,用来找对应方法的,我们来看看Bn端的具体实现:

status_t EventThreadConnection::stealReceiveChannel(gui::BitTube* outChannel) {
    outChannel->setReceiveFd(mChannel.moveReceiveFd());
    return NO_ERROR;
}

mChannel保存的是gui::BitTube

base::unique_fd BitTube::moveReceiveFd() {
    return std::move(mReceiveFd);
}
void BitTube::setReceiveFd(base::unique_fd&& receiveFd) {
    mReceiveFd = std::move(receiveFd);
}

所以stealReceiveChannel就等价于
outChannel.mReceiveFd = mChannel.mReceiveFd
这什么意思呢?其实就相当于将步骤2在surfaceFlinger进程中创建的mReceiveFd传递到app进程中去,app进程有了mReceiveFd,surfaceFlinger进程有了mSendFd就能够实现通信了

到此我们已经分析完了DisplayEventReceiver构造函数中的四个步骤,把代码再贴出来看下

DisplayEventReceiver::DisplayEventReceiver(ISurfaceComposer::VsyncSource vsyncSource) {
    //步骤1
    sp<ISurfaceComposer> sf(ComposerService::getComposerService());
    if (sf != nullptr) {
        //步骤2
        mEventConnection = sf->createDisplayEventConnection(vsyncSource);
        if (mEventConnection != nullptr) {
            //步骤3
            mDataChannel = std::make_unique<gui::BitTube>();
               //步骤4
            mEventConnection->stealReceiveChannel(mDataChannel.get());
        }
    }
}

我们对这四个步骤进行总结:

  1. 获取surfaceFlinger的Bp端,以便与surfaceFlinger进行Binder通信
  2. 获取EventThread::EventThreadConnection的Bp端,在创建EventThread::EventThreadConnection又创建了gui::BitTube对象,在gui::BitTube的init函数中创建了一对socket,并建立mReceiveFd,mSendFd和socket的关联,以便在监听mReceiveFd时能够收到mSendFd写入的消息
  3. 在app端创建一个gui::BitTube
  4. 通过stealReceiveChannel函数将app端的gui::BitTube传递到surfaceFlinger进程,目的是将surfaceFlinger进程的mReceiveFd传递到app端

到现在为止我们仅仅分析了最开始的nativeInit函数的步骤1

static jlong nativeInit(JNIEnv* env, jclass clazz, jobject receiverWeak,
     ......
    //步骤1
    sp<NativeDisplayEventReceiver> receiver = new NativeDisplayEventReceiver(env,
            receiverWeak, messageQueue, vsyncSource);
    //步骤2
    status_t status = receiver->initialize();
    ......
    return reinterpret_cast<jlong>(receiver.get());
}

我们接这来看看步骤2:receiver->initialize,它的实现在DisplayEventDispatcher中:

initialize

status_t DisplayEventDispatcher::initialize() {
    //检查mReceiver是否异常
    status_t result = mReceiver.initCheck();
    ...
    int rc = mLooper->addFd(mReceiver.getFd(), 0, Looper::EVENT_INPUT,
            this, NULL);
    if (rc < 0) {
        return UNKNOWN_ERROR;
    }
    return OK;
}

这个函数就比较简单了,调用Looper的addFd将我们前面得到的mReceiveFd添加到Handler进行监听,关于Handler的native层的消息机制可以参考我以前分析过的AndroidQ Handler消息机制(native层),我们这里就大概说一下,Handler消息机制可以处理三种消息,java层msg,native层msg,以及通过addFd创建的request,request中包含监听的fd以及收到消息时的回调handleEvent

所以这里监听了mReceiveFd之后,当mSendFd写入数据时就能收到消息,并回调DisplayEventDispatcher的handleEvent函数

限于篇幅,这篇文章就分析到这里,主要就是分析了nativeInit这一个native的函数

你可能感兴趣的:(Android源码分析)