Android 14 - 绘制体系 - VSync(1)

整体框架

VsyncConfiguration一些基本参数配置比如PhaseOffsetsWorkDuration

Scheduler:作为SF生成和派发VSync的整体调度器,主要面向SurfaceFlinger提供VSync相关接口。Scheduler包含对所有屏幕的VSync的控制。本身MessageQueue子类

RefreshRateSelector每个Display屏幕对应一个RefreshRateSelector用于基于屏幕支持的刷新率范围,选择一个合适Refresh RateFrame Rate传递VSyncSchedule作为软件VSync生成重要因素

VsyncScheduleVsync生成的调度器。每个屏幕对应一个VsyncSchedule。包含一个Tracker(VSyncPredictor)、一个Dispatch(VSyncDispatchTimerQueue)、一个Controller(VSyncReactor)。一方面对接硬件VSync信号开关一方面对接软件VSync计算输出

VSyncPredictor 在VsyncSchedule语境中一个Tracker负责综合各方因素根据算法由硬件VSync计算出软件VSync周期工具类

VSyncDispatchTimerQueue在VsyncSchedule语境中一个Dispather负责VSync分发使用者

VSyncCallbackRegistration代表一个VSync使用者的注册比如常见的针对上层应用的VSYNC-app、针对SurfaceFlinger合成的VSYNC-sf对应一个VSyncCallbackRegistration另外客户端还有一个VSYNC-appSf

EventThread处理客户端应用VSYNC的一个独立线程。期内维护一个不断请求VSYNC的死循环。比如VSYNC-app,一方面通过VSyncCallbackRegistration申请一次VSYNC另一方VSYNC生成通过ConnectionVSYNC发送给DisplayEventReceiver也就是VSYNC的终端接收者。一般情况两个EventThread一个是针对客户端应用侧VSYNC-app另一个客户端使用SF同步信号VSYNC-appSf

DisplayEventReceiver通过socket机制提供了一SF客户端应用传递VSYNC通道服务端EventThread通过DisplayEventReceiver发送VSYNC事件客户端Choreographer通过DisplayEventReceiver接收到VSYNC下发ViewRootImp驱动下一次绘制渲染

Android 13以后VSYNC架构变化之一是给SF使用的VSYNC-sf信号通过EventThread维护而是直接Schedule维护。供客户端应用使用的VSYN-app仍然EventThread维护另外新增一个VSYN-appSf信号也是EventThread维护主要作用如果客户端使用SF同步信号可以切换VSYNC-appSf这个信号Android 13之前这个机制通过VSYNC-sf实现Android 13SF专门使用VSYNC-sfEventThread剥离出来直接Schedule维护VSYN-appSf专门针对客户端

关键参数

探索VSync机制需要一些关键参数概念有所了解dumpsys SurfaceFlinger入手

屏幕刷新率

ColorMode设备支持ColorMode可根据系统设置应用自身设定的颜色模式最终决定使用那个ColorMode

deviceProductInfo: 屏幕设备信息manufacturerPnpId=QCMPlug and Play即插即用设备唯一识别码

activeMode:当前使用帧率模式

displayModes:当前屏幕支持帧率模式打印信息支持60Hz90Hz两种帧率

displayManagerPolicy当前采用帧率管理策略primaryRanges代表选取帧率通常采纳范围,如果用户通过setFrameRate手动指定一个帧率,其可能超出primaryRanges的范围;appRequestRanges代表用户可以指定帧率范围最终帧率可能超过primaryRanges但绝不会超过appRequestRanges

主要组件的初始化

SurfaceFlinger的初始化

SurfaceFlinger启动源于SystemServer执行main_surfaceflinger.cppmain方法

int main(int, char**) {
    ...
    sp<SurfaceFlinger> flinger = surfaceflinger::createSurfaceFlinger();
    ...
    flinger->init();
    ...
}

surfaceflinger::createSurfaceFlinger()实现platform/frameworks/native/services/surfaceflinger/SurfaceFlingerFactory.cpp

sp<SurfaceFlinger> createSurfaceFlinger() {
    static DefaultFactory factory;

    return sp<SurfaceFlinger>::make(factory);
}

随后调用SurfaceFlingerinit方法

platform/frameworks/native/services/surfaceflinger/SurfaceFlinger.cpp
void SurfaceFlinger::init() FTL_FAKE_GUARD(kMainThreadContext) {
    ...
    sp<const DisplayDevice> display;
    if (const auto indexOpt = mCurrentState.getDisplayIndex(getPrimaryDisplayIdLocked())) {
        const auto& displays = mCurrentState.displays;

        const auto& token = displays.keyAt(*indexOpt);
        const auto& state = displays.valueAt(*indexOpt);

        processDisplayAdded(token, state);
        mDrawingState.displays.add(token, state);

        display = getDefaultDisplayDeviceLocked();
    }
    ...
    initScheduler(display);
    ...
}

构建RefreshRateSelector

上面的代码中调用了processDisplayAdded添加主屏幕,后续挂载一个新屏幕也会走此流程:

void SurfaceFlinger::processDisplayAdded(const wp<IBinder>& displayToken,
                                         const DisplayDeviceState& state) {
     ...
     auto display = setupNewDisplayDeviceInternal(displayToken, std::move(compositionDisplay), state,
                                                 displaySurface, producer);
     ...
 }
 
 sp<DisplayDevice> SurfaceFlinger::setupNewDisplayDeviceInternal(
        const wp<IBinder>& displayToken,
        std::shared_ptr<compositionengine::Display> compositionDisplay,
        const DisplayDeviceState& state,
        const sp<compositionengine::DisplaySurface>& displaySurface,
        const sp<IGraphicBufferProducer>& producer) {
        ...
         creationArgs.refreshRateSelector =
                mPhysicalDisplays.get(physical->id)
                        .transform(&PhysicalDisplay::snapshotRef)
                        .transform([&](const display::DisplaySnapshot& snapshot) {
                            return std::make_shared<
                                    scheduler::RefreshRateSelector>(snapshot.displayModes(),
                                                                    creationArgs.activeModeId,
                                                                    config);
                        })
                        .value_or(nullptr);
        ...
        sp<DisplayDevice> display = getFactory().createDisplayDevice(creationArgs);
 
 }
                                             

上面每个Display构建一个refreshRateSelectorRefreshRateSelector

初始化Scheduler

VSync相关初始化都在initScheduler

void SurfaceFlinger::initScheduler(const sp<const DisplayDevice>& display) {
    const auto activeMode = display->refreshRateSelector().getActiveMode();
    const Fps activeRefreshRate = activeMode.fps;
    // 创建配置
    mVsyncConfiguration = getFactory().createVsyncConfiguration(activeRefreshRate);
    // 创建Scheduler
    mScheduler = std::make_unique<Scheduler>(static_cast<ICompositor&>(*this),
                                             static_cast<ISchedulerCallback&>(*this), features,
                                             std::move(modulatorPtr));
    // 注册屏幕每个屏幕构建一个VsyncSchedule对象
    mScheduler->registerDisplay(display->getPhysicalId(), display->holdRefreshRateSelector());
    mScheduler->startTimers();
    // 创建VSYNC-app对应EventThread
    mAppConnectionHandle =
		mScheduler->createEventThread(Scheduler::Cycle::Render,
									  mFrameTimeline->getTokenManager(),
									  /* workDuration */ configs.late.appWorkDuration,
									  /* readyDuration */ configs.late.sfWorkDuration);
    // 创建VSYNC-appSf对应的EventThread
mSfConnectionHandle =
		mScheduler->createEventThread(Scheduler::Cycle::LastComposite,
									  mFrameTimeline->getTokenManager(),
									  /* workDuration */ activeRefreshRate.getPeriod(),
									  /* readyDuration */ configs.late.sfWorkDuration);
    // 创建VSYNC-sf对应调度器
    mScheduler->initVsync(mScheduler->getVsyncSchedule()->getDispatch(),
                          *mFrameTimeline->getTokenManager(), configs.late.sfWorkDuration);
      ...
}

VsyncSchedule创建Scheduler::registerDisplay

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

void Scheduler::registerDisplay(PhysicalDisplayId displayId, RefreshRateSelectorPtr selectorPtr) {
    auto schedulePtr = std::make_shared<VsyncSchedule>(displayId, mFeatures,
                                                       [this](PhysicalDisplayId id, bool enable) {
                                                           onHardwareVsyncRequest(id, enable);
                                                       });

    registerDisplayInternal(displayId, std::move(selectorPtr), std::move(schedulePtr));
}

VsyncSchedule构造函数初始化

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

VsyncSchedule::VsyncSchedule(PhysicalDisplayId id, FeatureFlags features,
                             RequestHardwareVsync requestHardwareVsync)
      : mId(id),
        mRequestHardwareVsync(std::move(requestHardwareVsync)),
        mTracker(createTracker(id)),
        mDispatch(createDispatch(mTracker)),
        mController(createController(id, *mTracker, features)),
        mTracer(features.test(Feature::kTracePredictedVsync)
                        ? std::make_unique<PredictedVsyncTracer>(mDispatch)
                        : nullptr) {}

VsyncSchedule构造几个重要组件

VsyncSchedule::VsyncSchedule(PhysicalDisplayId id, FeatureFlags features,
                             RequestHardwareVsync requestHardwareVsync)
      : mId(id),
        mRequestHardwareVsync(std::move(requestHardwareVsync)),
        mTracker(createTracker(id)),
        mDispatch(createDispatch(mTracker)),
        mController(createController(id, *mTracker, features)),
        mTracer(features.test(Feature::kTracePredictedVsync)
                        ? std::make_unique<PredictedVsyncTracer>(mDispatch)
                        : nullptr) {}

其中mTracker本质上VSyncPredictor

VsyncSchedule::TrackerPtr VsyncSchedule::createTracker(PhysicalDisplayId id) {
    // TODO(b/144707443): Tune constants.
    constexpr nsecs_t kInitialPeriod = (60_Hz).getPeriodNsecs();
    constexpr size_t kHistorySize = 20;
    constexpr size_t kMinSamplesForPrediction = 6;
    constexpr uint32_t kDiscardOutlierPercent = 20;

    return std::make_unique<VSyncPredictor>(id, kInitialPeriod, kHistorySize,
                                            kMinSamplesForPrediction, kDiscardOutlierPercent);
}

mDispatch本质上VSyncDispatchTimerQueue

VsyncSchedule::DispatchPtr VsyncSchedule::createDispatch(TrackerPtr tracker) {
    using namespace std::chrono_literals;

    // TODO(b/144707443): Tune constants.
    constexpr std::chrono::nanoseconds kGroupDispatchWithin = 500us;
    constexpr std::chrono::nanoseconds kSnapToSameVsyncWithin = 3ms;

    return std::make_unique<VSyncDispatchTimerQueue>(std::make_unique<Timer>(), std::move(tracker),
                                                     kGroupDispatchWithin.count(),
                                                     kSnapToSameVsyncWithin.count());
}

mController本质上VSyncReactor

VsyncSchedule::ControllerPtr VsyncSchedule::createController(PhysicalDisplayId id,
                                                             VsyncTracker& tracker,
                                                             FeatureFlags features) {
    // TODO(b/144707443): Tune constants.
    constexpr size_t kMaxPendingFences = 20;
    const bool hasKernelIdleTimer = features.test(Feature::kKernelIdleTimer);

    auto reactor = std::make_unique<VSyncReactor>(id, std::make_unique<SystemClock>(), tracker,
                                                  kMaxPendingFences, hasKernelIdleTimer);

    reactor->setIgnorePresentFences(!features.test(Feature::kPresentFences));
    return reactor;
}

VSYNC-appVSYNC-appSf这两个信号是在EventThread维护看下createEventThread

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

ConnectionHandle Scheduler::createEventThread(Cycle cycle,
                                              frametimeline::TokenManager* tokenManager,
                                              std::chrono::nanoseconds workDuration,
                                              std::chrono::nanoseconds readyDuration) {
  // 根据cycle参数不同选择app还是appSf
    auto eventThread = std::make_unique<impl::EventThread>(cycle == Cycle::Render ? "app" : "appSf",
                                                           getVsyncSchedule(), tokenManager,
                                                           makeThrottleVsyncCallback(),
                                                           makeGetVsyncPeriodFunction(),
                                                           workDuration, readyDuration);

    auto& handle = cycle == Cycle::Render ? mAppConnectionHandle : mSfConnectionHandle;
    // 创建Connection
    handle = createConnection(std::move(eventThread));
    return handle;
}

EventThread构造函数

EventThread::EventThread(const char* name, std::shared_ptr<scheduler::VsyncSchedule> vsyncSchedule,
                         android::frametimeline::TokenManager* tokenManager,
                         ThrottleVsyncCallback throttleVsyncCallback,
                         GetVsyncPeriodFunction getVsyncPeriodFunction,
                         std::chrono::nanoseconds workDuration,
                         std::chrono::nanoseconds readyDuration)
      : mThreadName(name),
      // ATRACE名称
        mVsyncTracer(base::StringPrintf("VSYNC-%s", name), 0),
        // VSYNC计算时使用的偏移量
        mWorkDuration(base::StringPrintf("VsyncWorkDuration-%s", name), workDuration),
        // VSYNC计算时使用的偏移量
        mReadyDuration(readyDuration),
        mVsyncSchedule(std::move(vsyncSchedule)),
        // 一个VSYNC请求者的具体处理
        mVsyncRegistration(mVsyncSchedule->getDispatch(), createDispatchCallback()/*VSync生成后的回调函数*/, name),
        mTokenManager(tokenManager),
        mThrottleVsyncCallback(std::move(throttleVsyncCallback)),
        mGetVsyncPeriodFunction(std::move(getVsyncPeriodFunction)) {
    LOG_ALWAYS_FATAL_IF(getVsyncPeriodFunction == nullptr,
            "getVsyncPeriodFunction must not be null");

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

上面方法通过createConnection创建VSync事件派发通道

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

ConnectionHandle Scheduler::createConnection(std::unique_ptr<EventThread> eventThread) {
    const ConnectionHandle handle = ConnectionHandle{mNextConnectionHandleId++};
    ALOGV("Creating a connection handle with ID %" PRIuPTR, handle.id);

    auto connection = createConnectionInternal(eventThread.get());

    std::lock_guard<std::mutex> lock(mConnectionsLock);
    mConnections.emplace(handle, Connection{connection, std::move(eventThread)});
    return handle;
}

sp<EventThreadConnection> Scheduler::createConnectionInternal(
        EventThread* eventThread, EventRegistrationFlags eventRegistration,
        const sp<IBinder>& layerHandle) {
    int32_t layerId = static_cast<int32_t>(LayerHandle::getLayerId(layerHandle));
    auto connection = eventThread->createEventConnection([&] { resync(); }, eventRegistration);
    mLayerHistory.attachChoreographer(layerId, connection);
    return connection;
}

最终是由EventThread创建Connection:

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

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

VSYNC-app的请求流程

VSYNC-appEventThread维护VSYNC-app触发多种因素包括新屏幕挂载客户端主动请求EVentThread线程内部自发

EventThread内部自发为例

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();

            if (event->header.type == 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();
                }
            }
        }

        bool vsyncRequested = false;

        // Find connections that should consume this event.
        auto it = mDisplayEventConnections.begin();
        while (it != mDisplayEventConnections.end()) {
            if (const auto connection = it->promote()) {
                if (event && shouldConsumeEvent(*event, connection)) {
                    consumers.push_back(connection);
                }

                vsyncRequested |= connection->vsyncRequest != VSyncRequest::None;

                ++it;
            } else {
                it = mDisplayEventConnections.erase(it);
            }
        }

        if (!consumers.empty()) {
            dispatchEvent(*event, consumers);
            consumers.clear();
        }

        if (mVSyncState && vsyncRequested) {
            mState = mVSyncState->synthetic ? State::SyntheticVSync : State::VSync;
        } else {
            ALOGW_IF(!mVSyncState, "Ignoring VSYNC request while display is disconnected");
            mState = State::Idle;
        }

        if (mState == State::VSync) {
            const auto scheduleResult =
                    mVsyncRegistration.schedule({.workDuration = mWorkDuration.get().count(),
                                                 .readyDuration = mReadyDuration.count(),
                                                 .earliestVsync = mLastVsyncCallbackTime.ns()});
            LOG_ALWAYS_FATAL_IF(!scheduleResult, "Error scheduling callback");
        } else {
            mVsyncRegistration.cancel();
        }

        if (!mPendingEvents.empty()) {
            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 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);
                }

                LOG_FATAL_IF(!mVSyncState);
                const auto now = systemTime(SYSTEM_TIME_MONOTONIC);
                const auto deadlineTimestamp = now + timeout.count();
                const auto expectedVSyncTime = deadlineTimestamp + timeout.count();
                mPendingEvents.push_back(makeVSync(mVSyncState->displayId, now,
                                                   ++mVSyncState->count, expectedVSyncTime,
                                                   deadlineTimestamp));
            }
        }
    }
    // cancel any pending vsync event before exiting
    mVsyncRegistration.cancel();
}

触发VSYNC请求

const auto scheduleResult =

mVsyncRegistration.schedule({.workDuration = mWorkDuration.get().count(),

.readyDuration = mReadyDuration.count(),

.earliestVsync = mLastVsyncCallbackTime.ns()});

LOG_ALWAYS_FATAL_IF(!scheduleResult, "Error scheduling callback");

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

ScheduleResult VSyncCallbackRegistration::schedule(VSyncDispatch::ScheduleTiming scheduleTiming) {
    if (!mToken) {
        return std::nullopt;
    }
    return mDispatch->schedule(*mToken, scheduleTiming);
}

mDispatchVSyncDispatchTimerQueue同一个文件

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

ScheduleResult VSyncDispatchTimerQueue::schedule(CallbackToken token,
                                                 ScheduleTiming scheduleTiming) {
    std::lock_guard lock(mMutex);
    return scheduleLocked(token, scheduleTiming);
}

ScheduleResult VSyncDispatchTimerQueue::scheduleLocked(CallbackToken token,
                                                       ScheduleTiming scheduleTiming) {
    auto it = mCallbacks.find(token);
    if (it == mCallbacks.end()) {
        return {};
    }
    auto& callback = it->second;
    auto const now = mTimeKeeper->now();

    /* If the timer thread will run soon, we'll apply this work update via the callback
     * timer recalculation to avoid cancelling a callback that is about to fire. */
    auto const rearmImminent = now > mIntendedWakeupTime;
    if (CC_UNLIKELY(rearmImminent)) {
        callback->addPendingWorkloadUpdate(scheduleTiming);
        return getExpectedCallbackTime(*mTracker, now, scheduleTiming);
    }

    const ScheduleResult result = callback->schedule(scheduleTiming, *mTracker, now);
    if (!result.has_value()) {
        return {};
    }

    if (callback->wakeupTime() < mIntendedWakeupTime - mTimerSlack) {
        rearmTimerSkippingUpdateFor(now, it);
    }

    return result;
}

这里callbackVSyncDispatchTimerQueueEntry具体实现VSyncDispatchTimerQueue.cpp文件

ScheduleResult VSyncDispatchTimerQueueEntry::schedule(VSyncDispatch::ScheduleTiming timing,
                                                      VSyncTracker& tracker, nsecs_t now) {
    auto nextVsyncTime = tracker.nextAnticipatedVSyncTimeFrom(
            std::max(timing.earliestVsync, now + timing.workDuration + timing.readyDuration));
    auto nextWakeupTime = nextVsyncTime - timing.workDuration - timing.readyDuration;

    bool const wouldSkipAVsyncTarget =
            mArmedInfo && (nextVsyncTime > (mArmedInfo->mActualVsyncTime + mMinVsyncDistance));
    bool const wouldSkipAWakeup =
            mArmedInfo && ((nextWakeupTime > (mArmedInfo->mActualWakeupTime + mMinVsyncDistance)));
    if (wouldSkipAVsyncTarget && wouldSkipAWakeup) {
        return getExpectedCallbackTime(nextVsyncTime, timing);
    }

    nextVsyncTime = adjustVsyncIfNeeded(tracker, nextVsyncTime);
    nextWakeupTime = nextVsyncTime - timing.workDuration - timing.readyDuration;

    auto const nextReadyTime = nextVsyncTime - timing.readyDuration;
    mScheduleTiming = timing;
    mArmedInfo = {nextWakeupTime, nextVsyncTime, nextReadyTime};
    return getExpectedCallbackTime(nextVsyncTime, timing);
}

这里就是计算下一次VSync的地方了。tracker就是VSyncPredictor计算VSync核心

上面VSyncDispatchTimerQueue::scheduleLockedschedule计算时间调用

rearmTimerSkippingUpdateForrearmTimerSkippingUpdateFor设置一个Alarm定时执行VSync回调

void VSyncDispatchTimerQueue::rearmTimerSkippingUpdateFor(
        nsecs_t now, CallbackMap::iterator const& skipUpdateIt) {
        ...
        setTimer(*min, now);
        ...
}

void VSyncDispatchTimerQueue::setTimer(nsecs_t targetTime, nsecs_t /*now*/) {
    mIntendedWakeupTime = targetTime;
    mTimeKeeper->alarmAt(std::bind(&VSyncDispatchTimerQueue::timerCallback, this),
                         mIntendedWakeupTime);
    mLastTimerSchedule = mTimeKeeper->now();
}

这里timerCallbackEventThread这个方法

scheduler::VSyncDispatch::Callback EventThread::createDispatchCallback() {
    return [this](nsecs_t vsyncTime, nsecs_t wakeupTime, nsecs_t readyTime) {
        onVsync(vsyncTime, wakeupTime, readyTime);
    };
}

void EventThread::onVsync(nsecs_t vsyncTime, nsecs_t wakeupTime, nsecs_t readyTime) {
    std::lock_guard<std::mutex> lock(mMutex);
    mLastVsyncCallbackTime = TimePoint::fromNs(vsyncTime);

    LOG_FATAL_IF(!mVSyncState);
    mVsyncTracer = (mVsyncTracer + 1) % 2;
    mPendingEvents.push_back(makeVSync(mVSyncState->displayId, wakeupTime, ++mVSyncState->count,
                                       vsyncTime, readyTime));
    mCondition.notify_all();
}

Vsync信号将会封装Event放入mPendingEvents

VSYNC-app的分发过程

之前threadMain方法代码

if (!mPendingEvents.empty()) {
            event = mPendingEvents.front();
            mPendingEvents.pop_front();

            if (event->header.type == 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();
                }
            }
        }
...
if (!consumers.empty()) {
    dispatchEvent(*event, consumers);
    consumers.clear();
}

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) {
            const int64_t frameInterval = mGetVsyncPeriodFunction(consumer->mOwnerUid);
            copy.vsync.vsyncData.frameInterval = frameInterval;
            generateFrameTimeline(copy.vsync.vsyncData, frameInterval, copy.header.timestamp,
                                  event.vsync.vsyncData.preferredExpectedPresentationTime(),
                                  event.vsync.vsyncData.preferredDeadlineTimestamp());
        }
        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);
        }
    }
}

这里consumerEventThreadConnection

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

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);
}

DisplayEventReceiver::sendEvents最终客户端

ssize_t DisplayEventReceiver::sendEvents(gui::BitTube* dataChannel,
        Event const* events, size_t count)
{
    return gui::BitTube::sendObjects(dataChannel, events, count);
}

BitTube通过socket事件分发客户端的Choreographer

VSYNC-sf的请求和分发

VSYNC-sf触发SurfaceFlinger::initScheduler调用MessageQueue::initVsync

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

void MessageQueue::initVsync(std::shared_ptr<scheduler::VSyncDispatch> dispatch,
                             frametimeline::TokenManager& tokenManager,
                             std::chrono::nanoseconds workDuration) {
    std::unique_ptr<scheduler::VSyncCallbackRegistration> oldRegistration;
    {
        std::lock_guard lock(mVsync.mutex);
        mVsync.workDuration = workDuration;
        mVsync.tokenManager = &tokenManager;
        oldRegistration = onNewVsyncScheduleLocked(std::move(dispatch));
    }

    // See comments in onNewVsyncSchedule. Today, oldRegistration should be
    // empty, but nothing prevents us from calling initVsync multiple times, so
    // go ahead and destruct it outside the lock for safety.
    oldRegistration.reset();
}

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

std::unique_ptr<scheduler::VSyncCallbackRegistration> MessageQueue::onNewVsyncScheduleLocked(
        std::shared_ptr<scheduler::VSyncDispatch> dispatch) {
    const bool reschedule = mVsync.registration &&
            mVsync.registration->cancel() == scheduler::CancelResult::Cancelled;
    auto oldRegistration = std::move(mVsync.registration);
    mVsync.registration = std::make_unique<
            scheduler::VSyncCallbackRegistration>(std::move(dispatch),
                                                  std::bind(&MessageQueue::vsyncCallback, this,
                                                            std::placeholders::_1,
                                                            std::placeholders::_2,
                                                            std::placeholders::_3),
                                                  "sf");
    if (reschedule) {
        mVsync.scheduledFrameTime =
                mVsync.registration->schedule({.workDuration = mVsync.workDuration.get().count(),
                                               .readyDuration = 0,
                                               .earliestVsync = mVsync.lastCallbackTime.ns()});
    }
    return oldRegistration;
}

可以看到这里VSYNC信号命名“sf”mVsync.registration->schedule此处调用VSync生成过程前面VSync-app相同。但这里回调函数vsyncCallback

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

void MessageQueue::vsyncCallback(nsecs_t vsyncTime, nsecs_t targetWakeupTime, nsecs_t readyTime) {
    ATRACE_CALL();
    // Trace VSYNC-sf
    mVsync.value = (mVsync.value + 1) % 2;

    const auto expectedVsyncTime = TimePoint::fromNs(vsyncTime);
    {
        std::lock_guard lock(mVsync.mutex);
        mVsync.lastCallbackTime = expectedVsyncTime;
        mVsync.scheduledFrameTime.reset();
    }

    const auto vsyncId = VsyncId{mVsync.tokenManager->generateTokenForPredictions(
            {targetWakeupTime, readyTime, vsyncTime})};

    mHandler->dispatchFrame(vsyncId, expectedVsyncTime);
}

MessageQueue本身一个消息队列实现这里看到收到VSync回调,通过mHandler->dispatchFrame抛到队列最终执行

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

void MessageQueue::Handler::handleMessage(const Message&) {
    mFramePending.store(false);
    mQueue.onFrameSignal(mQueue.mCompositor, mVsyncId, mExpectedVsyncTime);
}

最后回调

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

void Scheduler::onFrameSignal(ICompositor& compositor, VsyncId vsyncId,
                              TimePoint expectedVsyncTime) {
          ...
          if (!compositor.commit(pacesetterId, targets)) return;
          ...
          const auto resultsPerDisplay = compositor.composite(pacesetterId, targeters);
  }

这里的compositor是SurfaceFlinger。接下来就是由SF进行合成工作

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:/a/651920.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

影响所有股票、债券和ETF交易!一文看懂美国“T+1”结算新规

T1对投资者有何好处&#xff1f;有哪些风险&#xff1f;T1已经到来&#xff0c;T0还远吗&#xff1f; 美股将在本周迎来历史性时刻。 从当地时间5月28日开始&#xff0c;美股交易结算周期将由T2缩短至T1&#xff0c;即投资者当天卖出的股票&#xff0c;在交易后一个工作日就能…

[Python]pyenv 环境配置

。pip install pyenv安装 / 去Git 下载pyenv版本安装 。安装好后控制台输入pyenv查看版本 。pyenv install --list列出所有pyenv可以支持的python版本 。pyenv install 3.9.7 安装指定的版本 。在pycharm里&#xff0c;可以选中项目&#xff0c;点击File-Settings&#xff0…

如何评价 OpenAI 最新发布支持实时语音对话的模型GPT-4o?OpenAI发完GTP-4o,国内大模型行业还有哪些机会?

文章目录 OpenAI发完GTP-4o&#xff0c;国内大模型行业还有哪些机会&#xff1f;详细了解一下OpenAI最新发布的支持实时语音对话的模型GPT-4o国内大模型如何寻找发展机会&#xff1f;想要发展技术必须要创新与追赶或许应用场景拓展也是一种出路产业生态构建 ChatGPT 问世才 17 …

大字体学生出勤记录系统网页源码

源码介绍 上课需要一个个点名记录出勤情况&#xff0c;就借助AI制作了一个网页版学生出勤记录系统&#xff0c; 大字体显示学生姓名和照片&#xff0c;让坐在最后排学生也能看清楚&#xff0c;显示姓名同时会语音播报姓名&#xff0c; 操作很简单&#xff0c;先导入学生姓名…

制作ARM架构 docker镜像

docker简介 docker客户端 Docker 客户端有两种替代选项:名为 docker 的命令行应用程序或名为 Docker Desktop 的基于图形用户界面 (GUI) 的应用程序。 CLI 和 Docker Desktop 均与 Docker 服务器交互。 来自 CLI 或 Docker Desktop 的 docker 命令使用 Docker REST API 将指…

C++ | Leetcode C++题解之第116题填充每个节点的下一个右侧节点指针

题目&#xff1a; 题解&#xff1a; class Solution { public:Node* connect(Node* root) {if (root nullptr) {return root;}// 从根节点开始Node* leftmost root;while (leftmost->left ! nullptr) {// 遍历这一层节点组织成的链表&#xff0c;为下一层的节点更新 next…

Android LAME原生音频

前言 我想大家都做过录音的功能吧&#xff0c;首先想到的是不是MediaRecorder&#xff1f;今天我们不用MediaRecorder&#xff0c;而是使用LAME库自己编译音频编码模块&#xff0c;很明显&#xff0c;这个需要用到NDK。凡是涉及到音视频编解码这块的&#xff0c;都需要用到And…

STM32H750外设之ADC通道选择

目录 概述 1 通道选择功能介绍 2 通道选择&#xff08; SQRx、 JSQRx&#xff09; 2.1 通道复用 2.1.1 通道介绍 2.1.2 通道框图 2.2 转换分组 2.3 内部专用通道 3 通道预选寄存器 (ADCx_PCSEL) 3.1 功能介绍 3.2 预选通道寄存器 概述 本位主要介绍STM32H750外设之…

2024年03月 Python(三级)真题解析#中国电子学会#全国青少年软件编程等级考试

Python等级考试(1~6级)全部真题・点这里 一、单选题(共25题,共50分) 第1题 在Python中,hex(2023)的功能是?( ) A:将十进制数2023转化成十六进制数 B:将十进制数2023转化成八进制数 C:将十六进制数2023转化成十进制数 D:将八进制数2023转化成十进制数 答案:A …

迭代器模式(行为型)

目录 一、前言 二、迭代器模式 三、总结 一、前言 迭代器模式(Iterator Pattern&#xff09;是一种行为型设计模式&#xff0c;提供一种方法顺序访问一个聚合对象中各个元素&#xff0c;而又不暴露该对象的内部表示。总的来说就是分离了集合对象的遍历行为&#xff0c;抽象出…

深度学习环境安装教程-anaconda-python-pytorch

首先是anaconda的安装&#xff0c;可以从下面地址下载安装包 Index of /anaconda/archive/ | 清华大学开源软件镜像站 | Tsinghua Open Source Mirror 尽量选择最新的日期的anaconda进行安装&#xff0c;我这里是windows电脑&#xff0c;因此选择了windos-x86_64.exe&#xf…

TIM(Timer)简介

TIM&#xff08;Timer&#xff09;定时器介绍 定时器可以对输入的时钟进行计数&#xff0c;并在计数值达到设定值时触发中断16位计数器、预分频器、自动重装寄存器的时基单元&#xff0c;在72MHz计数时钟下可以实现最大59.65s的定时不仅具备基本的定时中断功能&#xff0c;而且…

软件测试金字塔,对号入座,你在哪层?

自从学习了软件测试,脑袋也清晰了,目标也明确了,就是不知道学到哪里了.中间有很多的困难也有很多成就感,你目前在那个阶段呢? 初级测试工程师 技能要求:需求分析,使用等价类边界值等方法进行用例设计,执行功能测试,发现提交跟踪bug,使用禅道,会在测试中会操作数据库进行检查和…

DSPy - prompt 优化

文章目录 一、关于 DSPy与神经网络的类比常见问题解答**DSPy 优化器可以调整什么&#xff1f;****我应该如何使用 DSPy 完成我的任务&#xff1f;****如果我对提示或合成数据生成有更好的想法怎么办&#xff1f;**DSPy 代表什么&#xff1f; 二、安装三、文档A) 教程B) 指南C) …

python+pymysql对数据库进行增、删、改、查操作

一、概述 接口测试中&#xff0c;应用到数据库操作的场景&#xff1a; 1.校验测试数据 接口发送请求后明确会对数据库中的某个字段进行修改&#xff08;编辑&#xff0c;更新、删除操作&#xff09;&#xff0c;但&#xff0c;响应结果中无该字段数据时。 例如&#xff1a;删…

读人工智能时代与人类未来笔记16_科学发现

1. 科学发现 1.1. 科学认识的发展往往涉及理论和实验之间的巨大差距以及大量的试错 1.2. 模型不是像传统的那样来自理论理解&#xff0c;而是来自基于实验结果得出结论的人工智能 1.2.1. 这种方法需要的专业知识不同于开发理论模型或传统计…

6、python开发环境-PyCharm

下载完成之后双击进行安装 找到安装好的解释器程序

BERT系列模型 在OCNLI 训练微调 3

目录 0 资料1 项目搭建1.1 环境安装1.2 项目源码1.3 模型下载1.4 目录结构 2 改进部分2.1 可以实现更多模型的切换2.2 固定随机种子&#xff0c;保证输出的数据一致2.3 增加了另一个数据集进行联合训练2.4 模型测试时选择最好的一个模型而非最后一个 3 实验结果 0 资料 这是一…

css(四)

文章目录 css&#xff08;四&#xff09;一、其他样式1、圆角边框2、盒子阴影3、文字阴影 二、浮动1、传统网页布局的三种方式2、标准流&#xff08;普通流/文档流&#xff09;3、为什么需要浮动&#xff1f;4、什么是浮动&#xff1f;5、浮动特性6、浮动元素经常和标准流父级搭…

Linux IO模型深度解析与实战应用

linux的5种IO模型 一、这里IO是什么 操作系统设有用户态与内核态,确保系统安全。应用程序默认在用户态运行,而执行如IO操作等底层任务时,需切换至内核态以高效执行。 服务器从网络接收的大致流程如下: 1、数据通过计算机网络来到了网卡 2、把网卡的数据读取到 socket 缓…