Android12 SurfaceFlinger Vsync

Vsync可以控制系统绘图/合成的频率周期,是内容能够在正确的时机完整地显示在屏幕上
在Surfaceflinger中有一套SW-Vsync的机制,能够更灵活的控制app绘图与surfaceflinger合成的速度
SW-Vsync机制
从图中可以看出,DispSync接收hw-vsync作为输入,计算出Vsync的分发时机。对于其他关心硬件Vsync的组件,在指定的便宜以后发送SW-VSYNC,并且接收fence timestamp,来校准模型。当误差在接收范围内,便会关闭硬件VSYNC,只用该模型模拟的VSYNC 来控制整个系统绘制/合成速度。
于是,在这个机制当中,有两件事情就变得尤为重要:

  1. 如何建立VSYNC分发的机制
  2. 如何计算出正确分发SW-VSYNC的时机
    基于以上两点,本文将围绕以上两点进行说明:

分发

在分发的系统中,有几个比较重要的类,先来简单说明一下他们之间的关系
DispSyncSource
接收HW-Vsync,并更新计算出SW-Vsync的间隔
EventThread
接收Vsync信号,并分发给surfaceflinger 和 app等需要Vsync信号的进程
Connection
任何一个对VSYNC感兴趣都会在EventThread中抽象为一个connection
在这里插入图片描述
先来讲讲这个系统是怎么运转起来的
从surfacelinger 的初始化讲起
surfaceflinger::init()

void SurfaceFlinger::init() {
    ...
    // Process any initial hotplug and resulting display changes.
    processDisplayHotplugEventsLocked();
    ...
}

SurfaceFlinger::processDisplayHotplugEventsLocked(),在这里调用initscheduler,初始化整个Vsync系统

void SurfaceFlinger::processDisplayHotplugEventsLocked() {
    for (const auto& event : mPendingHotplugEvents) {
        ...
        if (event.connection == hal::Connection::CONNECTED) {
            ...
            if (it == mPhysicalDisplayTokens.end()) {
                ...

                if (event.hwcDisplayId == getHwComposer().getInternalHwcDisplayId()) {
                    initScheduler(state);//从这个里初始化整个VSYNC系统
                }

                mInterceptor->saveDisplayCreation(state);
            } else {
                ...
        } else {
            ...
            }
           ...
        }
       ...
    }
    ...
}

在initScheduler接口中,主要做了如下几件事情

  1. 实例化Scheduler对象,命名为mScheduler
  2. create two connection,one for surfaceflinger,another for app
  3. 将VsyncDispatch绑定到messageQueue的回调函数上,名字为 " sf "
  4. onPrimaryDisplayModeChanged
    下面分析每一步到底做了些什么
void SurfaceFlinger::initScheduler(const DisplayDeviceState& displayState) {
    if (mScheduler) {
        // In practice it's not allowed to hotplug in/out the primary display once it's been
        // connected during startup, but some tests do it, so just warn and return.
        ALOGW("Can't re-init scheduler");
        return;
    }
    const auto displayId = displayState.physical->id;
    scheduler::RefreshRateConfigs::Config config =
            {.enableFrameRateOverride = android::sysprop::enable_frame_rate_override(false),
             .frameRateMultipleThreshold =
                     base::GetIntProperty("debug.sf.frame_rate_multiple_threshold", 0)};
    mRefreshRateConfigs =
            std::make_unique<scheduler::RefreshRateConfigs>(displayState.physical->supportedModes,
                                                            displayState.physical->activeMode
                                                                    ->getId(),
                                                            config);
    const auto currRefreshRate = displayState.physical->activeMode->getFps();
    mRefreshRateStats = std::make_unique<scheduler::RefreshRateStats>(*mTimeStats, currRefreshRate,
                                                                      hal::PowerMode::OFF);

    mVsyncConfiguration = getFactory().createVsyncConfiguration(currRefreshRate);
    mVsyncModulator = sp<VsyncModulator>::make(mVsyncConfiguration->getCurrentConfigs());

    // start the EventThread
    mScheduler = getFactory().createScheduler(*mRefreshRateConfigs, *this);
    const auto configs = mVsyncConfiguration->getCurrentConfigs();
    const nsecs_t vsyncPeriod = currRefreshRate.getPeriodNsecs();
    mAppConnectionHandle =
            mScheduler->createConnection("app", mFrameTimeline->getTokenManager(),
                                         /*workDuration=*/configs.late.appWorkDuration,
                                         /*readyDuration=*/configs.late.sfWorkDuration,
                                         impl::EventThread::InterceptVSyncsCallback());
    mSfConnectionHandle =
            mScheduler->createConnection("appSf", mFrameTimeline->getTokenManager(),
                                         /*workDuration=*/std::chrono::nanoseconds(vsyncPeriod),
                                         /*readyDuration=*/configs.late.sfWorkDuration,
                                         [this](nsecs_t timestamp) {
                                             mInterceptor->saveVSyncEvent(timestamp);
                                         });

    mEventQueue->initVsync(mScheduler->getVsyncDispatch(), *mFrameTimeline->getTokenManager(),
                           configs.late.sfWorkDuration);

    mRegionSamplingThread =
            new RegionSamplingThread(*this, RegionSamplingThread::EnvironmentTimingTunables());
    mFpsReporter = new FpsReporter(*mFrameTimeline, *this);
    // Dispatch a mode change request for the primary display on scheduler
    // initialization, so that the EventThreads always contain a reference to a
    // prior configuration.
    //
    // This is a bit hacky, but this avoids a back-pointer into the main SF
    // classes from EventThread, and there should be no run-time binder cost
    // anyway since there are no connected apps at this point.
    mScheduler->onPrimaryDisplayModeChanged(mAppConnectionHandle, displayId,
                                            displayState.physical->activeMode->getId(),
                                            vsyncPeriod);
    static auto ignorePresentFences =
            base::GetBoolProperty("debug.sf.vsync_reactor_ignore_present_fences"s, false);
    mScheduler->setIgnorePresentFences(
            ignorePresentFences ||
            getHwComposer().hasCapability(hal::Capability::PRESENT_FENCE_IS_NOT_RELIABLE));
}
实例化Scheduler对象,命名为mScheduler

在surfaceflingerdefaultfacroty中真正去实例化Scheduler对象,这里的 callback = surfaceflinger

std::unique_ptr<Scheduler> DefaultFactory::createScheduler(
        const scheduler::RefreshRateConfigs& configs, ISchedulerCallback& callback) {
    return std::make_unique<Scheduler>(configs, callback);
}

Scheduler共有三个不同的构造函数,在实例化对象的时候差不多是一个从上到下的调用关系,初始化一些必要的成员变量。为了叙述方便,从上到下依次成为 C1,C2, C3。

//C1
Scheduler::Scheduler(const scheduler::RefreshRateConfigs& configs, ISchedulerCallback& callback)
      : Scheduler(configs, callback,
                  {.supportKernelTimer = sysprop::support_kernel_idle_timer(false),
                   .useContentDetection = sysprop::use_content_detection_for_refresh_rate(false)}) {
}

在C2中,调用了createVsyncSchedule,在其中创建和初始化了和VSync信号产生、分发相关的类对象和运行逻辑。tracker,dispatch,VsyncReactor对象实例化,返回VsyncScheduler结构体对象

Scheduler::VsyncSchedule Scheduler::createVsyncSchedule(bool supportKernelTimer) {
    auto clock = std::make_unique<scheduler::SystemClock>();
    auto tracker = createVSyncTracker();
    auto dispatch = createVSyncDispatch(*tracker);

    // TODO(b/144707443): Tune constants.
    constexpr size_t pendingFenceLimit = 20;
    auto controller =
            std::make_unique<scheduler::VSyncReactor>(std::move(clock), *tracker, pendingFenceLimit,
                                                      supportKernelTimer);
    return {std::move(controller), std::move(tracker), std::move(dispatch)};
}
//C2
Scheduler::Scheduler(const scheduler::RefreshRateConfigs& configs, ISchedulerCallback& callback,
                     Options options)
      : Scheduler(createVsyncSchedule(options.supportKernelTimer), configs, callback,
                  createLayerHistory(configs), options) {
    using namespace sysprop;

    const int setIdleTimerMs = base::GetIntProperty("debug.sf.set_idle_timer_ms"s, 0);

    if (const auto millis = setIdleTimerMs ? setIdleTimerMs : set_idle_timer_ms(0); millis > 0) {
        const auto callback = mOptions.supportKernelTimer ? &Scheduler::kernelIdleTimerCallback
                                                          : &Scheduler::idleTimerCallback;
        mIdleTimer.emplace(
                "IdleTimer", std::chrono::milliseconds(millis),
                [this, callback] { std::invoke(callback, this, TimerState::Reset); },
                [this, callback] { std::invoke(callback, this, TimerState::Expired); });
        mIdleTimer->start();
    }

    if (const int64_t millis = set_touch_timer_ms(0); millis > 0) {
        // Touch events are coming to SF every 100ms, so the timer needs to be higher than that
        mTouchTimer.emplace(
                "TouchTimer", std::chrono::milliseconds(millis),
                [this] { touchTimerCallback(TimerState::Reset); },
                [this] { touchTimerCallback(TimerState::Expired); });
        mTouchTimer->start();
    }

    if (const int64_t millis = set_display_power_timer_ms(0); millis > 0) {
        mDisplayPowerTimer.emplace(
                "DisplayPowerTimer", std::chrono::milliseconds(millis),
                [this] { displayPowerTimerCallback(TimerState::Reset); },
                [this] { displayPowerTimerCallback(TimerState::Expired); });
        mDisplayPowerTimer->start();
    }
}
//C3
Scheduler::Scheduler(VsyncSchedule schedule, const scheduler::RefreshRateConfigs& configs,
                     ISchedulerCallback& schedulerCallback,
                     std::unique_ptr<LayerHistory> layerHistory, Options options)
      : mOptions(options),
        mVsyncSchedule(std::move(schedule)),
        mLayerHistory(std::move(layerHistory)),
        mSchedulerCallback(schedulerCallback),
        mRefreshRateConfigs(configs),
        mPredictedVsyncTracer(
                base::GetBoolProperty("debug.sf.show_predicted_vsync", false)
                        ? std::make_unique<PredictedVsyncTracer>(*mVsyncSchedule.dispatch)
                        : nullptr) {
    mSchedulerCallback.setVsyncEnabled(false);
}

create two connection,one for surfaceflinger,another for app

接下来看看在createconnection中具体做了些什么(以 " appsf "为例)
这里解释一下一些变量的含义
workduration:client完成工作的时长,例如surfaceflinger完成一帧合成的时间
readyduration:对于app来说,完成一帧显示还要考虑sf合成的时间,因此这个值 = sf workduration;对于sf 来说,为0
earliestVsync:目标显示时间,the target display time。因此,callback应该在 earliestVsync 前 workduration + readyduration ns 前被dispatch

首先在 makePrimaryDispSyncSource 接口中 实例化了DispSyncSource对象,然后实例化了EventThread对象

Scheduler::ConnectionHandle Scheduler::createConnection(
        const char* connectionName, frametimeline::TokenManager* tokenManager,
        std::chrono::nanoseconds workDuration, std::chrono::nanoseconds readyDuration,
        impl::EventThread::InterceptVSyncsCallback interceptCallback) {
    auto vsyncSource = makePrimaryDispSyncSource(connectionName, workDuration, readyDuration);
    auto throttleVsync = makeThrottleVsyncCallback();
    auto getVsyncPeriod = makeGetVsyncPeriodFunction();
    auto eventThread = std::make_unique<impl::EventThread>(std::move(vsyncSource), tokenManager,
                                                           std::move(interceptCallback),
                                                           std::move(throttleVsync),
                                                           std::move(getVsyncPeriod));
    return createConnection(std::move(eventThread));
}

DispSyncSource构造函数中,vSyncDispatch为前面Scheduler中创建的对象。这里可以看到,传进来的name = “appsf”, 在mValue中被保存为了 “VSYNC-appsf”,这也与dump出来的结果是一致的。
然后还新建了一个CallbackRepeater对象

DispSyncSource::DispSyncSource(scheduler::VSyncDispatch& vSyncDispatch,
                               std::chrono::nanoseconds workDuration,
                               std::chrono::nanoseconds readyDuration, bool traceVsync,
                               const char* name)
      : mName(name),
        mValue(base::StringPrintf("VSYNC-%s", name), 0),
        mTraceVsync(traceVsync),
        mVsyncOnLabel(base::StringPrintf("VsyncOn-%s", name)),
        mWorkDuration(base::StringPrintf("VsyncWorkDuration-%s", name), workDuration),
        mReadyDuration(readyDuration) {
    mCallbackRepeater =
            std::make_unique<CallbackRepeater>(vSyncDispatch,
                                               std::bind(&DispSyncSource::onVsyncCallback, this,
                                                         std::placeholders::_1,
                                                         std::placeholders::_2,
                                                         std::placeholders::_3),
                                               name, workDuration, readyDuration,
                                               std::chrono::steady_clock::now().time_since_epoch());
}

来看看CallbackRepeater构造函数中做了些什么,
将DispSyncSource::onVsyncCallback 作为 callback函数保存下来

CallbackRepeater(VSyncDispatch& dispatch, VSyncDispatch::Callback cb, const char* name,
                     std::chrono::nanoseconds workDuration, std::chrono::nanoseconds readyDuration,
                     std::chrono::nanoseconds notBefore)
          : mName(name),
            mCallback(cb),
            mRegistration(dispatch,
                          std::bind(&CallbackRepeater::callback, this, std::placeholders::_1,
                                    std::placeholders::_2, std::placeholders::_3),
                          mName),
            mStarted(false),
            mWorkDuration(workDuration),
            mReadyDuration(readyDuration),
            mLastCallTime(notBefore) {}

并新建了一个 VSyncCallbackRegistration 对象,从这里可以看到,调用到了VSyncDispatchTimerQueue(为VsyncDispatch的实现类)的registercallback中,

VSyncCallbackRegistration::VSyncCallbackRegistration(VSyncDispatch& dispatch,
                                                     VSyncDispatch::Callback const& callbackFn,
                                                     std::string const& callbackName)
      : mDispatch(dispatch),
        mToken(dispatch.registerCallback(callbackFn, callbackName)),
        mValidToken(true) {}

回调函数是DispSyncSource::onVsyncCallback ,name = " appsf"

VSyncDispatchTimerQueue::CallbackToken VSyncDispatchTimerQueue::registerCallback(
        Callback const& callbackFn, std::string callbackName) {
    std::lock_guard lock(mMutex);
    return CallbackToken{
            mCallbacks
                    .emplace(++mCallbackToken,
                             std::make_shared<VSyncDispatchTimerQueueEntry>(callbackName,
                                                                            callbackFn,
                                                                            mMinVsyncDistance))
                    .first->first};
}

到这里,回调函数的绑定基本就结束了
我们再回头看看第二件事,实例化EventThread对象

auto eventThread = std::make_unique<impl::EventThread>(std::move(vsyncSource), tokenManager,
                                                           std::move(interceptCallback),
                                                           std::move(throttleVsync),
                                                           std::move(getVsyncPeriod));

看看EventThread的构造函数中做了什么
除了一些必要的成员变量赋值之外,还做了另外一件事,就是将eventthread 线程运行起来,入口函数为ThreadMain,并设置了线程优先级

EventThread::EventThread(std::unique_ptr<VSyncSource> vsyncSource,
                         android::frametimeline::TokenManager* tokenManager,
                         InterceptVSyncsCallback interceptVSyncsCallback,
                         ThrottleVsyncCallback throttleVsyncCallback,
                         GetVsyncPeriodFunction getVsyncPeriodFunction)
      : mVSyncSource(std::move(vsyncSource)),
        mTokenManager(tokenManager),
        mInterceptVSyncsCallback(std::move(interceptVSyncsCallback)),
        mThrottleVsyncCallback(std::move(throttleVsyncCallback)),
        mGetVsyncPeriodFunction(std::move(getVsyncPeriodFunction)),
        mThreadName(mVSyncSource->getName()) {

    LOG_ALWAYS_FATAL_IF(getVsyncPeriodFunction == nullptr,
            "getVsyncPeriodFunction must not be null");

    mVSyncSource->setCallback(this);

    mThread = std::thread([this]() NO_THREAD_SAFETY_ANALYSIS {
        std::unique_lock<std::mutex> lock(mMutex);
        threadMain(lock);
    });

    pthread_setname_np(mThread.native_handle(), mThreadName);

    pid_t tid = pthread_gettid_np(mThread.native_handle());

    // Use SCHED_FIFO to minimize jitter
    constexpr int EVENT_THREAD_PRIORITY = 2;
    struct sched_param param = {0};
    param.sched_priority = EVENT_THREAD_PRIORITY;
    if (pthread_setschedparam(mThread.native_handle(), SCHED_FIFO, &param) != 0) {
        ALOGE("Couldn't set SCHED_FIFO for EventThread");
    }

    set_sched_policy(tid, SP_FOREGROUND);
}

再来看看ThreadMain中的实现

  1. 如果有消息,对不同的消息有不同的处理。
    当收到connect的hotplug信号,并且mVSyncState不存在时,将对应的消息保存下来,在后面统一处理;
    当收到disconnect的hotplug信号,并且存在mVSyncState时,将对应display从mVSyncState 删去。
    这里的mVSyncState 记录的就是display的状态,即如果display连接后,mVSyncState 必不为空,反之为空
    当收到Vsync event时,这里的callback在createconnection中设置下来的,在“appsf”中对应 mInterceptor->saveVSyncEvent(timestamp);即把vsync消息保存下来
  2. 然后逐个寻找对应的consumer,找到之后dispatchEvent
  3. 后面更新线程状态,并通过线程状态判断是否需要产生 fake Vsync
  4. 值得一提的是,线程刚开始循环时,会block在mCondition.wait(lock);处,直到有connecction连接。
void EventThread::threadMain(std::unique_lock<std::mutex>& lock) {
    DisplayEventConsumers consumers;

    while (mState != State::Quit) {
        std::optional<DisplayEventReceiver::Event> event;

        // Determine next event to dispatch.
        if (!mPendingEvents.empty()) {
            event = mPendingEvents.front();
            mPendingEvents.pop_front();

            switch (event->header.type) {
                case DisplayEventReceiver::DISPLAY_EVENT_HOTPLUG:
                // 当收到connect的hotplug信号,并且mVSyncState不存在时,将对应的消息保存下来,在后面统一处理
                    if (event->hotplug.connected && !mVSyncState) {
                        mVSyncState.emplace(event->header.displayId);
                //当收到disconnect的hotplug信号,并且存在mVSyncState时,将对应display从mVSyncState 删去
                    } else if (!event->hotplug.connected && mVSyncState &&
                               mVSyncState->displayId == event->header.displayId) {
                        mVSyncState.reset();
                    }
                    break;

                case DisplayEventReceiver::DISPLAY_EVENT_VSYNC:
                    if (mInterceptVSyncsCallback) {
                    //这里的callback在createconnection中设置下来的,在“appsf”中对应mInterceptor->saveVSyncEvent(timestamp);
                    //即把vsync消息保存下来
                        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) {
        // 刚开始时会block在此处,直到有connection连接
            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 std::chrono::nanoseconds timeout =
                    mState == State::SyntheticVSync ? 16ms : 1000ms;
            if (mCondition.wait_for(lock, timeout) == std::cv_status::timeout) {
                if (mState == State::VSync) {
                    ALOGW("Faking VSYNC due to driver stall for thread %s", mThreadName);
                    std::string debugInfo = "VsyncSource debug info:\n";
                    mVSyncSource->dump(debugInfo);
                    // Log the debug info line-by-line to avoid logcat overflow
                    auto pos = debugInfo.find('\n');
                    while (pos != std::string::npos) {
                        ALOGW("%s", debugInfo.substr(0, pos).c_str());
                        debugInfo = debugInfo.substr(pos + 1);
                        pos = debugInfo.find('\n');
                    }
                }

                LOG_FATAL_IF(!mVSyncState);
                const auto now = systemTime(SYSTEM_TIME_MONOTONIC);
                const auto deadlineTimestamp = now + timeout.count();
                const auto expectedVSyncTime = deadlineTimestamp + timeout.count();
                const int64_t vsyncId = [&] {
                    if (mTokenManager != nullptr) {
                        return mTokenManager->generateTokenForPredictions(
                                {now, deadlineTimestamp, expectedVSyncTime});
                    }
                    return FrameTimelineInfo::INVALID_VSYNC_ID;
                }();
                mPendingEvents.push_back(makeVSync(mVSyncState->displayId, now,
                                                   ++mVSyncState->count, expectedVSyncTime,
                                                   deadlineTimestamp, vsyncId));
            }
        }
    }
}

那什么时候有connection连接进来呢,在createConnectionInternal中,调用eventThread->createEventConnection接口进行connection连接。

sp<EventThreadConnection> Scheduler::createConnectionInternal(
        EventThread* eventThread, ISurfaceComposer::EventRegistrationFlags eventRegistration) {
    return eventThread->createEventConnection([&] { resync(); }, eventRegistration);
}


在这个接口中,创建了一个新的对象,EventThreadConnection

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

构造函数中做了简单的成员变量赋值
并在onFirstRef接口中去registerconnection

EventThreadConnection::EventThreadConnection(
        EventThread* eventThread, uid_t callingUid, ResyncCallback resyncCallback,
        ISurfaceComposer::EventRegistrationFlags eventRegistration)
      : resyncCallback(std::move(resyncCallback)),
        mOwnerUid(callingUid),
        mEventRegistration(eventRegistration),
        mEventThread(eventThread),
        mChannel(gui::BitTube::DefaultSize) {}

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

registerDisplayEventConnection接口中,首先是将connection加入队列中,并通过mCondition.notify_all();通知线程解除block,即前面所说的block在mCondition.wait()

status_t EventThread::registerDisplayEventConnection(const sp<EventThreadConnection>& connection) {
    std::lock_guard<std::mutex> lock(mMutex);

    // this should never happen
    auto it = std::find(mDisplayEventConnections.cbegin(),
            mDisplayEventConnections.cend(), connection);
    if (it != mDisplayEventConnections.cend()) {
        ALOGW("DisplayEventConnection %p already exists", connection.get());
        mCondition.notify_all();
        return ALREADY_EXISTS;
    }

    mDisplayEventConnections.push_back(connection);
    mCondition.notify_all();
    return NO_ERROR;
}
将VsyncDispatch绑定到messageQueue的回调函数上,名字为 " sf "

接下来介绍一下messagequeue中回调函数的绑定过程
这里实例化了VSyncCallbackRegistration对象,与注册回调的流程相似,将MessageQueue::vsyncCallback作为回调函数设置下去,name 为 " sf " ,最终在VSyncDispatchTimerQueue中回调。

void MessageQueue::initVsync(scheduler::VSyncDispatch& dispatch,
                             frametimeline::TokenManager& tokenManager,
                             std::chrono::nanoseconds workDuration) {
    setDuration(workDuration);
    mVsync.tokenManager = &tokenManager;
    mVsync.registration = std::make_unique<
            scheduler::VSyncCallbackRegistration>(dispatch,
                                                  std::bind(&MessageQueue::vsyncCallback, this,
                                                            std::placeholders::_1,
                                                            std::placeholders::_2,
                                                            std::placeholders::_3),
                                                  "sf");
}
onPrimaryDisplayModeChanged

我们最后来看看onPrimaryDisplayModeChanged做了些什么
看代码,最后发现调用到了EventThread的onModeChanged

void Scheduler::onPrimaryDisplayModeChanged(ConnectionHandle handle, PhysicalDisplayId displayId,
                                            DisplayModeId modeId, nsecs_t vsyncPeriod) {
    {
        std::lock_guard<std::mutex> lock(mFeatureStateLock);
        // Cache the last reported modes for primary display.
        mFeatures.cachedModeChangedParams = {handle, displayId, modeId, vsyncPeriod};

        // Invalidate content based refresh rate selection so it could be calculated
        // again for the new refresh rate.
        mFeatures.contentRequirements.clear();
    }
    onNonPrimaryDisplayModeChanged(handle, displayId, modeId, vsyncPeriod);
}
void Scheduler::onNonPrimaryDisplayModeChanged(ConnectionHandle handle, PhysicalDisplayId displayId,
                                               DisplayModeId modeId, nsecs_t vsyncPeriod) {
    android::EventThread* thread;
    {
        std::lock_guard<std::mutex> lock(mConnectionsLock);
        RETURN_IF_INVALID_HANDLE(handle);
        thread = mConnections[handle].thread.get();
    }
    thread->onModeChanged(displayId, modeId, vsyncPeriod);
}

onModeChanged中,会自己生成一个event,并加入到列表中,然后通知threadmain去处理,通过dispatchEvent去分发

void EventThread::onModeChanged(PhysicalDisplayId displayId, DisplayModeId modeId,
                                nsecs_t vsyncPeriod) {
    std::lock_guard<std::mutex> lock(mMutex);

    mPendingEvents.push_back(makeModeChanged(displayId, modeId, vsyncPeriod));
    mCondition.notify_all();
}

这里的consumer实际就是EventThreadConnection,通过这个connection回调

void EventThread::dispatchEvent(const DisplayEventReceiver::Event& event,
                                const DisplayEventConsumers& consumers) {
    for (const auto& consumer : consumers) {
        DisplayEventReceiver::Event copy = event;
        if (event.header.type == DisplayEventReceiver::DISPLAY_EVENT_VSYNC) {
            copy.vsync.frameInterval = mGetVsyncPeriodFunction(consumer->mOwnerUid);
        }
        switch (consumer->postEvent(copy)) {
            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);
        }
    }
}

通过displayevetreceiver的sendEvents接口分发消息

status_t EventThreadConnection::postEvent(const DisplayEventReceiver::Event& event) {
    constexpr auto toStatus = [](ssize_t size) {
        return size < 0 ? status_t(size) : status_t(NO_ERROR);
    };

    if (event.header.type == DisplayEventReceiver::DISPLAY_EVENT_FRAME_RATE_OVERRIDE ||
        event.header.type == DisplayEventReceiver::DISPLAY_EVENT_FRAME_RATE_OVERRIDE_FLUSH) {
        mPendingEvents.emplace_back(event);
        if (event.header.type == DisplayEventReceiver::DISPLAY_EVENT_FRAME_RATE_OVERRIDE) {
            return status_t(NO_ERROR);
        }

        auto size = DisplayEventReceiver::sendEvents(&mChannel, mPendingEvents.data(),
                                                     mPendingEvents.size());
        mPendingEvents.clear();
        return toStatus(size);
    }

    auto size = DisplayEventReceiver::sendEvents(&mChannel, &event, 1);
    return toStatus(size);
}

到这里我们再来聊一聊前面说到的tracker,dispatch,VsyncReactor三个类
这三个类都是接口类,真正的实现在别的类中
VSyncTracker:实现类为VSyncPredictor,根据采样的硬件VSync,建立一个模拟的VSync模型,基于历史Vsync时间数据来预测未来Vsync信号发生的时间点
VSyncDispatch:实现类为VSyncDispatchTimerQueue,分发VSync回调事件
VsyncController:实现类为VSyncReactor,配合VSyncTracker进行硬件VSync的采样

计算

计算的过程稍微有点复杂,研究明白了再更新

  • 2
    点赞
  • 12
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
Android 中,View 是用户界面的基本组件,用于显示和处理用户界面上的各种元素。Android 13 中的 SurfaceFlinger 通过与 View 系统进行协作来实现定时刷新 View 的功能。 具体来说,Android 中的 View 系统提供了一个名为 Choreographer 的系统服务,它可以帮助应用程序实现定时刷新 View 的功能。Choreographer 可以协调应用程序中各种动画和 UI 事件的执行顺序,并在每一帧结束时向 SurfaceFlinger 发送 VSync 信号,从而触发 SurfaceFlinger 开始下一帧的渲染。 当应用程序中的某个 View 需要进行定时刷新时,可以通过以下步骤来实现: 1. 在 View 中创建一个 Choreographer.FrameCallback 对象,并重写其 doFrame() 方法来实现 View 的刷新逻辑; 2. 在 View 中注册 FrameCallback 对象,以便在每一帧结束时得到回调通知; 3. 在 View 的生命周期中,通过 Choreographer.getInstance().postFrameCallback(FrameCallback) 方法来注册和注销 FrameCallback 对象。 以下是一个示例代码: ```java public class MyView extends View implements Choreographer.FrameCallback { private Choreographer mChoreographer; public MyView(Context context) { super(context); mChoreographer = Choreographer.getInstance(); } @Override protected void onAttachedToWindow() { super.onAttachedToWindow(); mChoreographer.postFrameCallback(this); } @Override protected void onDetachedFromWindow() { super.onDetachedFromWindow(); mChoreographer.removeFrameCallback(this); } @Override public void doFrame(long frameTimeNanos) { // 在这里实现 View 的刷新逻辑 // ... // 重新注册 FrameCallback 对象 mChoreographer.postFrameCallback(this); } } ``` 在上述代码中,我们首先创建了一个 MyView 类,它继承自 View 类,并实现了 Choreographer.FrameCallback 接口。在 MyView 中,我们在 onAttachedToWindow() 方法中注册了 FrameCallback 对象,并在 onDetachedFromWindow() 方法中注销了 FrameCallback 对象。在 doFrame() 方法中,我们实现了 View 的刷新逻辑,并在最后重新注册了 FrameCallback 对象以实现定时刷新的功能。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值