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的追踪

android Q 显示系统(一) VSync_第1张图片

(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的跨线程通信原理:

android Q 显示系统(一) VSync_第2张图片

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)中的图用来作为总结:

android Q 显示系统(一) VSync_第3张图片

 

更多相关文章

  1. Android Studio打包生成Jar包的方法(亲测可用)
  2. Android 中调试手段 打印函数调用栈信息
  3. Android 中broadcast 注册过程解析
  4. Android更新UI的方法
  5. Eclipse中编译Android工程时出现的问题解决方法。
  6. Android studio获取证书指纹 (SHA1)的方法
  7. Android 解析XML文件方法

随机推荐

  1. Android(安卓)UI架构(四)--SurfaceFlinge
  2. 四十二、Android完全退出应用程序
  3. android SDK 环境变量配置+ADT安装
  4. Android(安卓)RIL总体架构介绍
  5. SQL Server误区30日谈 第19天 Truncate表
  6. SQL Server误区30日谈 第18天 有关FileSt
  7. SQL Server误区30日谈 第16天 数据的损坏
  8. SQL Server误区30日谈 第17天 有关页校验
  9. SQL Server误区30日谈 第15天 CheckPoint
  10. SQL Server误区30日谈 第14天 清除日志后