android Q 显示系统(一) VSync

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张图片

 

你可能感兴趣的:(android,10,android,源码,android,显示)