上一篇文章我们分析了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的构造方法中初始化的
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
/*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函数
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);
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);
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
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",
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
sp<EventThreadConnection> Scheduler::createConnectionInternal(EventThread* eventThread,
ResyncCallback&& resyncCallback) {
return eventThread->createEventConnection(std::move(resyncCallback));
}
调用EventThread的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);
}
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
通过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端的调用
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());
}
}
}
我们对这四个步骤进行总结:
到现在为止我们仅仅分析了最开始的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中:
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的函数