关于Choreographer的知识,这里分作3部分来解析:
- Choreographer的初始化
- View绘制请求
- View绘制
先放一张总流程图,如下:
第一部分 Choreographer的初始化
//ViewRootImpl.java
public ViewRootImpl(Context context, Display display) {
...
mChoreographer = Choreographer.getInstance();
...
}
初始化从ViewRootImpl开始,在创建ViewRootImpl的时候会初始化Choreography。
//Choreographer.java
public static Choreographer getInstance() {
return sThreadInstance.get();
}
//Choreographer.java
private static final ThreadLocal<Choreographer> sThreadInstance =
new ThreadLocal<Choreographer>() {
@Override
protected Choreographer initialValue() {
Looper looper = Looper.myLooper();
if (looper == null) {
throw new IllegalStateException("The current thread must have a looper!");
}
Choreographer choreographer = new Choreographer(looper, VSYNC_SOURCE_APP);
if (looper == Looper.getMainLooper()) {
mMainInstance = choreographer;
}
return choreographer;
}
};
这里有几点需要注意:
- ThreadLocal,表示Choreography是线程私有的,也就是每一个ViewRoot都会私有一个Choreography实例,二者是一一对应的
- VSYNC_SOURCE_APP,这个是用来与Vsync源建立连接的,其定义在ISurfaceComposer.h中,目前有两类,一个是app,一个是sf(SurfaceFlinger),他们会分别监听响应VSync信号,后面还会讲到
- looper,发起创建Choreography的线程必须有自己的Looper,因为后续VSync信号来临时需要通过handler的方式发给各自的对应的thread
顺便可以了解一下如下几个概念的对应关系,对这些概念有个大概的轮廓印象:
//Choreographer.java
private Choreographer(Looper looper, int vsyncSource) {
mLooper = looper;
mHandler = new FrameHandler(looper);
mDisplayEventReceiver = USE_VSYNC
? new FrameDisplayEventReceiver(looper, vsyncSource)
: null;
mLastFrameTimeNanos = Long.MIN_VALUE;
mFrameIntervalNanos = (long)(1000000000 / getRefreshRate());
mCallbackQueues = new CallbackQueue[CALLBACK_LAST + 1];
for (int i = 0; i <= CALLBACK_LAST; i++) {
mCallbackQueues[i] = new CallbackQueue();
}
}
note:
USE_VSYNC: 默认为true,可以通过设置系统属性debug.choreographer.vsync为false来关闭,只用于调试
mFrameIntervalNanos: 其实就是VSync周期时间,单位纳秒。
mCallbackQueues:这个是记录回调的,Vsync信号来临时,会通过这个回调去通知相应目标,后续在设置回调的地方会详细描述。
FrameDisplayEventReceiver:这个是初始化比较重要的一环,初始化DisplayEventReceiver来监听底层VSync信号,FrameDisplayEventReceiver是Choreography内部类,继承自DisplayEventReceiver,所以这里实际上是调用的DisplayEventReceiver的构造函数。
//DisplayEventReceiver.java
public DisplayEventReceiver(Looper looper, int vsyncSource) {
mMessageQueue = looper.getQueue();
mReceiverPtr = nativeInit(new WeakReference<DisplayEventReceiver>(this), mMessageQueue,
vsyncSource);
}
//android_view_DisplayEventReceiver.cpp
static jlong nativeInit(JNIEnv* env, jclass clazz, jobject receiverWeak,
jobject messageQueueObj, jint vsyncSource) {
sp<NativeDisplayEventReceiver> receiver = new NativeDisplayEventReceiver(env,
receiverWeak, messageQueue, vsyncSource);
status_t status = receiver->initialize();
return reinterpret_cast<jlong>(receiver.get());
}
//android_view_DisplayEventReceiver.cpp
class NativeDisplayEventReceiver : public DisplayEventDispatcher {}继承关系
NativeDisplayEventReceiver::NativeDisplayEventReceiver(JNIEnv* env,
jobject receiverWeak, const sp<MessageQueue>& messageQueue, jint vsyncSource) :
DisplayEventDispatcher(messageQueue->getLooper(),
static_cast<ISurfaceComposer::VsyncSource>(vsyncSource)) {
}
note:
- DisplayEventReceiver.java会通过native调用最终去初始化native端的DisplayEventReceiver,需要注意mReceiverPtr,这个变量是nativeInit返回的,为jlong类型,实际上它是NativeDisplayEventReceiver对象的指针地址,当需要调用native方法的时候把这个long型传递给native,native就可以根据这个值找到对应的对象。后续还会遇到类似的设计,比如SurfaceControl的初始化,Surface的初始化等都会通过这样的方式来持有native端的对象
- NativeDisplayEventReceiver构造方法只是调用构造DisplayEventDispatcher,这里主要有两个动作,一是构造DisplayEventDispatcher,一是调用DisplayEventDispatcher的initialize()
构造DisplayEventDispatcher
//DisplayEventDispatcher.cpp
DisplayEventDispatcher::DisplayEventDispatcher(const sp<Looper>& looper,
ISurfaceComposer::VsyncSource vsyncSource) :
mLooper(looper), mReceiver(vsyncSource), mWaitingForVsync(false) {
ALOGV("dispatcher %p ~ Initializing display event dispatcher.", this);
}
mLooper就是java层一路传进来的
这里主要看看mReceiver(vsyncSource),这个vsyncSource就是前面传来的VSYNC_SOURCE_APP,mReceiver为DisplayEventReceiver类型变量。
//DisplayEventReceiver.cpp
DisplayEventReceiver::DisplayEventReceiver(ISurfaceComposer::VsyncSource vsyncSource) {
sp<ISurfaceComposer> sf(ComposerService::getComposerService());
if (sf != nullptr) {
mEventConnection = sf->createDisplayEventConnection(vsyncSource);
if (mEventConnection != nullptr) {
mDataChannel = std::make_unique<gui::BitTube>();
mEventConnection->stealReceiveChannel(mDataChannel.get());
}
}
}
需要注意以下几点:
- 创建DisplayEventConnection,这里通过ISurfaceComposer来创建,而ComposerService实际上是对SurfaceFlinger的Binder代理的封装,所以这里实际上调用的是SF的方法createDisplayEventConnection,SF通过scheduler最终调用到EventThread的createEventConnection,关于SF的相关信息在讲解Surface的时候再详述
- BitTube:可以简单的理解为一个文件节点,把这个节点绑定给Looper之后,一端写入数据,另一端就可以读取,就像MessageQueue写入数据触发Looper读取是完全类似的。感兴趣的可以自行研究。
- stealReceiveChannel:把这个节点设置为通信通道
//EventThread.cpp
sp<EventThreadConnection> EventThread::createEventConnection(ResyncCallback resyncCallback) const {
return new EventThreadConnection(const_cast<EventThread*>(this), std::move(resyncCallback));
}
这里构造EventThreadConnection,注意这里有个隐藏对象,那就是this,这个this代表的是EventThread,它的初始化是由SurfaceFlinger来完成的,这里先不研究。
//EventThread.cpp
EventThreadConnection::EventThreadConnection(EventThread* eventThread,
ResyncCallback resyncCallback)
: resyncCallback(std::move(resyncCallback)),
mEventThread(eventThread),
mChannel(gui::BitTube::DefaultSize) {}
这个主要功能是把EventThread的引用扔给EventThreadConnection。
完成connection建立之后,实际上也是第一次引用该对象,所以会直接调用EventThreadConnection::onFirstRef()
//EventThread.cpp
void EventThreadConnection::onFirstRef() {
// NOTE: mEventThread doesn't hold a strong reference on us
mEventThread->registerDisplayEventConnection(this);
}
status_t EventThread::registerDisplayEventConnection(const sp<EventThreadConnection>& connection) {
std::lock_guard<std::mutex> lock(mMutex);
// this should never happen
auto it = std::find(mDisplayEventConnections.cbegin(),
mDisplayEventConnections.cend(), connection);
if (it != mDisplayEventConnections.cend()) {
ALOGW("DisplayEventConnection %p already exists", connection.get());
mCondition.notify_all();
return ALREADY_EXISTS;
}
mDisplayEventConnections.push_back(connection);
mCondition.notify_all();
return NO_ERROR;
}
检查新建立的connection是否已经存在,如果不存在则加入到mDisplayEventConnections中。
下面的类图展示了连接建立完成之后的各个类之间的关系:
调用DisplayEventDispatcher的initialize()
//DisplayEventDispatcher.cpp
status_t DisplayEventDispatcher::initialize() {
int rc = mLooper->addFd(mReceiver.getFd(), 0, Looper::EVENT_INPUT,
this, NULL);
}
其实就一个动作,把DisplayEventReceiver创建的BitTube节点添加给mLooper,这样mLooper就开始循环读取该节点的消息了,把this设置为该Looper的回调,也就是handleEvent,但有消息来的时候,就会回调handleEvent。
到这里connection连接就建立完成了,回调也配置好了,下面来一张图阐述这部分的流程,图中同时包含了EventThread的初始化:
第二部分 EventThread初始化
从SurfaceFlinger的init开始,SF作为系统服务,它是在系统启动的时候启动的,详细情况在介绍SF的时候再说。
//SurfaceFlinger.cpp
void SurfaceFlinger::init() {
// start the EventThread
mScheduler =
getFactory().createScheduler([this](bool enabled) { setVsyncEnabled(enabled); },
mRefreshRateConfigs);
mAppConnectionHandle =
mScheduler->createConnection("app", mPhaseOffsets->getCurrentAppOffset(),
resyncCallback,
impl::EventThread::InterceptVSyncsCallback());
mSfConnectionHandle = mScheduler->createConnection("sf", mPhaseOffsets->getCurrentSfOffset(),
resyncCallback, [this](nsecs_t timestamp) {
mInterceptor->saveVSyncEvent(timestamp);
});
}
这里有两项工作,一是通过Factory构建Scheduler,二是通过Scheduler创建到EventThread的connection,分别创建了两条连接“app”和“sf”。
1. 构建Scheduler
//Scheduler.cpp
Scheduler::Scheduler(impl::EventControlThread::SetVSyncEnabledFunction function,
const scheduler::RefreshRateConfigs& refreshRateConfig) {
// Note: We create a local temporary with the real DispSync implementation
// type temporarily so we can initialize it with the configured values,
// before storing it for more generic use using the interface type.
auto primaryDispSync = std::make_unique<impl::DispSync>("SchedulerDispSync");
primaryDispSync->init(mHasSyncFramework, mDispSyncPresentTimeOffset);
mPrimaryDispSync = std::move(primaryDispSync);
}
两件事
- 定义mPrimaryDispSync指向DispSync,执行构造函数
- 调用init初始化DispSync
//DispSync.cpp
DispSync::DispSync(const char* name) : mName(name), mRefreshSkipCount(0) {
mThread = new DispSyncThread(name, mTraceDetailedInfo);
}
void DispSync::init(bool hasSyncFramework, int64_t dispSyncPresentTimeOffset) {
mThread->run("DispSync", PRIORITY_URGENT_DISPLAY + PRIORITY_MORE_FAVORABLE);
reset();
beginResync();
}
可以看到这里主要就是创建了DispSyncThread,并启动开始循环,接着看看循环体:
//DispSync.cpp
virtual bool threadLoop() {
while (true) {
std::vector<CallbackInvocation> callbackInvocations;
{
targetTime = computeNextEventTimeLocked(now);
bool isWakeup = false;
if (now < targetTime) {
if (targetTime == INT64_MAX) {
ALOGV("[%s] Waiting forever", mName);
err = mCond.wait(mMutex);
} else {
ALOGV("[%s] Waiting until %" PRId64, mName, ns2us(targetTime));
err = mCond.waitRelative(mMutex, targetTime - now);
}
if (err == TIMED_OUT) {
isWakeup = true;
} else if (err != NO_ERROR) {
ALOGE("error waiting for next event: %s (%d)", strerror(-err), err);
return false;
}
}
callbackInvocations = gatherCallbackInvocationsLocked(now);
}
if (callbackInvocations.size() > 0) {
fireCallbackInvocations(callbackInvocations);
}
}
}
三件事
- 计算Event触发时间
- 获取event监听对象
- 如果存在监听者,回调监听者注册的回调函数onDispSyncEvent,关于这个回调后面会有类图展示
这里只需要知道周期性触发并回调即可。
2. 构建connection
//Scheduler.cpp
sp<Scheduler::ConnectionHandle> Scheduler::createConnection(
const char* connectionName, int64_t phaseOffsetNs, ResyncCallback resyncCallback,
impl::EventThread::InterceptVSyncsCallback interceptCallback) {
const int64_t id = sNextId++;
std::unique_ptr<EventThread> eventThread =
makeEventThread(connectionName, mPrimaryDispSync.get(), phaseOffsetNs,
std::move(interceptCallback));
auto eventThreadConnection =
createConnectionInternal(eventThread.get(), std::move(resyncCallback));
mConnections.emplace(id,
std::make_unique<Connection>(new ConnectionHandle(id),
eventThreadConnection,
std::move(eventThread)));
return mConnections[id]->handle;
}
- sNextId : connection id,标志新建立的connection
- 构建EventThread
- 与EventThread建立连接
- 组建Connection,然后加入到mConnections,返回其对应的handle
构建EventThread
//Scheduler.cpp
std::unique_ptr<EventThread> Scheduler::makeEventThread(
const char* connectionName, DispSync* dispSync, int64_t phaseOffsetNs,
impl::EventThread::InterceptVSyncsCallback interceptCallback) {
std::unique_ptr<VSyncSource> eventThreadSource =
std::make_unique<DispSyncSource>(dispSync, phaseOffsetNs, true, connectionName);
return std::make_unique<impl::EventThread>(std::move(eventThreadSource),
std::move(interceptCallback), connectionName);
}
创建DispSyncSource,它将作为EventThread与DispSync通信的桥梁
创建EventThread
//EventThread.cpp
EventThread::EventThread(VSyncSource* src, std::unique_ptr<VSyncSource> uniqueSrc,
InterceptVSyncsCallback interceptVSyncsCallback, const char* threadName)
: mVSyncSource(src),
mVSyncSourceUnique(std::move(uniqueSrc)),
mInterceptVSyncsCallback(std::move(interceptVSyncsCallback)),
mThreadName(threadName) {
mVSyncSource->setCallback(this);
mThread = std::thread([this]() NO_THREAD_SAFETY_ANALYSIS {
std::unique_lock<std::mutex> lock(mMutex);
threadMain(lock);
});
}
三件事
- 赋值mVSyncSource=DispSyncSource,并设置callback为this,EventThread继承了VSyncSource::Callback,所以DispSyncSource回调将会调用到onVSyncEvent
- 设置name为“app”
-
创建thread并在thread中运行threadMain,重点关注threadMain