界面显示_视图Choreographer控制
Choreographer_舞蹈编导
为什么叫舞蹈编导,因为舞蹈是由节奏的,节奏是每个点位动作的快慢控制,跳舞时节奏很重要,编舞者控制节奏。视图刷新也是如此,不是说你想刷就能刷,一切要按照底层信号要求的节奏来。
理解屏幕刷新频率
刷新频率:每秒钟刷新屏幕的次数,从缓存中取出每一帧,显示到屏幕上的速度。
帧率:GPU/CPU生成每一帧画面图像,存入缓存中的速度。
一般情况下帧率是大于刷新频率的,每个设备的刷新频率固定,与硬件相关,若帧率是刷新率的两倍,两张图像画面,只能有一个现实到屏幕上,也就是说生产画面的速度要大于显示画面的速度。典型的生产者-消费者模式。
屏幕刷新过程:从左到右刷新一行,然后垂直刷新,再一行..,直到屏幕刷新完毕。每一次刷新,都是这一个过程,刷新一次后,中间有一个期间,刷新率太高,每秒60帧左右,人眼无法感知。
tearing:若帧率大于刷新率,会导致在刷新前一帧还未开始时,缓存已经被新一帧覆盖一部分,那么在刷新前一帧时,现显示的一部分是新一帧内容。会导致画面前后帧上下重叠。这种情况技术上称之tearing,画面撕裂的意思。
解决方案:增加缓存到两个缓存,CPU生成帧存入一个缓存A,屏幕取出帧存入另一个缓存B,解决了一个缓存导致生产者与消费者不同步的问题。增加Vsync同步信号,负责调度将A缓存拷贝到B缓存,显示取出的就是一个完整帧的画面。Vsync信号在一帧刷新完的中间期间产生,A到B的复制(交换地址即可),进入下一次刷新,并通知生产者gpu/cpu继续生产帧,只有收到Vsync信号,生产者才会生产帧。因此,可使帧率与刷新率保持同步,消耗一次才生成一次。
掉帧:若Vsync信号发出时,A缓存正在被生产者锁住生产,gpu绘制生产帧时间超过信号发出时刻一点,此时不会复制。导致B缓存仍是老帧,下一次周期与前一次刷新相同的帧。当gpu生产结束后,此时刷新老数据的刷新周期中,还没有Vsync信号,则gpu空闲。
掉帧解决方案:再增加一个缓存到三个缓存。当有缓存锁住时复制他前面的上一次被锁住的另一个缓存。
Android平台提供两种信号,一种是硬件信号,另一种是软件信号,由SurfaceFlinger进程的一个线程定时发出,硬件信号由硬件发出。
App进程若要通过gpu实现图像绘制,需要在接收到Vsync信号的条件下进行,因此,App进程访问SurfaceFlinger进程获取这个信号,再进行gpu绘制。
Choreographer就是负责获取Vsync同步信号并控制App线程(主要是主线程绘图)完成图像绘制的类。
Choreographer单例
在Android系统中主要是主线程负责UI绘制,其他线程也可以绘制,如SurfaceView,这里以主线程UI绘制进行介绍。
每个线程中保存一个Choreographer实例对象。
Choreographer#sThreadInstance静态对象。
private static final ThreadLocal<Choreographer> sThreadInstance =
new ThreadLocal<Choreographer>() {
@Override
protected Choreographer initialValue() {
Looper looper = Looper.myLooper();
if (looper == null) {
//抛出异常。
}
return new Choreographer(looper);
}
};
线程本地存储ThreadLocal变量,Choreographer类型,在线程中初始化变量时,创建Choreographer对象,绑定主线程Looper。
每个窗体旗下ViewRootImpl均使用同一个Choregrapher对象,它承担控制大部分视图绘制节奏的工作。
安排一次遍历
一次遍历,就是完成一个树形视图的绘制过程,遍历视图树的每一个节点。
ViewRootImpl#scheduleTraversals方法。
void scheduleTraversals() {
if (!mTraversalScheduled) {
mTraversalScheduled = true;
mTraversalBarrier = mHandler.getLooper().getQueue().postSyncBarrier();
mChoreographer.postCallback(
Choreographer.CALLBACK_TRAVERSAL, mTraversalRunnable, null);
...
}
}
每当ViewRootImpl安排一次遍历scheduleTraversals,设置标志位mTraversalScheduled,防止多次安排。发送同步栅栏。当执行遍历doTraversal或主动取消遍历unscheduleTraversals时,关掉标志位。取消同步栅栏。
委托Choreographer安排遍历,请求信号。
Choreographer#postCallback分析
Choreographer#postCallbackDelayedInternal方法。
private void postCallbackDelayedInternal(int callbackType,
Object action, Object token, long delayMillis) {
synchronized (mLock) {
final long now = SystemClock.uptimeMillis();
final long dueTime = now + delayMillis;
mCallbackQueues[callbackType].addCallbackLocked(dueTime, action, token);
if (dueTime <= now) {//没有延迟,以当前时间安排帧。
scheduleFrameLocked(now);
} else {
Message msg = mHandler.obtainMessage(MSG_DO_SCHEDULE_CALLBACK, action);
msg.arg1 = callbackType;
msg.setAsynchronous(true);
mHandler.sendMessageAtTime(msg, dueTime);
}
}
}
Choreographer#postCallback的功能是向回调请求数组中存入一个对应类型的记录,该纪录封装回调任务,当前时间,等待信号安排一帧绘制。CallbackQueue数组,数组元素是CallbackQueue对象,内部包含指向CallbackRecord链表的头指针。四种callbackType类型:CALLBACK_INPUT、CALLBACK_ANIMATION、CALLBACK_TRAVERSAL、CALLBACK_COMMIT。每一种callbackType类型代表数组的一个索引。

CallbackQueue#addCallbackLocked方法,创建一个CallbackRecord对象,封装dueTime执行时间(当前时间+延迟),任务action和token。将CallbackRecord插入链表,按照dueTime时间排序决定插入位置,dueTime小的位于链表的前面。
这里只关注CALLBACK_TRAVERSAL类型与回调任务TraversalRunnable,当收到Vsync信号时,触发执行doTraversal方法。
若没有延迟,立即安排,触发Choreographer#scheduleFrameLocked方法。若有延迟,等待delayMillis时间,在特定时刻dueTime利用Choreographer内部FrameHandler发送消息。
Choreographer#FrameHandler#handleMessage方法
@Override
public void handleMessage(Message msg) {
switch (msg.what) {
...
case MSG_DO_SCHEDULE_CALLBACK:
doScheduleCallback(msg.arg1);
break;
}
}
FrameHandler处理延迟发送的CALLBACK,触发doScheduleCallback方法。
Choreographer#doScheduleCallback方法。
void doScheduleCallback(int callbackType) {
synchronized (mLock) {
if (!mFrameScheduled) {
final long now = SystemClock.uptimeMillis();
if (mCallbackQueues[callbackType].hasDueCallbacksLocked(now)) {
scheduleFrameLocked(now);
}
}
}
}
有延迟时,当到达时间dueTime,在handleMessage方法开始执行,最终实现一次安排,与没有延迟时一样,触发Choreographer#scheduleFrameLocked方法。
注意,在经过一段时间的延迟,中间有不确定性,增加两个条件判断。
- 若mFrameScheduled标志,表示此时已经有过一次安排,请求一次有回复在doFrame处重置标志。这时,不再安排。
- 获取当前时间now,当链表头结点的dueTime比now大,表示当时以(now + delayMillis)插入的CallbackRecord节点已经不在链表中了,否则在(now + delayMillis)时刻执行获取的当前时间一定会大于或等于now,链表每个元素的dueTime都大于now,或者头节点是空,这种情况下不再安排。
Choreographer#scheduleFrameLocked分析
Choreographer#scheduleFrameLocked方法
private void scheduleFrameLocked(long now) {
if (!mFrameScheduled) {
mFrameScheduled = true;
if (USE_VSYNC) {
if (isRunningOnLooperThreadLocked()) {
scheduleVsyncLocked();
} else {
Message msg = mHandler.obtainMessage(MSG_DO_SCHEDULE_VSYNC);
msg.setAsynchronous(true);
mHandler.sendMessageAtFrontOfQueue(msg);
}
} else {
final long nextFrameTime = Math.max(
mLastFrameTimeNanos / TimeUtils.NANOS_PER_MS + sFrameDelay, now);
...
Message msg = mHandler.obtainMessage(MSG_DO_FRAME);
msg.setAsynchronous(true);
mHandler.sendMessageAtTime(msg, nextFrameTime);
}
}
}
now参数是执行该方法前获取的当前时间。执行时设置mFrameScheduled标志,底层回调后才会重置此标志。
USE_VSYNC默认是true,若当前线程Looper与Choreographer的Looper一致,即与Choreographer所在线程一样,触发Choreographer#scheduleVsyncLocked方法,通过注册的接收器JNI访问底层请求垂直同步信号。
若当前线程与Choreographer所在线程不同,通过FrameHandler发送消息,FrameHandler负责处理Choreographer线程事务消息。
@Override
public void handleMessage(Message msg) {
switch (msg.what) {
...
case MSG_DO_SCHEDULE_VSYNC:
doScheduleVsync();
break;
}
}
在doScheduleVsync方法中触发Choreographer#scheduleVsyncLocked方法。
Choreographer#postCallback流程图如下所示。

显示事件接收器
Java层DisplayEventReceiver分析
Choreographer#scheduleVsyncLocked方法
private void scheduleVsyncLocked() {
mDisplayEventReceiver.scheduleVsync();
}
Choreographer#mDisplayEventReceiver是FrameDisplayEventReceiver类型,它在Choreographer构造方法初始化,继承DisplayEventReceiver。
Java#DisplayEventReceiver构造方法。
public DisplayEventReceiver(Looper looper) {
..//Looper是空抛异常
mMessageQueue = looper.getQueue();
mReceiverPtr = nativeInit(new WeakReference<DisplayEventReceiver>(this), mMessageQueue);
}
DisplayEventReceiver创建时,绑定Choreographer线程的消息队列。JNI#nativeInit方法初始化底层对象,创建一个DisplayEventReceiver的弱引用,与消息队列一起,传入底层。
JNI#nativeInit方法
static jlong nativeInit(JNIEnv* env, jclass clazz, jobject receiverWeak,
jobject messageQueueObj) {
sp<MessageQueue> messageQueue = android_os_MessageQueue_getMessageQueue(env, messageQueueObj);
...
sp<NativeDisplayEventReceiver> receiver = new NativeDisplayEventReceiver(env,
receiverWeak, messageQueue);
status_t status = receiver->initialize();
...
receiver->incStrong(gDisplayEventReceiverClassInfo.clazz);
return reinterpret_cast<jlong>(receiver.get());
}
nativeInit方法主要工作
- 根据Java层MQ获取Native层消息队列,Choreographer线程消息队列。
- 创建JNI层接收器NativeDisplayEventReceiver,它继承LooperCallback,将mReceiverPtr指针返回给Java层DisplayEventReceiver对象。封装Java层弱引用receiverWeak、Native层消息队列、Native层DisplayEventReceiver对象。
NativeDisplayEventReceiver#initialize方法。
status_t NativeDisplayEventReceiver::initialize() {
status_t result = mReceiver.initCheck();
...
int rc = mMessageQueue->getLooper()->addFd(mReceiver.getFd(), 0, Looper::EVENT_INPUT,
this, NULL);
return OK;
}
- 向Choreographer线程Looper监听Native层对象DisplayEventReceiver中BitTube的mReceiverFd描述符。监听一旦接收到消息,在Looper中将触发handleEvent回调方法。
Java层DisplayEventReceiver通过JNI调用实现帧画面的显示控制,主要三个任务:底层初始化(nativeInit),发起请求(scheduleVsync),实现回调(dispatchVsync)。
Native层DisplayEventReceiver分析
Native#DisplayEventReceive构造方法
DisplayEventReceiver::DisplayEventReceiver() {
sp<ISurfaceComposer> sf(ComposerService::getComposerService());
if (sf != NULL) {
mEventConnection = sf->createDisplayEventConnection();
if (mEventConnection != NULL) {
mDataChannel = mEventConnection->getDataChannel();
}
}
}
在DisplayEventReceiver构造方法,初始化两个重要对象的指针。
- mEventConnection,IDisplayEventConnection类型。
- mDataChannel,BitTube类型。
IDisplayEventConnection负责真正向底层发起请求,涉及与SurfaceFlinger进程通信,它定义了与SurfaceFlinger进程通信的业务逻辑接口。
IDisplayEventConnection接口业务层方法
requestNextVsync:请求下一次垂直同步信号。
setVsyncRate:设置垂直同步帧率。
getDataChannel:获取通信管道。
sf是App进程ISurfaceComposer业务代理,业务对象在SurfaceFlinger进程,SurfaceFlinger对象,继承BnSurfaceComposer。
ISurfaceComposer业务进程通信如图所示。

App进程:
ISurfaceComposer代理#createDisplayEventConnection方法,返回IDisplayEventConnection业务代理mEventConnection,它继承BpDisplayEventConnection。
App进程利用mEventConnection三个业务方法请求SurfaceFlinger进程服务。
SurfaceFlinger进程:
SurfaceFlinger#createDisplayEventConnection方法,创建IDisplayEventConnection业务对象Connection,继承BnDisplayEventConnection。在与App进程通信时,Parcal#writeStrongBinder与readStrongBinder实现Binder对象传输,内核红黑树创建服务与引用节点,在App进程端创建业务代理BpDisplayEventConnection。
SurfaceFlinger进程#createDisplayEventConnection方法。
sp<IDisplayEventConnection> SurfaceFlinger::createDisplayEventConnection() {
return mEventThread->createEventConnection();
}
EventThread#createEventConnection方法。
sp<EventThread::Connection> EventThread::createEventConnection() const {
//在创建前会向EventThread注册该连接,加入到mDisplayEventConnections中。
return new Connection(const_cast<EventThread*>(this));
}
创建Connection对象,它是EventThread内部类。
Connection#构造方法。
EventThread::Connection::Connection(const sp<EventThread>& eventThread)
: count(-1), mEventThread(eventThread), mChannel(new BitTube())
{
}
在Connection构造方法,构建数据通道BitTube,BitTub内部一对Socket描述符,提供读写方法用于数据通讯。
IDisplayEventConnection业务进程通信如图所示。

BitTube分析
BitTube#构造方法
BitTube::BitTube()
: mSendFd(-1), mReceiveFd(-1){
init(DEFAULT_SOCKET_BUFFER_SIZE, DEFAULT_SOCKET_BUFFER_SIZE);
}
BitTube#init方法
void BitTube::init(size_t rcvbuf, size_t sndbuf) {
int sockets[2];
if (socketpair(AF_UNIX, SOCK_SEQPACKET, 0, sockets) == 0) {
...
mReceiveFd = sockets[0];
mSendFd = sockets[1];
} else {
mReceiveFd = -errno;
}
}
初始化一对socket发送与接收描述符,提供读写数据的管道功能。Tube的意思是管,BitTube即字节管道。socket缓存4M,mSendFd用于写入,写入后,mReceivedFd接收端能读取,mReceiveFd用于接收。
App进程:
通过IDisplayEventConnection#getDataChannel方法获取BitTube,SurfaceFlinger进程利用writeDupFileDescriptor写入mReceivedFd描述符,App进程从Parcel中读取描述符,创建BitTube对象,封装mReceivedFd描述符。
BpDisplayEventConnection#getDataChannel方法
virtual sp<BitTube> getDataChannel() const {
Parcel data, reply;
data.writeInterfaceToken(IDisplayEventConnection::getInterfaceDescriptor());
remote()->transact(GET_DATA_CHANNEL, data, &reply);
return new BitTube(reply);
}
Parcel#writeDupFileDescriptor与readFileDescriptor方法负责FileDescriptor类型读写存储。
BitTube#构造方法(带Parcel参数)。
BitTube::BitTube(const Parcel& data)
: mSendFd(-1), mReceiveFd(-1) {
mReceiveFd = dup(data.readFileDescriptor());
if (mReceiveFd < 0) {
mReceiveFd = -errno;
ALOGE("BitTube(Parcel): can't dup filedescriptor (%s)",
strerror(-mReceiveFd));
}
}
Choreographer接收器与SurfaceFlinger通信的架构图如下。综上:BitTube通过socketpair建立一对匿名已经连接套接字mReceiveFd与mSendFd,实现SurfaceFlinger与App进程的双向通信管道。在App进程中,有mReceiveFd描述符,监听描述符来自SurfaceFlinger进程mSendFd端的消息。

Java层DisplayEventReceiver请求下一次垂直同步信号的过程
流程图

JNI#nativeScheduleVsync方法。
static void nativeScheduleVsync(JNIEnv* env, jclass clazz, jlong receiverPtr) {
sp<NativeDisplayEventReceiver> receiver =
reinterpret_cast<NativeDisplayEventReceiver*>(receiverPtr);
status_t status = receiver->scheduleVsync();
...
}
根据Java层receiverPtr指针,获取NativeDisplayEventReceiver对象。
DisplayEventReceiver#scheduleVsync方法。
status_t NativeDisplayEventReceiver::scheduleVsync() {
if (!mWaitingForVsync) {
...
processPendingEvents(&vsyncTimestamp, &vsyncDisplayId, &vsyncCount);
status_t status = mReceiver.requestNextVsync();
...
mWaitingForVsync = true;
}
return OK;
}
DisplayEventReceiver#requestNextVsync方法。
status_t DisplayEventReceiver::requestNextVsync() {
if (mEventConnection != NULL) {
mEventConnection->requestNextVsync();
return NO_ERROR;
}
return NO_INIT;
}
跨进程IDisplayEventConnection业务#requestNextVsync方法,请求SurfaceFlinger进程提供服务,与SurfaceFlinger进程的Connection服务通信,Connection实现IDisplayEventConnection业务。Connection代表与App的连接,而不是SurfaceFlinger主线程的连接。
Connection#requestNextVsync方法。
void EventThread::Connection::requestNextVsync() {
mEventThread->requestNextVsync(this);
}
EventThread#requestNextVsync方法。
void EventThread::requestNextVsync(
const sp<EventThread::Connection>& connection) {
Mutex::Autolock _l(mLock);
if (connection->count < 0) {
connection->count = 0;
mCondition.broadcast();
}
}
通知mCondition条件,broadcast唤醒SurfaceFlinger进程的一个循环线程mEventThread,该线程在waitForEvent处等待,被唤醒后可利用Connection发送事件。
SurfaceFlinger循环线程EventThread
EventThread#threadLoop方法
bool EventThread::threadLoop() {
DisplayEventReceiver::Event event;
Vector< sp<EventThread::Connection> > signalConnections;
signalConnections = waitForEvent(&event);//等待事件,等待得到的事件保存在event指针处
const size_t count = signalConnections.size();
for (size_t i=0 ; i<count ; i++) {//遍历有信号的Connection,每个都发送event
const sp<Connection>& conn(signalConnections[i]);
status_t err = conn->postEvent(event);//写入的内容是Event类型
if (err == -EAGAIN || err == -EWOULDBLOCK) {
...
} else if (err < 0) {
removeDisplayEventConnection(signalConnections[i]);
}
}
return true;
}
在threadLoop循环中,唯一的工作是waitForEvent等待VSYNC信号,当信号发生时,发送给BitTube#mSendFd句柄。注意:SurfaceFlinger有两个EventThread线程,运行在各自的循环中。
SurfaceFlinger绘制延迟线程mEventThread发送消息
遍历收到信号的Connection,触发Connection#postEvent方法,调用DisplayEventReceiver#sendEvents方法,利用Connection内部BitTube即mChannel的write方法发送数据到mSendFd句柄,App进程的mReceiveFd就能收到消息。
Connection#postEvent方法
status_t EventThread::Connection::postEvent(
const DisplayEventReceiver::Event& event) {
ssize_t size = DisplayEventReceiver::sendEvents(mChannel, &event, 1);
return size < 0 ? status_t(size) : status_t(NO_ERROR);
}
利用数据通道BitTube发送消息,write方法。
DisplayEventReceiver#sendEvents方法
ssize_t DisplayEventReceiver::sendEvents(const sp<BitTube>& dataChannel,
Event const* events, size_t count) {
return BitTube::sendObjects(dataChannel, events, count);
}
dataChannel是BitTube对象,保存在Connection内部。 BitTube#sendObjects触发BitTube#write方法,即dataChannel的write方法,向mSendFd写入数据,App进程mReceiveFd可收到数据,实现SurfaceFlinger进程到App进程的数据传输。
App进程Choreographer线程Looper与SurfaceFlinger主线程Looper都在监听各自的mReceiveFd,等待数据到来。
App进程Choreographer线程监听到消息
App进程,mReceiveFd收到消息后,Choreographer线程Looper触发LooperCallback#handleEvent方法,即NativeDisplayEventReceiver#handleEvent方法,调用NativeDisplayEventReceiver#dispatchVsync方法。
NativeDisplayEventReceiver#dispatchVsync方法。
void NativeDisplayEventReceiver::dispatchVsync(nsecs_t timestamp, int32_t
id, uint32_t count) {
JNIEnv* env = AndroidRuntime::getJNIEnv();
ScopedLocalRef<jobject> receiverObj(env, jniGetReferent(env, mReceiverWeakGlobal));
if (receiverObj.get()) {
env->CallVoidMethod(receiverObj.get(),
gDisplayEventReceiverClassInfo.dispatchVsync, timestamp, id, count);
}
...
}
env#CallVoidMethod触发Java层DisplayEventReceiver对象的dispatchVsync方法。
Java#DisplayEventReceiver#dispatchVsync方法。
private void dispatchVsync(long timestampNanos, int builtInDisplayId, int frame) {
onVsync(timestampNanos, builtInDisplayId, frame);
}
在Choreographer类,FrameDisplayEventReceiver重写onVsync方法,onVsync由Choreographer线程执行。

FrameDisplayEventReceiver#onVsync方法
@Override
public void onVsync(long timestampNanos, int builtInDisplayId, int frame) {
...
long now = System.nanoTime();
if (timestampNanos > now) {
timestampNanos = now;
}
...
mTimestampNanos = timestampNanos;
mFrame = frame;
Message msg = Message.obtain(mHandler, this);
msg.setAsynchronous(true);
mHandler.sendMessageAtTime(msg, timestampNanos / TimeUtils.NANOS_PER_MS);
}
特定时刻发送消息,FrameDisplayEventReceiver实现Runnable。
SurfaceFlinger主线程消息队列与描述符监听
SurfaceFlinger#init方法初始化两个EventThread线程,与主线程通信的是mSFEventThread线程。
SurfaceFlinger#init方法。
void SurfaceFlinger::init() {
...
sp<VSyncSource> vsyncSrc = new DispSyncSource(&mPrimaryDispSync,
vsyncPhaseOffsetNs, true, "app");
mEventThread = new EventThread(vsyncSrc);
sp<VSyncSource> sfVsyncSrc = new DispSyncSource(&mPrimaryDispSync,
sfVsyncPhaseOffsetNs, true, "sf");
mSFEventThread = new EventThread(sfVsyncSrc);
mEventQueue.setEventThread(mSFEventThread);
...
}
- mEventThread线程:负责处理App进程的绘制请求事件,具体请求交由Connection服务处理。
- mSFEventThread线程:与SurfaceFlinger主线程通信,发送消息。
- MessageQueue:SurfaceFlinger主线程消息队列。

EventThread#onFirstRef方法,在EventThread构造方法执行后调用。
void EventThread::onFirstRef() {
run("EventThread", PRIORITY_URGENT_DISPLAY + PRIORITY_MORE_FAVORABLE);
}
EventThread#run启动线程,循环执行EventThread#threadLoop方法。
MessageQueue结构图如下所示。

SurfaceFlinger#onFirstRef方法。
void SurfaceFlinger::onFirstRef(){
mEventQueue.init(this);
}
MessageQueue#init方法。
void MessageQueue::init(const sp<SurfaceFlinger>& flinger) {
mFlinger = flinger;
mLooper = new Looper(true);
mHandler = new Handler(*this);
}
MessageQueue#setEventThread方法。
void MessageQueue::setEventThread(const sp<EventThread>& eventThread) {
mEventThread = eventThread;
mEvents = eventThread->createEventConnection();
mEventTube = mEvents->getDataChannel();
mLooper->addFd(mEventTube->getFd(), 0, Looper::EVENT_INPUT,
MessageQueue::cb_eventReceiver, this);
}
MessageQueue#setEventThread方法主要功能是SurfaceFlinger主线程Looper监听mReceiveFd描述符。
setEventThread方法负责设置EventThread,创建Connection与BitTube,Looper监听BitTube#mReceiveFd描述符,cb_eventReceiver是回调方法。
信号源DispSyncSource
SurfaceFlinger#init方法,创建两个DispSyncSource信号源,一个用于App进程绘制请求,另一个用于SurfaceFlinger合成。
EventThread构造方法传入DispSyncSource,DispSyncSource内部是相同的DispSync对象。
EventThread与DispSyncSource结构关系图如下所示。

DispSync#构造方法。
DispSync::DispSync() :
mRefreshSkipCount(0),
mThread(new DispSyncThread()) {
mThread->run("DispSync", PRIORITY_URGENT_DISPLAY + PRIORITY_MORE_FAVORABLE);
reset();
beginResync();
}
DispSync创建时,启动一个DispSyncThread线程。
DispSyncThread线程的主要工作是不断向DispSyncSource信号源发送vsync信号。
DispSyncThread线程产生信号,执行DispSyncSource#onDispSyncEvent方法,触发Callback#onVSyncEvent方法,而EventThread正是Callback,因此,程序执行EventThread#onVSyncEvent方法。在此处,mSFEventThread线程被唤醒broadcast。
EventThread#onVSyncEvent方法。
void EventThread::onVSyncEvent(nsecs_t timestamp) {
Mutex::Autolock _l(mLock);
//mVSyncEvent是一个Event的数组
mVSyncEvent[0].header.type = DisplayEventReceiver::DISPLAY_EVENT_VSYNC;
mVSyncEvent[0].header.id = 0;
//接收的vsync信号是一个时间戳,每个之间间隔mPeriod
mVSyncEvent[0].header.timestamp = timestamp;
mVSyncEvent[0].vsync.count++;//每次事件都加1
mCondition.broadcast();//唤醒waitForEvent
}
mSFEventThread线程被broadcast唤醒后,以同样的方法向mSendFd句柄发送数据,SurfaceFlinger主线程Looper监听mReceiveFd收到消息,触发cb_eventReceiver回调方法。
MessageQueue#cb_eventReceiver方法
int MessageQueue::cb_eventReceiver(int fd, int events, void* data) {
//当在EventThread线程,向mSendFd发送时,Looper监听到并处理事件
MessageQueue* queue = reinterpret_cast<MessageQueue *>(data);
return queue->eventReceiver(fd, events);
}
MessageQueue#eventReceiver方法。
int MessageQueue::eventReceiver(int /*fd*/, int /*events*/) {
ssize_t n;
DisplayEventReceiver::Event buffer[8];
while ((n = DisplayEventReceiver::getEvents(mEventTube, buffer, 8)) > 0) {
for (int i=0 ; i<n ; i++) {//每个buffer元素是DisplayEventReceiver::Event
if (buffer[i].header.type == DisplayEventReceiver::DISPLAY_EVENT_VSYNC) {//判断类型是vsync信号
#if INVALIDATE_ON_VSYNC//获取的event保存在buffer中
mHandler->dispatchInvalidate();//MQ内部Handler处理
#else
mHandler->dispatchRefresh();
#endif
break;
}
}
}
return 1;
}
DisplayEventReceiver#getEvents方法,利用BitTube#recvObjects方法接收消息,接收mReceiveFd获取的消息。读取BitTube#mReceiveFd描述符的数据,在SurfaceFlinger主线程处理。mEventTube是MQ内部BitTube对象。
DisplayEventReceiver#getEvents方法。
ssize_t DisplayEventReceiver::getEvents(const sp<BitTube>& dataChannel,
Event* events, size_t count) {
return BitTube::recvObjects(dataChannel, events, count);
}
任重而道远