VSync是垂直同步(Vertical Synchronization)的简称。基本的思路是将设备的FPS和显示屏同步起来。其目的是避免显示出现"撕裂"现象,此文章主要是在android 10的代码上追下VSync的主要流程,以后用来自己复习总结,有错误还请指出.

(1)VSync注册(接收HW_VSync)

SurfaceFlinger.h 继承自ComposerCallback

class SurfaceFlinger : private HWC2::ComposerCallback()    /* ------------------------------------------------------------------------     * HWC2::ComposerCallback / HWComposer::EventHandler interface     */    void onVsyncReceived(int32_t sequenceId, hwc2_display_t hwcDisplayId,                         int64_t timestamp) override;    void onHotplugReceived(int32_t sequenceId, hwc2_display_t hwcDisplayId,                           HWC2::Connection connection) override;    void onRefreshReceived(int32_t sequenceId, hwc2_display_t hwcDisplayId) override;

HWC2.h ComposerCallback定义

class ComposerCallback { public:    virtual void onHotplugReceived(int32_t sequenceId, hwc2_display_t display,                                   Connection connection) = 0;    virtual void onRefreshReceived(int32_t sequenceId,                                   hwc2_display_t display) = 0;    virtual void onVsyncReceived(int32_t sequenceId, hwc2_display_t display,                                 int64_t timestamp) = 0;    virtual ~ComposerCallback() = default;};

HWC2.cpp 实现Hwc2::IComposerCallback(

ComposerHal.h --> namespace android{ namespace Hwc2 {

                                                               namespace V2_1 = hardware::graphics::composer::V2_1;

                                                              using V2_1::IComposerCallback;

}})

class ComposerCallbackBridge : public Hwc2::IComposerCallback {public:    ComposerCallbackBridge(ComposerCallback* callback, int32_t sequenceId)            : mCallback(callback), mSequenceId(sequenceId) {}    Return onHotplug(Hwc2::Display display,                           IComposerCallback::Connection conn) override    {        HWC2::Connection connection = static_cast(conn);        mCallback->onHotplugReceived(mSequenceId, display, connection);        return Void();    }    Return onRefresh(Hwc2::Display display) override    {        mCallback->onRefreshReceived(mSequenceId, display);        return Void();    }    Return onVsync(Hwc2::Display display, int64_t timestamp) override    {        mCallback->onVsyncReceived(mSequenceId, display, timestamp);        return Void();    }private:    ComposerCallback* mCallback;    int32_t mSequenceId;};

以上是将用于VSync注册的关键class,下面是真正的注册过程:

SurfaceFlinger.cpp 在init中注册HWComposer的回调

// Do not call property_set on main thread which will be blocked by init// Use StartPropertySetThread instead.void SurfaceFlinger::init() {    /**/    mCompositionEngine->getHwComposer().registerCallback(this, getBE().mComposerSequenceId);    // Process any initial hotplug and resulting display changes.    /**/}

HWComposer.cpp 注册HWC2::Device的回调

void HWComposer::registerCallback(HWC2::ComposerCallback* callback,                                  int32_t sequenceId) {    mHwcDevice->registerCallback(callback, sequenceId);}

HWC2.cpp 实例化ComposerCallbackBridge注册android::Hwc2::Composer的回调

void Device::registerCallback(ComposerCallback* callback, int32_t sequenceId) {    if (mRegisteredCallback) {        ALOGW("Callback already registered. Ignored extra registration "                "attempt.");        return;    }    mRegisteredCallback = true;    sp callbackBridge(            new ComposerCallbackBridge(callback, sequenceId));    mComposer->registerCallback(callbackBridge);}

ComposerHal.cpp 注册hardware::graphics::composer::V2_1::IComposerClient的回调

void Composer::registerCallback(const sp& callback){    auto ret = mClient->registerCallback(callback);    if (!ret.isOk()) {        ALOGE("failed to register IComposerCallback");    }}

以上为VSync的注册全过程,可以看到VSync的产生还是会受硬件控制的.

(2)VSync 从HIDL到SurfaceFlinger的分发(HW_VSync到SW_VSync)

hardware::graphics::composer::V2_1::IComposerClient.h 开始分发给Hwc2::IComposerCallback

class HalEventCallback : public Hal::EventCallback {       public:        HalEventCallback(const sp callback, ComposerResources* resources)            : mCallback(callback), mResources(resources) {}        /**/        void onVsync(Display display, int64_t timestamp) {            auto ret = mCallback->onVsync(display, timestamp);            ALOGE_IF(!ret.isOk(), "failed to send onVsync: %s", ret.description().c_str());        }        /**/    };

 HWC2.cpp 分发给class SurfaceFlinger : private HWC2::ComposerCallback

class ComposerCallbackBridge : public Hwc2::IComposerCallback {public:    ComposerCallbackBridge(ComposerCallback* callback, int32_t sequenceId)            : mCallback(callback), mSequenceId(sequenceId) {}    /**/    Return onVsync(Hwc2::Display display, int64_t timestamp) override    {        mCallback->onVsyncReceived(mSequenceId, display, timestamp);        return Void();    }    /**/};

SurfaceFlinger.cpp开始分发

void SurfaceFlinger::onVsyncReceived(int32_t sequenceId, hwc2_display_t hwcDisplayId,                                     int64_t timestamp) {    ATRACE_NAME("SF onVsync");    Mutex::Autolock lock(mStateLock);    // Ignore any vsyncs from a previous hardware composer.    if (sequenceId != getBE().mComposerSequenceId) {        return;    }    if (!getHwComposer().onVsync(hwcDisplayId, timestamp)) {        return;    }    if (hwcDisplayId != getHwComposer().getInternalHwcDisplayId()) {        // For now, we don't do anything with external display vsyncs.        return;    }    bool periodChanged = false;    mScheduler->addResyncSample(timestamp, &periodChanged);    if (periodChanged) {        mVsyncModulator.onRefreshRateChangeDetected();    }}

Scheduler.cpp 将VSync传递给DispSync。如果DipSync检测到vsync周期已更改,periodChange将为true,否则为false。

void Scheduler::addResyncSample(const nsecs_t timestamp, bool* periodChanged) {    bool needsHwVsync = false;    *periodChanged = false;    { // Scope for the lock        std::lock_guard lock(mHWVsyncLock);        if (mPrimaryHWVsyncEnabled) {            needsHwVsync = mPrimaryDispSync->addResyncSample(timestamp, periodChanged);        }    }    if (needsHwVsync) {        enableHardwareVsync();    } else {        disableHardwareVsync(false);    }}

DispSync.cpp 往SW VSync模型中添加硬件VSync时间戳样本,同时在利用已经存在硬件vsync时间戳的实时更新下一次SW VSync的时间.此文章更详细:https://blog.csdn.net/zhuawalibai/article/details/87976799

bool DispSync::addResyncSample(nsecs_t timestamp, bool* periodChanged) {    Mutex::Autolock lock(mMutex);    ALOGV("[%s] addResyncSample(%" PRId64 ")", mName, ns2us(timestamp));    *periodChanged = false;    const size_t idx = (mFirstResyncSample + mNumResyncSamples) % MAX_RESYNC_SAMPLES;    mResyncSamples[idx] = timestamp;    if (mNumResyncSamples == 0) {        mPhase = 0;        ALOGV("[%s] First resync sample: mPeriod = %" PRId64 ", mPhase = 0, "              "mReferenceTime = %" PRId64,              mName, ns2us(mPeriod), ns2us(timestamp));    } else if (mPendingPeriod > 0) {        // mNumResyncSamples > 0, so priorIdx won't overflow        const size_t priorIdx = (mFirstResyncSample + mNumResyncSamples - 1) % MAX_RESYNC_SAMPLES;        const nsecs_t lastTimestamp = mResyncSamples[priorIdx];        const nsecs_t observedVsync = std::abs(timestamp - lastTimestamp);        if (std::abs(observedVsync - mPendingPeriod) < std::abs(observedVsync - mPeriod)) {            // Observed vsync is closer to the pending period, so reset the            // model and flush the pending period.            resetLocked();            mPeriod = mPendingPeriod;            mPendingPeriod = 0;            if (mTraceDetailedInfo) {                ATRACE_INT("DispSync:PendingPeriod", mPendingPeriod);            }            *periodChanged = true;        }    }    // Always update the reference time with the most recent timestamp.    mReferenceTime = timestamp;    mThread->updateModel(mPeriod, mPhase, mReferenceTime);            if (mNumResyncSamples < MAX_RESYNC_SAMPLES) {        mNumResyncSamples++;    } else {        mFirstResyncSample = (mFirstResyncSample + 1) % MAX_RESYNC_SAMPLES;    }    updateModelLocked();    if (mNumResyncSamplesSincePresent++ > MAX_RESYNC_SAMPLES_WITHOUT_PRESENT) {        resetErrorLocked();    }    if (mIgnorePresentFences) {        // If we're ignoring the present fences we have no way to know whether        // or not we're synchronized with the HW vsyncs, so we just request        // that the HW vsync events be turned on.        return true;    }    // Check against kErrorThreshold / 2 to add some hysteresis before having to    // resync again    bool modelLocked = mModelUpdated && mError < (kErrorThreshold / 2) && mPendingPeriod == 0;    ALOGV("[%s] addResyncSample returning %s", mName, modelLocked ? "locked" : "unlocked");    if (modelLocked) {        mThread->lockModel();    }    return !modelLocked;}

 DispSync.cpp fireCallbackInvocations函数遍历回调列表调用其onDispSyncEvent函数。

    void fireCallbackInvocations(const std::vector& callbacks) {        if (mTraceDetailedInfo) ATRACE_CALL();        for (size_t i = 0; i < callbacks.size(); i++) {            callbacks[i].mCallback->onDispSyncEvent(callbacks[i].mEventTime);        }    }

DispSyncSource.h (DispSyncSource final : public VSyncSource, private DispSync::Callback)

DispSyncSource.cpp 实现 DispSync::Callback ,在自身onDispSyncEvent函数中处理VSync信号

void DispSyncSource::onDispSyncEvent(nsecs_t when) {    VSyncSource::Callback* callback;    {        std::lock_guard lock(mCallbackMutex);        callback = mCallback;        if (mTraceVsync) {            mValue = (mValue + 1) % 2;            ATRACE_INT(mVsyncEventLabel.c_str(), mValue);        }    }    if (callback != nullptr) {        callback->onVSyncEvent(when);    }}

EventThread.h (class EventThread : public android::EventThread, private VSyncSource::Callback)

EventThread.cpp 实现 DispSync::Callback,在自身onVSyncEvent去创建Event事件

void EventThread::onVSyncEvent(nsecs_t timestamp) {    std::lock_guard lock(mMutex);    LOG_FATAL_IF(!mVSyncState);    mPendingEvents.push_back(makeVSync(mVSyncState->displayId, timestamp, ++mVSyncState->count));    mCondition.notify_all();}DisplayEventReceiver::Event makeVSync(PhysicalDisplayId displayId, nsecs_t timestamp,                                      uint32_t count) {    DisplayEventReceiver::Event event;    event.header = {DisplayEventReceiver::DISPLAY_EVENT_VSYNC, displayId, timestamp};    event.vsync.count = count;    return event;}

 EventThread.cpp threadMain循环处理Event事件

void EventThread::threadMain(std::unique_lock& lock) {    DisplayEventConsumers consumers;    while (mState != State::Quit) {        std::optional event;        // Determine next event to dispatch.        if (!mPendingEvents.empty()) {            event = mPendingEvents.front();            mPendingEvents.pop_front();            switch (event->header.type) {                case DisplayEventReceiver::DISPLAY_EVENT_HOTPLUG:                    if (event->hotplug.connected && !mVSyncState) {                        mVSyncState.emplace(event->header.displayId);                    } else if (!event->hotplug.connected && mVSyncState &&                               mVSyncState->displayId == event->header.displayId) {                        mVSyncState.reset();                    }                    break;                case DisplayEventReceiver::DISPLAY_EVENT_VSYNC:                    if (mInterceptVSyncsCallback) {                        mInterceptVSyncsCallback(event->header.timestamp);                    }                    break;            }        }        bool vsyncRequested = false;        // Find connections that should consume this event.        auto it = mDisplayEventConnections.begin();        while (it != mDisplayEventConnections.end()) {            if (const auto connection = it->promote()) {                vsyncRequested |= connection->vsyncRequest != VSyncRequest::None;                if (event && shouldConsumeEvent(*event, connection)) {                    consumers.push_back(connection);                }                ++it;            } else {                it = mDisplayEventConnections.erase(it);            }        }        if (!consumers.empty()) {            dispatchEvent(*event, consumers);            consumers.clear();        }        State nextState;        if (mVSyncState && vsyncRequested) {            nextState = mVSyncState->synthetic ? State::SyntheticVSync : State::VSync;        } else {            ALOGW_IF(!mVSyncState, "Ignoring VSYNC request while display is disconnected");            nextState = State::Idle;        }        if (mState != nextState) {            if (mState == State::VSync) {                mVSyncSource->setVSyncEnabled(false);            } else if (nextState == State::VSync) {                mVSyncSource->setVSyncEnabled(true);            }            mState = nextState;        }        if (event) {            continue;        }        // Wait for event or client registration/request.        if (mState == State::Idle) {            mCondition.wait(lock);        } else {            // Generate a fake VSYNC after a long timeout in case the driver stalls. When the            // display is off, keep feeding clients at 60 Hz.            const auto timeout = mState == State::SyntheticVSync ? 16ms : 1000ms;            if (mCondition.wait_for(lock, timeout) == std::cv_status::timeout) {                ALOGW_IF(mState == State::VSync, "Faking VSYNC due to driver stall");                LOG_FATAL_IF(!mVSyncState);                mPendingEvents.push_back(makeVSync(mVSyncState->displayId,                                                   systemTime(SYSTEM_TIME_MONOTONIC),                                                   ++mVSyncState->count));            }        }    }}

EventThread.cpp dispatchEvent 分发事件给EventThreadConnection

void EventThread::dispatchEvent(const DisplayEventReceiver::Event& event,                                const DisplayEventConsumers& consumers) {    for (const auto& consumer : consumers) {        switch (consumer->postEvent(event)) {            case NO_ERROR:                break;            case -EAGAIN:                // TODO: Try again if pipe is full.                ALOGW("Failed dispatching %s for %s", toString(event).c_str(),                      toString(*consumer).c_str());                break;            default:                // Treat EPIPE and other errors as fatal.                removeDisplayEventConnectionLocked(consumer);        }    }}status_t EventThreadConnection::postEvent(const DisplayEventReceiver::Event& event) {    ssize_t size = DisplayEventReceiver::sendEvents(&mChannel, &event, 1);    return size < 0 ? status_t(size) : status_t(NO_ERROR);}

EventThread.cpp EventThreadConnection::postEvent分发事件

status_t EventThreadConnection::postEvent(const DisplayEventReceiver::Event& event) {    ssize_t size = DisplayEventReceiver::sendEvents(&mChannel, &event, 1);    return size < 0 ? status_t(size) : status_t(NO_ERROR);}

DisplayEventReceiver.cpp EventThreadConnection通过DisplayEventReceiver::sendEvents静态方法利用mChannel(gui::BitTube)去发送事件.

public:    enum {        DISPLAY_EVENT_VSYNC = fourcc('v', 's', 'y', 'n'),        DISPLAY_EVENT_HOTPLUG = fourcc('p', 'l', 'u', 'g'),        DISPLAY_EVENT_CONFIG_CHANGED = fourcc('c', 'o', 'n', 'f'),    };    struct Event {        struct Header {            uint32_t type;            PhysicalDisplayId displayId;            nsecs_t timestamp __attribute__((aligned(8)));        };        struct VSync {            uint32_t count;        };        struct Hotplug {            bool connected;        };        struct Config {            int32_t configId;        };        Header header;        union {            VSync vsync;            Hotplug hotplug;            Config config;        };    };ssize_t DisplayEventReceiver::sendEvents(gui::BitTube* dataChannel,        Event const* events, size_t count){    return gui::BitTube::sendObjects(dataChannel, events, count);}

BitTube.cpp sendObjects 会利用内置的成对的socket发送事件.

    // send objects (sized blobs). All objects are guaranteed to be written or the call fails.    template     static ssize_t sendObjects(BitTube* tube, T const* events, size_t count) {        return sendObjects(tube, events, count, sizeof(T));    }ssize_t BitTube::sendObjects(BitTube* tube, void const* events, size_t count, size_t objSize) {    const char* vaddr = reinterpret_cast(events);    ssize_t size = tube->write(vaddr, count * objSize);    // should never happen because of SOCK_SEQPACKET    LOG_ALWAYS_FATAL_IF((size >= 0) && (size % static_cast(objSize)),                        "BitTube::sendObjects(count=%zu, size=%zu), res=%zd (partial events were "                        "sent!)",                        count, objSize, size);    // ALOGE_IF(size<0, "error %d sending %d events", size, count);    return size < 0 ? size : size / static_cast(objSize);}ssize_t BitTube::write(void const* vaddr, size_t size) {    ssize_t err, len;    do {        len = ::send(mSendFd, vaddr, size, MSG_DONTWAIT | MSG_NOSIGNAL);        // cannot return less than size, since we're using SOCK_SEQPACKET        err = len < 0 ? errno : 0;    } while (err == EINTR);    return err == 0 ? len : -err;}

到此为止,SufaceFlinger之下的VSync分发过程就到此为止了,此前分析是从hidl开始到SufaceFlinger结束的,因为从SufaceFlinger到app的发送过程需要先分析些前提,所以此处暂做一个小结.

onVsync( hardware::graphics::composer::V2_1::IComposerClient.h)
    --> onVsync(ComposerHal.h hardware::graphics::composer::V2_1::IComposerCallback)
    --> onVsyncReceived(SurfaceFlinger.cpp class SurfaceFlinger : private HWC2::ComposerCallback)
    --> addResyncSample(Scheduler.cpp)
    --> addResyncSample(DispSync.cpp 利用硬件VSync时间戳样本实时更新SW VSync模型)
    --> fireCallbackInvocations(DispSync.cpp)
    --> onDispSyncEvent(DispSyncSource final : public VSyncSource, private DispSync::Callback)
    --> onVSyncEvent(class EventThread : public android::EventThread, private VSyncSource::Callback)
    --> mPendingEvents.push_back(makeVSync)(EventThread.cpp生成类型为DisplayEventReceiver::DISPLAY_EVENT_VSYNC的DisplayEventReceiver::Event)
    threadMain(EventThread.cpp 循环读取DisplayEventReceiver::Event)
    --> mPendingEvents.front()/threadMain (EventThread.cpp 通过threadMain提取DisplayEventReceiver::Event)
    --> dispatchEvent(EventThread.cpp)
    --> postEvent(EventThread.cpp)
    -->static DisplayEventReceiver::sendEvents(DisplayEventReceiver.cpp)
    --> gui::BitTube::sendObjects(BitTube.h)
    --> sendObjects(BitTube.cpp)
    --> write(BitTube.cpp 利用socket发送数据)

以下是app与SF分别接受VSync的追踪

(3)VSync 从SurfaceFlinger到SurfaceFlinger的分发(SF VSync)

(a)SurfaceFlinger自己对于VSync的注册过程为

SurfaceFlinger.cpp SurfaceFlinger会先生成std::unique_ptr mEventQueue,之后在SurfaceFlinger::init()中利用mEventQueue的gui::BitTube实现VSync的socket接收数据

SurfaceFlinger::SurfaceFlinger(Factory& factory, SkipInitializationTag)      : mFactory(factory),        mPhaseOffsets(mFactory.createPhaseOffsets()),        mInterceptor(mFactory.createSurfaceInterceptor(this)),        mTimeStats(mFactory.createTimeStats()),        mEventQueue(mFactory.createMessageQueue()),        mCompositionEngine(mFactory.createCompositionEngine()) {}void SurfaceFlinger::onFirstRef(){    mEventQueue->init(this);}void SurfaceFlinger::init() {    /* */    mSfConnectionHandle = mScheduler->createConnection("sf", mPhaseOffsets->getCurrentSfOffset(),                                                       resyncCallback, [this](nsecs_t timestamp) {                                                           mInterceptor->saveVSyncEvent(timestamp);                                                       });    mEventQueue->setEventConnection(mScheduler->getEventConnection(mSfConnectionHandle));    /* */}

(b)SurfaceFlinger自己对于VSync的接收过程

MessageQueue.cpp MessageQueue的setEventConnection函数会利用EventThread中生成时预置的一个EventThreadConnection的stealReceiveChannel方法获取到EventThreadConnection的gui::BitTube,之后利用Handler传递给SurfaceFlinger

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++) {            if (buffer[i].header.type == DisplayEventReceiver::DISPLAY_EVENT_VSYNC) {                mHandler->dispatchInvalidate();                break;            }        }    }    return 1;}void MessageQueue::Handler::dispatchInvalidate() {    if ((android_atomic_or(eventMaskInvalidate, &mEventMask) & eventMaskInvalidate) == 0) {        mQueue.mLooper->sendMessage(this, Message(MessageQueue::INVALIDATE));    }}void MessageQueue::Handler::handleMessage(const Message& message) {    switch (message.what) {        case INVALIDATE:            android_atomic_and(~eventMaskInvalidate, &mEventMask);            mQueue.mFlinger->onMessageReceived(message.what);            break;        case REFRESH:            android_atomic_and(~eventMaskRefresh, &mEventMask);            mQueue.mFlinger->onMessageReceived(message.what);            break;    }}

SurfaceFlinger.cpp 会在onMessageReceived中处理接到Message事件.

void SurfaceFlinger::onMessageReceived(int32_t what) NO_THREAD_SAFETY_ANALYSIS {    ATRACE_CALL();    switch (what) {        case MessageQueue::INVALIDATE: {            bool frameMissed = previousFrameMissed();            bool hwcFrameMissed = mHadDeviceComposition && frameMissed;            bool gpuFrameMissed = mHadClientComposition && frameMissed;            ATRACE_INT("FrameMissed", static_cast(frameMissed));            ATRACE_INT("HwcFrameMissed", static_cast(hwcFrameMissed));            ATRACE_INT("GpuFrameMissed", static_cast(gpuFrameMissed));            if (frameMissed) {                mFrameMissedCount++;                mTimeStats->incrementMissedFrames();            }            if (hwcFrameMissed) {                mHwcFrameMissedCount++;            }            if (gpuFrameMissed) {                mGpuFrameMissedCount++;            }            if (mUseSmart90ForVideo) {                // This call is made each time SF wakes up and creates a new frame. It is part                // of video detection feature.                mScheduler->updateFpsBasedOnContent();            }            if (performSetActiveConfig()) {                break;            }            if (frameMissed && mPropagateBackpressure) {                if ((hwcFrameMissed && !gpuFrameMissed) ||                    mPropagateBackpressureClientComposition) {                    signalLayerUpdate();                    break;                }            }            // Now that we're going to make it to the handleMessageTransaction()            // call below it's safe to call updateVrFlinger(), which will            // potentially trigger a display handoff.            updateVrFlinger();            bool refreshNeeded = handleMessageTransaction();            refreshNeeded |= handleMessageInvalidate();            updateCursorAsync();            updateInputFlinger();            refreshNeeded |= mRepaintEverything;            if (refreshNeeded && CC_LIKELY(mBootStage != BootStage::BOOTLOADER)) {                // Signal a refresh if a transaction modified the window state,                // a new buffer was latched, or if HWC has requested a full                // repaint                signalRefresh();            }            break;        }        case MessageQueue::REFRESH: {            handleMessageRefresh();            break;        }    }}

SF VSync分发小结

eventReceiver (MessageQueue.cpp)
    -->dispatchInvalidate(MessageQueue.cpp)
    -->handleMessage(MessageQueue.cpp)
    -->onMessageReceived(SurfaceFlinger.cpp)

 

(4)VSync 从SurfaceFlinger到app的分发

(a)app在SurfaceFlinger中对于VSync的注册过程为:

SurfaceFlinger.cpp 其中在init()中生成专属app的ConnectionHandle,用于在Scheduler中找到自己.

void SurfaceFlinger::init() {    /* */    mAppConnectionHandle =            mScheduler->createConnection("app", mPhaseOffsets->getCurrentAppOffset(),                                         resyncCallback,                                         impl::EventThread::InterceptVSyncsCallback());    /* */}

Scheduler.cpp 生成专属app的EventThread用于接收VSync

sp Scheduler::createConnection(        const char* connectionName, int64_t phaseOffsetNs, ResyncCallback resyncCallback,        impl::EventThread::InterceptVSyncsCallback interceptCallback) {    const int64_t id = sNextId++;    ALOGV("Creating a connection handle with ID: %" PRId64 "\n", id);    std::unique_ptr eventThread =            makeEventThread(connectionName, mPrimaryDispSync.get(), phaseOffsetNs,                            std::move(interceptCallback));    auto eventThreadConnection =            createConnectionInternal(eventThread.get(), std::move(resyncCallback));    mConnections.emplace(id,                         std::make_unique(new ConnectionHandle(id),                                                      eventThreadConnection,                                                      std::move(eventThread)));    return mConnections[id]->handle;}std::unique_ptr Scheduler::makeEventThread(        const char* connectionName, DispSync* dispSync, int64_t phaseOffsetNs,        impl::EventThread::InterceptVSyncsCallback interceptCallback) {    std::unique_ptr eventThreadSource =            std::make_unique(dispSync, phaseOffsetNs, true, connectionName);    return std::make_unique(std::move(eventThreadSource),                                               std::move(interceptCallback), connectionName);}sp Scheduler::createConnectionInternal(EventThread* eventThread,                                                              ResyncCallback&& resyncCallback) {    return eventThread->createEventConnection(std::move(resyncCallback));}

以上是在SurfaceFlinger中生成了专属app的EventThread并注册到DispSync中,此EventThread一边在循环读取着DispSync传来的VSync的事件,一边等待着应用通过SurfaceFlinger在自己中注册应用的VSync接受器IDisplayEventConnection,以下从java层开始记录此注册过程:

ViewRootImpl.java 在ViewRootImpl构造过程中,会生成一个Choreographer,Choreographer是用来协调动画、输入和绘图的时间的

    public ViewRootImpl(Context context, Display display) {    /* */        mChoreographer = Choreographer.getInstance();    /* */    }

Choreographer.java 中会获取当前线程的独立的一个Choreographer实例,在new Choreographer中会new一个FrameDisplayEventReceiver.

    // Thread local storage for the choreographer.    private static final ThreadLocal sThreadInstance =            new ThreadLocal() {        @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;        }    };    /**     * Gets the choreographer for the calling thread.  Must be called from     * a thread that already has a {@link android.os.Looper} associated with it.     *     * @return The choreographer for this thread.     * @throws IllegalStateException if the thread does not have a looper.     */    public static Choreographer getInstance() {        return sThreadInstance.get();    }    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();        }        // b/68769804: For low FPS experiments.        setFPSDivisor(SystemProperties.getInt(ThreadedRenderer.DEBUG_FPS_DIVISOR, 1));    }

Choreographer.java FrameDisplayEventReceiver扩展至DisplayEventReceiver

    private final class FrameDisplayEventReceiver extends DisplayEventReceiver            implements Runnable {        public FrameDisplayEventReceiver(Looper looper, int vsyncSource) {            super(looper, vsyncSource);        }    }

DisplayEventReceiver.java 在其构造函数中会通过nativeInit把DisplayEventReceiver的弱引用传到Native层(方便后续通过反射回调),

    /**     * Creates a display event receiver.     *     * @param looper The looper to use when invoking callbacks.     * @param vsyncSource The source of the vsync tick. Must be on of the VSYNC_SOURCE_* values.     */    public DisplayEventReceiver(Looper looper, int vsyncSource) {        if (looper == null) {            throw new IllegalArgumentException("looper must not be null");        }        mMessageQueue = looper.getQueue();        mReceiverPtr = nativeInit(new WeakReference(this), mMessageQueue,                vsyncSource);        mCloseGuard.open("dispose");    }

android_view_DisplayEventReceiver.cpp nativeInit函数中NativeDisplayEventReceiver会在new的过程中给予其父类DisplayEventDispatcher的属性赋值,并通过receiver->initialize()与SurfaceFlinger发生联系.

NativeDisplayEventReceiver::NativeDisplayEventReceiver(JNIEnv* env,        jobject receiverWeak, const sp& messageQueue, jint vsyncSource) :        DisplayEventDispatcher(messageQueue->getLooper(),                static_cast(vsyncSource)),        mReceiverWeakGlobal(env->NewGlobalRef(receiverWeak)),        mMessageQueue(messageQueue) {    ALOGV("receiver %p ~ Initializing display event receiver.", this);}static jlong nativeInit(JNIEnv* env, jclass clazz, jobject receiverWeak,        jobject messageQueueObj, jint vsyncSource) {    sp messageQueue = android_os_MessageQueue_getMessageQueue(env, messageQueueObj);    if (messageQueue == NULL) {        jniThrowRuntimeException(env, "MessageQueue is not initialized.");        return 0;    }    sp receiver = new NativeDisplayEventReceiver(env,            receiverWeak, messageQueue, vsyncSource);    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(receiver.get());}

DisplayEventDispatcher.cpp 其属性mReceiver(DisplayEventReceiver)初始化,看到这个不陌生了把,DisplayEventReceiver的静态函数曾被SurfaceFlinger中调用过,用于BitTube的数据传递,此处在正好用到了它,另外在initialize()中,我们又看到了熟悉的mLooper->addFd,

DisplayEventDispatcher::DisplayEventDispatcher(const sp& looper,        ISurfaceComposer::VsyncSource vsyncSource) :        mLooper(looper), mReceiver(vsyncSource), mWaitingForVsync(false) {    ALOGV("dispatcher %p ~ Initializing display event dispatcher.", this);}status_t DisplayEventDispatcher::initialize() {    status_t result = mReceiver.initCheck();    if (result) {        ALOGW("Failed to initialize display event receiver, status=%d", result);        return result;    }    int rc = mLooper->addFd(mReceiver.getFd(), 0, Looper::EVENT_INPUT,            this, NULL);    if (rc < 0) {        return UNKNOWN_ERROR;    }    return OK;}

DisplayEventReceiver.cpp 此时是处于APP的Native运行中,那么是什么样的方法与SurfaceFlinger链接在一起的呢?

其实在BitTube创建之初,BitTube中已经生成了一对互相链接的socket,BitTube会记录这对socket的文件句柄(mReceiveFd,mSendFd),在DisplayEventReceiver的构造函数中利用IDisplayEventConnection的stealReceiveChannel方法,把此时的mReceiveFd替换为SurfaceFlinger中存在的一个BitTube的mReceiveFd,这样就形成了socket的跨线程通信.

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

*** 此处附上BitTube的跨线程通信原理:

app注册到SurfaceFlinger小结:

new ViewRootImpl(ViewRootImpl.java)
    -->getInstance(Choreographer.java)
    --> new Choreographer(Choreographer.java)
    --> new FrameDisplayEventReceiver(Choreographer.java)
    --> new DisplayEventReceiver(DisplayEventReceiver.java)
    --> nativeInit(android_view_DisplayEventReceiver.cpp)
    --> initialize(DisplayEventDispatcher.cpp)
    --> new DisplayEventReceiver(DisplayEventReceiver.cpp)
    --> stealReceiveChannel(DisplayEventReceiver.cpp)

 

(b)SurfaceFlinger分发VSync到app的过程:

DisplayEventDispatcher.cpp此实例中会在handleEvent中利用processPendingEvents读取VSync事件,并通过dispatchVsync传递出去

int DisplayEventDispatcher::handleEvent(int, int events, void*) {    if (events & (Looper::EVENT_ERROR | Looper::EVENT_HANGUP)) {        ALOGE("Display event receiver pipe was closed or an error occurred.  "                "events=0x%x", events);        return 0; // remove the callback    }    if (!(events & Looper::EVENT_INPUT)) {        ALOGW("Received spurious callback for unhandled poll event.  "                "events=0x%x", events);        return 1; // keep the callback    }    // Drain all pending events, keep the last vsync.    nsecs_t vsyncTimestamp;    PhysicalDisplayId vsyncDisplayId;    uint32_t vsyncCount;    if (processPendingEvents(&vsyncTimestamp, &vsyncDisplayId, &vsyncCount)) {        ALOGV("dispatcher %p ~ Vsync pulse: timestamp=%" PRId64 ", displayId=%"                ANDROID_PHYSICAL_DISPLAY_ID_FORMAT ", count=%d",                this, ns2ms(vsyncTimestamp), vsyncDisplayId, vsyncCount);        mWaitingForVsync = false;        dispatchVsync(vsyncTimestamp, vsyncDisplayId, vsyncCount);    }    return 1; // keep the callback}bool DisplayEventDispatcher::processPendingEvents(        nsecs_t* outTimestamp, PhysicalDisplayId* outDisplayId, uint32_t* outCount) {    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));        for (ssize_t i = 0; i < n; i++) {            const DisplayEventReceiver::Event& ev = buf[i];            switch (ev.header.type) {            case DisplayEventReceiver::DISPLAY_EVENT_VSYNC:                // Later vsync events will just overwrite the info from earlier                // ones. That's fine, we only care about the most recent.                gotVsync = true;                *outTimestamp = ev.header.timestamp;                *outDisplayId = ev.header.displayId;                *outCount = ev.vsync.count;                break;            case DisplayEventReceiver::DISPLAY_EVENT_HOTPLUG:                dispatchHotplug(ev.header.timestamp, ev.header.displayId, ev.hotplug.connected);                break;            case DisplayEventReceiver::DISPLAY_EVENT_CONFIG_CHANGED:                dispatchConfigChanged(ev.header.timestamp, ev.header.displayId, ev.config.configId);                break;            default:                ALOGW("dispatcher %p ~ ignoring unknown event type %#x", this, ev.header.type);                break;            }        }    }    if (n < 0) {        ALOGW("Failed to get events from display event dispatcher, status=%d", status_t(n));    }    return gotVsync;}

android_view_DisplayEventReceiver.cpp 此处class NativeDisplayEventReceiver : public DisplayEventDispatcher,并实现了其方法dispatchVsync,用于处理VSync.处理的方法是利用之前得到的java实例DisplayEventReceiver,反射使用其方法dispatchVsync

void NativeDisplayEventReceiver::dispatchVsync(nsecs_t timestamp, PhysicalDisplayId displayId,                                               uint32_t count) {    JNIEnv* env = AndroidRuntime::getJNIEnv();    ScopedLocalRef receiverObj(env, jniGetReferent(env, mReceiverWeakGlobal));    if (receiverObj.get()) {        ALOGV("receiver %p ~ Invoking vsync handler.", this);        env->CallVoidMethod(receiverObj.get(),                gDisplayEventReceiverClassInfo.dispatchVsync, timestamp, displayId, count);        ALOGV("receiver %p ~ Returned from vsync handler.", this);    }    mMessageQueue->raiseAndClearException(env, "dispatchVsync");}

DisplayEventReceiver.java dispatchVsync方法中调用了onVsync方法,我们需要取器子类中找

    // Called from native code.    @SuppressWarnings("unused")    @UnsupportedAppUsage    private void dispatchVsync(long timestampNanos, long physicalDisplayId, int frame) {        onVsync(timestampNanos, physicalDisplayId, frame);    }

Choreographer.java DisplayEventReceiver的子类FrameDisplayEventReceiver重写了onVsync方法,其又利用Message.obtain(mHandler, this)的方法,使得其继承自Runnable的run()方法可以在指定的时间之后运行当前Choreographer的线程中.

        @Override        public void onVsync(long timestampNanos, long physicalDisplayId, int frame) {            // Post the vsync event to the Handler.            // The idea is to prevent incoming vsync events from completely starving            // the message queue.  If there are no messages in the queue with timestamps            // earlier than the frame time, then the vsync event will be processed immediately.            // Otherwise, messages that predate the vsync event will be handled first.            long now = System.nanoTime();            if (timestampNanos > now) {                Log.w(TAG, "Frame time is " + ((timestampNanos - now) * 0.000001f)                        + " ms in the future!  Check that graphics HAL is generating vsync "                        + "timestamps using the correct timebase.");                timestampNanos = now;            }            if (mHavePendingVsync) {                Log.w(TAG, "Already have a pending vsync event.  There should only be "                        + "one at a time.");            } else {                mHavePendingVsync = true;            }            mTimestampNanos = timestampNanos;            mFrame = frame;            Message msg = Message.obtain(mHandler, this);            msg.setAsynchronous(true);            mHandler.sendMessageAtTime(msg, timestampNanos / TimeUtils.NANOS_PER_MS);        }

Choreographer.java 在FrameDisplayEventReceiver的run()方法中开始进入doFrame操作

    private final class FrameDisplayEventReceiver extends DisplayEventReceiver            implements Runnable {        @Override        public void run() {            mHavePendingVsync = false;            doFrame(mTimestampNanos, mFrame);        }    }

分发VSync到app的过程小结:

handleEvent(DisplayEventDispatcher.cpp)
    -->processPendingEvents(DisplayEventDispatcher.cpp)
    -->dispatchVsync(android_view_DisplayEventReceiver.cpp)
    -->dispatchVsync(DisplayEventReceiver.java 利用发射机制有native层调用)
    -->onVsync(Choreographer.java)
    -->sendMessageAtTime(Choreographer.java 指定时间运行run()方法)
    -->run(Choreographer.java)
    -->doFrame(Choreographer.java)

结尾出附上大神文章(https://www.jianshu.com/p/d3e4b1805c92)中的图用来作为总结:

 

更多相关文章

  1. 浅谈Java中Collections.sort对List排序的两种方法
  2. Python list sort方法的具体使用
  3. python list.sort()根据多个关键字排序的方法实现
  4. Android解析WindowManagerService(一)WMS的诞生
  5. Android中JNI的使用方法
  6. Android(安卓)LayoutInflater的获取及inflate()参数和返回值
  7. android关于activity的组成
  8. Android(安卓)Studio打包生成Jar包的方法(亲测可用)
  9. android屏幕旋转时,Activity不重新调用onCreate的方法

随机推荐

  1. 12:VMware Horizon View 8.0-创建即时克隆
  2. 数据流中的中位数
  3. 3-12(队列的结束以及树的开始)
  4. 原来我还有网络天赋
  5. 工欲善其事 必先利其器
  6. 软件测试行业状况报告2017
  7. Prometheus+Alertmanager配置邮件报警
  8. Playbook批量部署Docker
  9. 我的2017个人总结
  10. 自动化测试如何比较颜色