AndroidAndroid Stability

界面显示_视图Choreographer控制

2018-03-02  本文已影响148人  gczxbb

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数组.png

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方法。
注意,在经过一段时间的延迟,中间有不确定性,增加两个条件判断。

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流程图如下所示。

Choreographer#postCallback流程 .png

显示事件接收器

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方法主要工作

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;
}

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构造方法,初始化两个重要对象的指针。

IDisplayEventConnection负责真正向底层发起请求,涉及与SurfaceFlinger进程通信,它定义了与SurfaceFlinger进程通信的业务逻辑接口。

IDisplayEventConnection接口业务层方法
requestNextVsync:请求下一次垂直同步信号。
setVsyncRate:设置垂直同步帧率。
getDataChannel:获取通信管道。

sf是App进程ISurfaceComposer业务代理,业务对象在SurfaceFlinger进程,SurfaceFlinger对象,继承BnSurfaceComposer。
ISurfaceComposer业务进程通信如图所示。

ISurfaceComposer业务进程通信.png
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业务进程通信如图所示。

IDisplayEventConnection业务进程通信.png
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缓存4MmSendFd用于写入,写入后,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));
    }
}

综上:BitTube通过socketpair建立一对匿名已经连接套接字mReceiveFd与mSendFd,实现SurfaceFlinger与App进程的双向通信管道。在App进程中,有mReceiveFd描述符,监听描述符来自SurfaceFlinger进程mSendFd端的消息。

Choreographer接收器与SurfaceFlinger通信的架构图如下。 Choreographer接收器与SurfaceFlinger通信流程架构图.png

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

流程图
DisplayEventReceiver请求下一次信号的流程.png

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线程执行。

onVsync流程图如下所示。 FrameDisplayEventReceiver#onVsync方法执行流程图.png

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);
    ...
}
SurfaceFlinger#init初始化EventThread线程如图所示。 SurfaceFlinger#init初始化EventThread线程.png

EventThread#onFirstRef方法,在EventThread构造方法执行后调用。

void EventThread::onFirstRef() {
    run("EventThread", PRIORITY_URGENT_DISPLAY + PRIORITY_MORE_FAVORABLE);
}

EventThread#run启动线程,循环执行EventThread#threadLoop方法。
MessageQueue结构图如下所示。

SurfaceFlinger的MessageQueue结构图.png SurfaceFlinger主线程触发MessageQueue#init方法,初始化主线程消息队列,初始化主线程Looper与Handler。
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结构关系图如下所示。

EventThread与DispSyncSource的结构图.png EventThread继承Thread,实现VSyncSource#Callback接口,#onVSyncEvent方法。DispSyncSource#Callback设置成EventThread。
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);
}

任重而道远

上一篇下一篇

猜你喜欢

热点阅读