Android-View绘制原理(03)-Vsync原理之App篇

上一篇文章中介绍了SurfaceFlinger搭建的Vsync基础设施,它先向HWComposer注册回调,然后开启EventThread 线程无限循环,从pendingEvents中拿事件向消费者分发事件,它会往消费者提供的文件描述符中发送信号,从而通知消费者。当pendingEvents中没有事件时,线程就等待mCondition上的通知。而另一方面,当HWComposer上来Vsync事件时,会往pendingEvents添加一个 Vsync的事件,并调用mCondition.notify_all,唤醒分发线程。 同时也提到如果没有消费者,或者消费者没有发出请求,则不会向App发出Vsync信号。本文将从App的角度继续来分析Vsync的原理。

1.1 App层注册DisplayEventReceiver

首先是App运行时,会在初始化Choreographer的初始化,这时就创建了一个DisplayEventReceiver的子类的对象

private Choreographer(Looper looper, int vsyncSource) {
        mLooper = looper;
        mHandler = new FrameHandler(looper);
        mDisplayEventReceiver = USE_VSYNC
                ? new FrameDisplayEventReceiver(looper, vsyncSource)
                : null;
...
}

构造方法内部调用一个nativeInit方法在JNI层生成一个NativeDisplayEventReceiver对象,并将该对象的指针返回,java层将指针保存到mReceiverPtr

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

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

frameworks/base/core/jni/android_view_DisplayEventReceiver.cpp

static jlong nativeInit(JNIEnv* env, jclass clazz, jobject receiverWeak, jobject messageQueueObj, jint vsyncSource, jint eventRegistration) {
    sp<NativeDisplayEventReceiver> receiver =
            new NativeDisplayEventReceiver(env, receiverWeak, messageQueue, vsyncSource,eventRegistration);
    status_t status = receiver->initialize();
   
    receiver->incStrong(gDisplayEventReceiverClassInfo.clazz); // retain a reference for the object
    return reinterpret_cast<jlong>(receiver.get());
}

这里的NativeDisplayEventReceiver继承自DisplayEventDispatcher

 class NativeDisplayEventReceiver : public DisplayEventDispatcher {

而这个DisplayEventDispatcher来自于

frameworks/native/libs/gui/DisplayEventReceiver.cpp

DisplayEventReceiver::DisplayEventReceiver(
        ISurfaceComposer::VsyncSource vsyncSource,
        ISurfaceComposer::EventRegistrationFlags eventRegistration) {
    sp<ISurfaceComposer> sf(ComposerService::getComposerService());
    if (sf != nullptr) {
        mEventConnection = sf->createDisplayEventConnection(vsyncSource, eventRegistration);
        if (mEventConnection != nullptr) {
            mDataChannel = std::make_unique<gui::BitTube>();
            mEventConnection->stealReceiveChannel(mDataChannel.get());
        }
    }
}

创建好层的NativeDisplayEventReceiver,它会获取surfaceFlinger远程服务创建一个mEventConnection,接着调用了mEventConnection->stealReceiveChannel(mDataChannel.get());方法,这个远程服务的流程在后文中再介绍。

frameworks/native/services/surfaceflinger/Scheduler/EventThread.cpp

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

这是一个远程调用,它将mEventConnect的mChannel中的moveReceiveFd和getSendFd都拷贝到了outChannel,然后调用initialize进行初始化。

frameworks/native/libs/gui/DisplayEventDispatcher.cpp

status_t DisplayEventDispatcher::initialize() {
    ...
    if (mLooper != nullptr) {
        int rc = mLooper->addFd(mReceiver.getFd(), 0, Looper::EVENT_INPUT, this, NULL);
        if (rc < 0) {
            return UNKNOWN_ERROR;
        }
    }
    return OK;
}

initialize很简单,只是给mLooper添加一个监听的mReceiver的文件描述符FileDescriptor,上面看到这个文件描述符是有从 mEventConnection中”steal“来的,因此实际上监听是注册在mEventConnection上的(上一篇中介绍到,当EventThread分发时Vsync时,是通过send方法向FD中发送数据,所以APP和SurfaceFlinger就是在这里对接起来),于是当产生EVENT_INPUT事件时回调this的handleEvent函数

int DisplayEventDispatcher::handleEvent(int, int events, void*) {
   ...
    // Drain all pending events, keep the last vsync.
    nsecs_t vsyncTimestamp;
    PhysicalDisplayId vsyncDisplayId;
    uint32_t vsyncCount;
    VsyncEventData vsyncEventData;
    if (processPendingEvents(&vsyncTimestamp, &vsyncDisplayId, &vsyncCount, &vsyncEventData)) {
        ...
        mWaitingForVsync = false;
        dispatchVsync(vsyncTimestamp, vsyncDisplayId, vsyncCount, vsyncEventData);
    }
    return 1; // keep the callback
}

handleEvent的时候会调用processPendingEvents来处理收到的事件数据,其中一种数据的header.type == DISPLAY_EVENT_VSYNC,就表示是sync事件,然后调用dispatchVsync函数,通知app层sync信号产生了。

bool DisplayEventDispatcher::processPendingEvents(nsecs_t* outTimestamp, PhysicalDisplayId* outDisplayId, 
                                                   uint32_t* outCount, VsyncEventData* outVsyncEventData) {
    bool gotVsync = false;
    DisplayEventReceiver::Event buf[EVENT_BUFFER_SIZE];
    ssize_t n;
    while ((n = mReceiver.getEvents(buf, EVENT_BUFFER_SIZE)) > 0) {
        ALOGV("dispatcher %p ~ Read %d events.", this, int(n));
        mFrameRateOverrides.reserve(n);
        for (ssize_t i = 0; i < n; i++) {
            const DisplayEventReceiver::Event& ev = buf[i];
            switch (ev.header.type) {
                case DisplayEventReceiver::DISPLAY_EVENT_VSYNC:
                    gotVsync = true;
                    ...
                    break;
                ...
    return gotVsync;
}

dispatchVsyncs是一个虚函数,在NativeDisplayEventReceiver中实现
frameworks/base/core/jni/android_view_DisplayEventReceiver.cpp

void NativeDisplayEventReceiver::dispatchVsync(nsecs_t timestamp, PhysicalDisplayId displayId,
                                               uint32_t count, VsyncEventData vsyncEventData) {
    JNIEnv* env = AndroidRuntime::getJNIEnv();

    ScopedLocalRef<jobject> receiverObj(env, jniGetReferent(env, mReceiverWeakGlobal));
    if (receiverObj.get()) {
     
        env->CallVoidMethod(receiverObj.get(), gDisplayEventReceiverClassInfo.dispatchVsync,
                            timestamp, displayId.value, count, vsyncEventData.id,
                            vsyncEventData.deadlineTimestamp, vsyncEventData.frameInterval);
    }

    mMessageQueue->raiseAndClearException(env, "dispatchVsync");
}

获取到JAVA层DisplayEventReceiver对象的指针,然后调用dispatchVsync方法(偏移量为DisplayEventReceiverClassInfo.dispatchVsync)
android/view/DisplayEventReceiver.java

private void dispatchVsync(long timestampNanos, long physicalDisplayId, int frame,
            long frameTimelineVsyncId, long frameDeadline, long frameInterval) {
        onVsync(timestampNanos, physicalDisplayId, frame,
                new VsyncEventData(frameTimelineVsyncId, frameDeadline, frameInterval));
    }

调用onVsync方法,这个时在Choreogragher 的内部类中实现的

 public FrameDisplayEventReceiver(Looper looper, int vsyncSource) {
            super(looper, vsyncSource, 0);
        }

        public void onVsync(long timestampNanos, long physicalDisplayId, int frame,
                VsyncEventData vsyncEventData) {
                ...
                Message msg = Message.obtain(mHandler, this);
                msg.setAsynchronous(true);
                mHandler.sendMessageAtTime(msg, timestampNanos / TimeUtils.NANOS_PER_MS);
        }
       
       public void run() {
            mHavePendingVsync = false;
            doFrame(mTimestampNanos, mFrame, mLastVsyncEventData);
        }

Vsync就在应用层得到了响应,执行doFrame开始绘制界面。整个的初始化流程以及Vsync信息向上传递的流程就串联起来了。但是中间有一个断层,就是DisplayEventDispatcher的Looper什么时候会收到mReceiver文件描述符上的Looper::EVENT_INPUT事件?前一篇文章中提到Vsync需要App层的通知才会发送,否则EventThread线程将一直等待在mCondition.wait.

3.2 触发Vsync

我们再回到UI层来看看

3.2.1 ViewRootimpl

在ViewRootImpl.setView之后,回去调用requestLayout方法,此时会向Choreographer注册callback:

public void requestLayout() {
        if (!mHandlingLayoutInLayoutRequest) {
            checkThread();
            mLayoutRequested = true;
            scheduleTraversals();
        }
    }
void scheduleTraversals() {
        if (!mTraversalScheduled) {
            mTraversalScheduled = true;
            mTraversalBarrier = mHandler.getLooper().getQueue().postSyncBarrier();
            mChoreographer.postCallback(Choreographer.CALLBACK_TRAVERSAL, mTraversalRunnable, null);
            notifyRendererOfFramePending();
            pokeDrawLockIfNeeded();
        }
    }

mChoreographer.postCallback将进入到Choreograher,通知安排vsync

3.2.2 Choreographer

Choreograher是一个承上启下的角色,当Vsync到来时通知View进行绘制,同样当画面绘制开始时,它也会通知低层开始可以安排Vsync

public void postCallback(int callbackType, Runnable action, Object token) {
        postCallbackDelayed(callbackType, action, token, 0);
    }
public void postCallbackDelayed(int callbackType, Runnable action, Object token, long delayMillis) {
        ...
        postCallbackDelayedInternal(callbackType, action, token, delayMillis);
    }
 private void postCallbackDelayedInternal(int callbackType, Object action, Object token, long delayMillis) {
                ...
                Message msg = mHandler.obtainMessage(MSG_DO_SCHEDULE_CALLBACK, action);
                msg.arg1 = callbackType;
                msg.setAsynchronous(true);
                mHandler.sendMessageAtTime(msg, dueTime);
    }

mHandler是FrameHandler的实例,它 是一个内部类,它可以处理三种消息
1,MSG_DO_FRAME。调用doFrame开始新一帧的绘制
2,MSG_DO_SCHEDULE_VSYNC。调用doScheduleVsync通知低层准备VSync
3,MSG_DO_SCHEDULE_CALLBACK。调用doScheduleCallback,如果mFrameScheduled = false,调用scheduleFrameLocked,将mFrameScheduled 设置为true,在USE_VSYNC==true的时候,发送MSG_DO_SCHEDULE_VSYNC消息,消息处理后就会调用到doScheduleVsync。目前USE_VSYNC都是为true的,如果关闭它,则发送直接发送MSG_DO_FRAME消息。

private final class FrameHandler extends Handler {
    
        @Override
        public void handleMessage(Message msg) {
            switch (msg.what) {
                case MSG_DO_FRAME:
                    doFrame(System.nanoTime(), 0, new DisplayEventReceiver.VsyncEventData());
                    break;
                case MSG_DO_SCHEDULE_VSYNC:
                    doScheduleVsync();
                    break;
                case MSG_DO_SCHEDULE_CALLBACK:
                    doScheduleCallback(msg.arg1);
                    break;
            }
        }
    }

处理MSG_DO_SCHEDULE_VSYNC消息,此时mFrameScheduled = false,调用scheduleFrameLocked方法

 void doScheduleCallback(int callbackType) {
            if (!mFrameScheduled) {
                    ...
                    scheduleFrameLocked(now);
             }
    }

mFrameScheduled 开始为false,进入case之后设置为true,USE_VSYNC是由一个系统属性“debug.choreographer.vsync”控制的,默认为true,然后就发送MSG_DO_SCHEDULE_VSYNC消息。

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 {
                Message msg = mHandler.obtainMessage(MSG_DO_FRAME);
                msg.setAsynchronous(true);
                mHandler.sendMessageAtTime(msg, nextFrameTime);
            }
        }
    }

处理MSG_DO_SCHEDULE_VSYNC消息,此时mFrameScheduled = true,因此执行scheduleVsyncLocked方法

   void doScheduleVsync() {
        synchronized (mLock) {
            if (mFrameScheduled) {
                scheduleVsyncLocked();
            }
        }
    }

调用mDisplayEventReceiver安排sync

    private void scheduleVsyncLocked() {
            ...
            mDisplayEventReceiver.scheduleVsync();
            ...
    }

这里有一个mFrameScheduled控制变量很重要,它表示已经通知低层为下一帧排期了,在app收到Vsync,执行doFrame之后,它会再次置为false。

到目前为之,我们可以看到,是因为ViewRootImpl.requestLayout 触发了 mDisplayEventReceiver.scheduleVsync,也就是app需要更新的时候,并不是自己立刻就动手绘制,而且先告知底层框架,我有更新需求了,底层框架得到通知后就检测一下它是不是显示完一帧了,显示完了就发一个Vsync给上层app,app收到之后执行doFrame开始真正的绘制。如果app一直没有更新需求,底层得不到通知,所以就不会发出vsync信号

@UnsupportedAppUsage
    public void scheduleVsync() {
        if (mReceiverPtr == 0) {
            Log.w(TAG, "Attempted to schedule a vertical sync pulse but the display event "
                    + "receiver has already been disposed.");
        } else {
            nativeScheduleVsync(mReceiverPtr);
        }
    }

调用了一个native方法nativeScheduleVsync函数,传入mReceiverPtr

frameworks/base/core/jni/android_view_DisplayEventReceiver.cpp

static const JNINativeMethod gMethods[] = {
    ...
    { "nativeScheduleVsync", "(J)V", (void*)nativeScheduleVsync }
};

nativeScheduleVsync映射到nativeScheduleVsync这个函数

static void nativeScheduleVsync(JNIEnv* env, jclass clazz, jlong receiverPtr) {
    sp<NativeDisplayEventReceiver> receiver =
            reinterpret_cast<NativeDisplayEventReceiver*>(receiverPtr);
    status_t status = receiver->scheduleVsync();
    if (status) {
        String8 message;
        message.appendFormat("Failed to schedule next vertical sync pulse.  status=%d", status);
        jniThrowRuntimeException(env, message.string());
    }
}

将receiverPtr转换回NativeDisplayEventReceiver类型的对象,这个对象就是初始化时在JNI生成的,然后再执行它的scheduleVsync函数

status_t DisplayEventDispatcher::scheduleVsync() {
    if (!mWaitingForVsync) {
       
        // Drain all pending events.
        nsecs_t vsyncTimestamp;
        PhysicalDisplayId vsyncDisplayId;
        uint32_t vsyncCount;
        VsyncEventData vsyncEventData;
        if (processPendingEvents(&vsyncTimestamp, &vsyncDisplayId, &vsyncCount, &vsyncEventData)) {
            ALOGE("dispatcher %p ~ last event processed while scheduling was for %" PRId64 "", this,
                  ns2ms(static_cast<nsecs_t>(vsyncTimestamp)));
        }
        status_t status = mReceiver.requestNextVsync();
        if (status) {
            ALOGW("Failed to request next vsync, status=%d", status);
            return status;
        }

        mWaitingForVsync = true;
    }
    return OK;
}

继续调用 mReceiver.requestNextVsync()请求下一次 Vsync,
frameworks/native/libs/gui/include/gui/DisplayEventDispatcher.h


status_t DisplayEventReceiver::requestNextVsync() {
    if (mEventConnection != nullptr) {
        mEventConnection->requestNextVsync();
        return NO_ERROR;
    }
    return NO_INIT;
}

mEventConnection是初始化DisplayEventReceiver时调用ComposeerService.createDisplayEventConnection就创建好的,它的类型是IDisplayEventConnection,然后在requestNextVsync时,通过调用mEventConnection.requestNextVsync来请求下一次VSync。

需要说明的是到目前为止,我们的代码包括JAVA和JNI,都运行在app的进程。这个里多出来几个新的类型。ComposerService,ISurfaceComposer,IDisplayEventConnection, 现在我们就需要通过Binder进行IPC穿越到surfaceflinger进程中去,IBinder的机制不是本文的范围,这里就不介绍Binder的原理了,直接进入到 SurfaceFlingger
.

3.2.3 连接SurfaceFligger

  1. ComposerService::getComposerService()

frameworks/native/include/private/gui/ComposerService.h
*frameworks/native/libs/gui/SurfaceComposerClient.cpp

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

ComposerService 是通过宏定义的一个单例,

NDROID_SINGLETON_STATIC_INSTANCE(ComposerService);

ComposerService::ComposerService()
: Singleton<ComposerService>() {
    Mutex::Autolock _l(mLock);
    connectLocked();
}

bool ComposerService::connectLocked() {
    const String16 name("SurfaceFlinger");
    mComposerService = waitForService<ISurfaceComposer>(name);
    if (mComposerService == nullptr) {
        return false; // fatal error or permission problem
    }
...
}

初始化单例对象的时候,会调用connectLocked方法,内部通过调用ServiceManager的waitForService去获取SurfaceFlinger远程服务的本地接口,所以mComposerService可以和远程的SurfaceFlinger服务进行IPC通信。

这里的第一个通信就是createDisplayEventConnection

我们知道一个Binder通信由3部分组成,一个就是通信接口,一个服务端的Bn接口和客户端的Bp接口。ISurfaceComposer 是接口,BnSurfaceComposer是服务端,BpSurfaceComposer是客户端。ISurfaceComposer,BnSurfaceComposer的申明是在ISurfaceComposer.h中,
frameworks/native/include/gui/ISurfaceComposer.h

class ISurfaceComposer: public IInterface {
public:
    DECLARE_META_INTERFACE(SurfaceComposer)//

    static constexpr size_t MAX_LAYERS = 4096;
...
}

这里用到DECLARE_META_INTERFACE这个宏定义,就具有IIIterface的那些模板方法

class BnSurfaceComposer: public BnInterface<ISurfaceComposer> {
public:
    enum ISurfaceComposerTag {
    }
...

BnSurfaceComposer 是服务端的桩,surfaceflinger服务类需要继承这个类.下面是客户端的BpSurfaceComposer

frameworks/native/libs/gui/ISurfaceComposer.cpp

class BpSurfaceComposer : public BpInterface<ISurfaceComposer>
{
public:
    explicit BpSurfaceComposer(const sp<IBinder>& impl)
        : BpInterface<ISurfaceComposer>(impl)
    {
    }

    virtual ~BpSurfaceComposer();

    virtual sp<ISurfaceComposerClient> createConnection()

我们通过 mComposerService = waitForService<ISurfaceComposer>(“SurfaceFlinger”)得到的mComposerService,就是在Binder驱动中查找到的IBinder,然后用BpSurfaceComposer包装出来的,也就是说mComposerService的类型是BpSurfaceComposer。因此createDisplayEventConnection方法如下:
frameworks/native/libs/gui/ISurfaceComposer.cpp

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

remote()->transact就是在进行远程调用,它会IPC到surfaceFlinger进程,执行BnSurfaceComposer.createDisplayEventConnection,而SurfaceFlinger就是BnSurfaceComposer的子类,因此进入到SurfaceFlinger。

frameworks/native/services/surfaceflinger/SurfaceFlinger.h

class SurfaceFlinger : public BnSurfaceComposer,
                       public PriorityDumper,
                       private IBinder::DeathRecipient,
                       private HWC2::ComposerCallback,
                       private ISchedulerCallback {
...
}

SurfaceFlinger 是继承自BnSurfaceComposer。下面来看看createDisplayEventConnection的实现。

frameworks/native/services/surfaceflinger/SurfaceFlinger.cpp

sp<IDisplayEventConnection> SurfaceFlinger::createDisplayEventConnection(
        ISurfaceComposer::VsyncSource vsyncSource,
        ISurfaceComposer::EventRegistrationFlags eventRegistration) {
    const auto& handle =
            vsyncSource == eVsyncSourceSurfaceFlinger ? mSfConnectionHandle : mAppConnectionHandle;

    return mScheduler->createDisplayEventConnection(handle, eventRegistration);
}

这里通过呼叫mScheduler的createDisplayEventConnection来创建,因为这里是App进来的,因此handle == mAppConnectionHandle

frameworks/native/services/surfaceflinger/Scheduler/Scheduler.cpp

sp<IDisplayEventConnection> Scheduler::createDisplayEventConnection(
        ConnectionHandle handle, ISurfaceComposer::EventRegistrationFlags eventRegistration) {
    std::lock_guard<std::mutex> lock(mConnectionsLock);
    RETURN_IF_INVALID_HANDLE(handle, nullptr);
    return createConnectionInternal(mConnections[handle].thread.get(), eventRegistration);
}
sp<EventThreadConnection> Scheduler::createConnectionInternal(
        EventThread* eventThread, ISurfaceComposer::EventRegistrationFlags eventRegistration) {
    return eventThread->createEventConnection([&] { resync(); }, eventRegistration);
}

调用eventThread的createEventConnection

frameworks/native/services/surfaceflinger/Scheduler/EventThread.cpp

sp<EventThreadConnection> EventThread::createEventConnection(
        ResyncCallback resyncCallback,
        ISurfaceComposer::EventRegistrationFlags eventRegistration) const {
    return new EventThreadConnection(const_cast<EventThread*>(this),
                                     IPCThreadState::self()->getCallingUid(),
                                     std::move(resyncCallback), eventRegistration);
}

也就是说最后这个EventConnection是一个EventThreadConnection对象这再上一篇文章中也介绍过。这个EventThreadConnection也是一个IBinder,因为这个是一个Binder,当第一引用的时候,会执行onFirstRef,然后调用到mEventThread->registerDisplayEventConnection(this); 于是把这个connect放入到mDisplayEventConnections这个集合中,从而加入Vsync消费者行列。
frameworks/native/services/surfaceflinger/Scheduler/EventThread.h

class EventThreadConnection : public BnDisplayEventConnection {
     VSyncRequest vsyncRequest = VSyncRequest::None;
...
}

void EventThreadConnection::onFirstRef() {
    // NOTE: mEventThread doesn't hold a strong reference on us
    mEventThread->registerDisplayEventConnection(this);
}

status_t EventThread::registerDisplayEventConnection(const sp<EventThreadConnection>& connection) {
    ...
    mDisplayEventConnections.push_back(connection);
    mCondition.notify_all();
    return NO_ERROR;
}

它对应的BnDisplayEventConnection接口是
frameworks/native/include/gui/IDisplayEventConnection.h

class BnDisplayEventConnection : public SafeBnInterface<IDisplayEventConnection> {
public:
    BnDisplayEventConnection()
          : SafeBnInterface<IDisplayEventConnection>("BnDisplayEventConnection") {}

    status_t onTransact(uint32_t code, const Parcel& data, Parcel* reply,
                        uint32_t flags = 0) override;
};

因为DisplayEventReceiver在初始化时拿到了surfaceFlinger的客户端,然后调用这个客户端的createDisplayEventConnection方法,返回了一个
EventThreadConnection对象并赋值给mEventConnection,而这个对象又是BnDisplayEventConnection的客户端,所以在DisplayEventReceiver的requestNextVsync方法中,mEventConnection.requestNextVsync将会进入到BnDisplayEventConnection的requestNextVsync方法

status_t DisplayEventReceiver::requestNextVsync() {
    if (mEventConnection != nullptr) {
        mEventConnection->requestNextVsync();
        return NO_ERROR;
    }
    return NO_INIT;
}

BnDisplayEventConnection作为服务端的桩,由服务者实现。
frameworks/native/services/surfaceflinger/Scheduler/EventThread.h

class EventThreadConnection : public BnDisplayEventConnection {
     ...
}

所以requestNextVsync将进入这里:
frameworks/native/services/surfaceflinger/Scheduler/EventThread.cpp

void EventThreadConnection::requestNextVsync() {
    ATRACE_NAME("requestNextVsync");
    mEventThread->requestNextVsync(this);
}

mEventThread是EventThread的实例

void EventThread::requestNextVsync(const sp<EventThreadConnection>& connection) {
    if (connection->resyncCallback) {
        connection->resyncCallback();
    }

    std::lock_guard<std::mutex> lock(mMutex);

    if (connection->vsyncRequest == VSyncRequest::None) {
        connection->vsyncRequest = VSyncRequest::Single;
        mCondition.notify_all();
    } else if (connection->vsyncRequest == VSyncRequest::SingleSuppressCallback) {
        connection->vsyncRequest = VSyncRequest::Single;
    }
}

在上面构造EventThreadConnection时,没有为vsyncRequest赋值,所以默认是VSyncRequest::None。因此执行:
connection->vsyncRequest = VSyncRequest::Single;
mCondition.notify_all();
起关键作用的就是mCondition.notify_all()。

4. 总结

  • 从UI层注册监听,实质上是建立了一个与SurfaceFlinger建立了EventThreadConnection,然后将其加入到Vsync的消费者集合,
    然后复制并监听其消息的文件描述符。
  • 从UI层requestLayout触发的scheduleVsync,其路经很长,经由JNI,IPC最终进入到EventThread,
    完成唤醒分发线mCondition.notify_all() 的任务
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 204,684评论 6 478
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 87,143评论 2 381
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 151,214评论 0 337
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,788评论 1 277
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,796评论 5 368
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,665评论 1 281
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 38,027评论 3 399
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,679评论 0 258
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 41,346评论 1 299
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,664评论 2 321
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,766评论 1 331
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,412评论 4 321
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 39,015评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,974评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,203评论 1 260
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 45,073评论 2 350
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,501评论 2 343

推荐阅读更多精彩内容