SurfaceFinger FrameTimeline 分析

0 阅读8分钟

一、帧时间线简介

帧时间线(FrameTimeLine)是 Android 12 引入的、集成在 SurfaceFlinger 中的系统级卡顿检测与分析工具。它通过对比帧渲染的预期时间线与实际时间线,精准定位卡顿发生的时间和原因。每一帧的时间线都包括预期时间线(Expected Timeline)和实际时间线(Actual Timeline)两部分。

注意:这一节的介绍源自 谷歌 perfetto frametimeline 文档,部分信息已过时。

1.1 应用帧时间线

每一个在屏幕上至少显示过一帧的应用都会增加两个追踪。

timeline_tracks.png

  • 预期时间线:每个片段代表分配给应用程序用于渲染帧的时间。为了避免系统卡顿,期望应用程序在这时间内完成渲染。开始时间是 Choreographer 回调被调度运行的时间。
  • 实际时间线:这些片段代表应用程序完成一帧所实际花费的时间(包括 GPU 工作),并将其发送到 SurfaceFlinger 进行合成。开始时间是 Choreographer#doFrame 或 AChoreographer_vsyncCallback 开始运行的时间。这里的片段结束时间则是 max(gpu time, post time) 的值。提交时间是应用程序的帧被提交给 SurfaceFlinger 的时间。

app-timelines.png

1.2 合成器帧时间线

同样地,合成器也会获得这两个新追踪,分别表示其预计完成的时间和实际用于完成帧合成并在屏幕上显示的时间。在这里,SurfaceFlinger 的工作代表显示堆栈中的所有下级元素,包括 Composer 和 DisplayHAL。因此,这些片段代表了从 SurfaceFlinger 主线程开始到屏幕更新的全过程。

片段的名称表示从 choreographer 接收到的标记。你可以将实际时间线追踪中的片段与其对应的预期时间线追踪中的片段进行比较,以查看应用程序相较于预期的表现如何。此外,为了调试目的,该标记被添加到了应用程序的 doFrame 和 RenderThread 片段中。对于 SurfaceFlinger,相同的标记会在 onMessageReceived 中显示。

sf-vsyncid.png

二、合成器的屏幕帧时间线

在 SurfaceFlinger 中,应用帧时间线对应的实现是 SurfaceFrame,合成器帧时间线的实现是 DisplayFrame。本文仅分析 DisplayFrame 有关的流程。

2.1 DisplayFrame 定义

DisplayFrameFrameTimeline 的一个内部类,它有两个核心变量 mSurfaceFlingerPredictionsmSurfaceFlingerActuals,分别表示预期时间线和实际时间线。

// [services/surfaceflinger/FrameTimeline/FrameTimeline.h]
class FrameTimeline : public android::frametimeline::FrameTimeline {
    // ...
    /*
     * DisplayFrame should be used only internally within FrameTimeline. All members and methods are
     * guarded by FrameTimeline's mMutex.
     */
    class DisplayFrame {
        // ...
        /* Usage of TimelineItem w.r.t SurfaceFlinger
         * startTime    Time when SurfaceFlinger wakes up to handle transactions and buffer updates
         * endTime      Time when SurfaceFlinger sends a composited frame to Display
         * presentTime  Time when the composited frame was presented on screen
         */
        TimelineItem mSurfaceFlingerPredictions;
        TimelineItem mSurfaceFlingerActuals;
        // ...
    };
    // ...
};

mSurfaceFlingerPredictionsmSurfaceFlingerActuals 的类型为 TimelineItem,这是一个结构体,用于收集时间戳信息

// [services/surfaceflinger/FrameTimeline/FrameTimeline.h]
struct TimelineItem {
    TimelineItem(const nsecs_t startTime = 0, const nsecs_t endTime = 0,
                 const nsecs_t presentTime = 0, const nsecs_t desiredPresentTime = 0)
          : startTime(startTime),
            endTime(endTime),
            presentTime(presentTime),
            desiredPresentTime(desiredPresentTime) {}

    nsecs_t startTime;
    nsecs_t endTime;
    nsecs_t presentTime;
    nsecs_t desiredPresentTime;

    // ...
};

FrameTimeline 中,还定义了一个队列 mDisplayFrames 和一个指针 mCurrentDisplayFrame

class FrameTimeline : public android::frametimeline::FrameTimeline {
    // ...
    // Sliding window of display frames. TODO(b/168072834): compare perf with fixed size array
    std::deque<std::shared_ptr<DisplayFrame>> mDisplayFrames GUARDED_BY(mMutex);
    std::vector<std::pair<std::shared_ptr<FenceTime>, std::shared_ptr<DisplayFrame>>>
            mPendingPresentFences GUARDED_BY(mMutex);
    std::shared_ptr<DisplayFrame> mCurrentDisplayFrame GUARDED_BY(mMutex);
    // ...
};

2.2 预期时间线 mSurfaceFlingerPredictions

2.2.1 mSurfaceFlingerPredictions 的更新

直接赋值给 mSurfaceFlingerPredictions 的地方是 FrameTimeline::DisplayFrame::onSfWakeUp(),直接产生预期时间线的地方是 TokenManager::getPredictionsForToken()

// [services/surfaceflinger/FrameTimeline/FrameTimeline.cpp]
void FrameTimeline::DisplayFrame::onSfWakeUp(int64_t token, Fps refreshRate, Fps renderRate,
                                             std::optional<TimelineItem> predictions,
                                             nsecs_t wakeUpTime) {
    // ...
    if (!predictions) {
        mPredictionState = PredictionState::Expired;
    } else {
        mPredictionState = PredictionState::Valid;
        mSurfaceFlingerPredictions = *predictions;
    }
    // ...
}

void FrameTimeline::setSfWakeUp(int64_t token, nsecs_t wakeUpTime, Fps refreshRate,
                                Fps renderRate) {
    // ...
    mCurrentDisplayFrame->onSfWakeUp(token, refreshRate, renderRate,
                                     mTokenManager.getPredictionsForToken(token), wakeUpTime);
}

std::optional<TimelineItem> TokenManager::getPredictionsForToken(int64_t token) const {
    std::scoped_lock lock(mMutex);
    auto predictionsIterator = mPredictions.find(token);
    if (predictionsIterator != mPredictions.end()) {
        return predictionsIterator->second;
    }
    return {};
}

2.2.2 mPredictions 的定义

TokenManager::getPredictionsForToken() 函数是从 mPredictions 中获取一个 TimelineItem 对象。mPredictions 是定义在 TokenManager 中的一个 std::map

// [services/surfaceflinger/FrameTimeline/FrameTimeline.h]
class TokenManager : public android::frametimeline::TokenManager {
    // ...
    std::map<int64_t, TimelineItem> mPredictions GUARDED_BY(mMutex);
    // ...
};

2.2.3 mPredictions 的更新

mPredictions 添加元素的地方只有一处——TokenManager::generateTokenForPredictions(),该函数将函数入参 predictions 添加给 mPredictions

// [services/surfaceflinger/FrameTimeline/FrameTimeline.cpp]
int64_t TokenManager::generateTokenForPredictions(TimelineItem&& predictions) {
    // ...
    const int64_t assignedToken = mCurrentToken++;
    mPredictions[assignedToken] = predictions;
    return assignedToken;
}

对于 DisplayFrame,调用 TokenManager::generateTokenForPredictions(),传入 predictions 的地方是 MessageQueue::vsyncCallback()。在 MessageQueue::vsyncCallback() 函数中,它用自己的三个入参 targetWakeupTimereadyTimevsyncTime 创建了一个 TimelineItem 对象。

// [services/surfaceflinger/Scheduler/MessageQueue.cpp]
void MessageQueue::vsyncCallback(nsecs_t vsyncTime, nsecs_t targetWakeupTime, nsecs_t readyTime) {
    // ...
    const auto vsyncId = VsyncId{mVsync.tokenManager->generateTokenForPredictions(
            {targetWakeupTime, readyTime, vsyncTime})};
    // ...
}

综上,预期时间线来源于 MessageQueue::vsyncCallback() 的函数入参。

2.3 实际时间线 mSurfaceFlingerActuals

mSurfaceFlingerActualsDisplayFrame 构造时创建,不同于 mSurfaceFlingerPredictions,它的 startTimeendTimepresentTime独立更新 的。

2.3.1 mSurfaceFlingerActuals.startTime 的更新

直接给 startTime 赋值的地方是 FrameTimeline::DisplayFrame::onSfWakeUp()

// [services/surfaceflinger/FrameTimeline/FrameTimeline.cpp]
void FrameTimeline::DisplayFrame::onSfWakeUp(int64_t token, Fps refreshRate, Fps renderRate,
                                             std::optional<TimelineItem> predictions,
                                             nsecs_t wakeUpTime) {
    // ...
    mSurfaceFlingerActuals.startTime = wakeUpTime;
}

void FrameTimeline::setSfWakeUp(int64_t token, nsecs_t wakeUpTime, Fps refreshRate,
                                Fps renderRate) {
    // ...
    mCurrentDisplayFrame->onSfWakeUp(token, refreshRate, renderRate,
                                     mTokenManager.getPredictionsForToken(token), wakeUpTime);
}

顺着调用链进一步追踪,在 SurfacerFlinger::commit() 函数中,将 pacesetterFrameTargetPtr->frameBeginTime().ns() 作为 wakeupTime 传入。

// [services/surfaceflinger/SurfaceFlinger.cpp]
bool SurfaceFlinger::commit(PhysicalDisplayId pacesetterId,
                            const scheduler::FrameTargets& frameTargets) {
    const scheduler::FrameTarget& pacesetterFrameTarget = *frameTargets.get(pacesetterId)->get();

    const VsyncId vsyncId = pacesetterFrameTarget.vsyncId();
    SFTRACE_NAME(ftl::Concat(__func__, ' ', ftl::to_underlying(vsyncId)).c_str());
    // ...
    const Period vsyncPeriod = mScheduler->getVsyncSchedule()->period();
    // ...
    {
        mFrameTimeline->setSfWakeUp(ftl::to_underlying(vsyncId),
                                    pacesetterFrameTarget.frameBeginTime().ns(),
                                    Fps::fromPeriodNsecs(vsyncPeriod.ns()),
                                    mScheduler->getPacesetterRefreshRate());
        // ...
    }
    // ...
}

先看看 scheduler::FrameTarget 的定义。

// [services/surfaceflinger/Scheduler/include/scheduler/FrameTargeter.h]
// Read-only interface to the metrics computed by FrameTargeter for the latest frame.
class FrameTarget {
    // ...
    // The time when the frame actually began, as opposed to when it had been scheduled to begin.
    TimePoint frameBeginTime() const { return mFrameBeginTime; }
    // ...
    TimePoint mFrameBeginTime;
    // ...
};

scheduler::FrameTarget::frameBeginTime() 函数返回的是 scheduler::FrameTarget::mFrameBeginTime,它只在 FrameTargeter::beginFrame() 函数中更新。最终可以追到是在 Scheduler::onFrameSignal() 函数中创建 FrameTargeter:BeginFrameArgs,用当前时间 SchedulerClock::now() 赋值。

// [services/surfaceflinger/Scheduler/src/FrameTargeter.cpp]
void FrameTargeter::beginFrame(const BeginFrameArgs& args, const IVsyncSource& vsyncSource,
                               IsFencePendingFuncPtr isFencePendingFuncPtr) {
    // ...
    mFrameBeginTime = args.frameBeginTime;
    // ...
}
// [services/surfaceflinger/Scheduler/Scheduler.cpp]
void Scheduler::onFrameSignal(ICompositor& compositor, VsyncId vsyncId,
                              TimePoint expectedVsyncTime) {
    // ...

    const FrameTargeter::BeginFrameArgs beginFrameArgs =
            {.frameBeginTime = SchedulerClock::now(),
             .vsyncId = vsyncId,
             .expectedVsyncTime = expectedVsyncTime,
             .sfWorkDuration = mVsyncModulator->getVsyncConfig().sfWorkDuration,
             .hwcMinWorkDuration = mVsyncConfiguration->getCurrentConfigs().hwcMinWorkDuration,
             .debugPresentTimeDelay = debugPresentDelay};

    ftl::NonNull<const Display*> pacesetterPtr = pacesetterPtrLocked();
    pacesetterPtr->targeterPtr->beginFrame(beginFrameArgs, *pacesetterPtr->schedulePtr);

    // ...
}

2.3.2 mSurfaceFlingerActuals.endTime 的更新

有了前面 startTime 的基础,我们不难查到最终更新 endTime 的地方是 SurfaceFlinger::onCompositionPresented() 函数,用 presentTime = TimePoint::now() 赋值。

// [services/surfaceflinger/FrameTimeline/FrameTimeline.cpp]
void FrameTimeline::DisplayFrame::setActualEndTime(nsecs_t actualEndTime) {
    mSurfaceFlingerActuals.endTime = actualEndTime;
}

void FrameTimeline::setSfPresent(nsecs_t sfPresentTime,
                                 const std::shared_ptr<FenceTime>& presentFence,
                                 const std::shared_ptr<FenceTime>& gpuFence) {
    // ...
    mCurrentDisplayFrame->setActualEndTime(sfPresentTime);
    // ...
}
// [services/surfaceflinger/SurfaceFlinger.cpp]
void SurfaceFlinger::onCompositionPresented(PhysicalDisplayId pacesetterId,
                                            const scheduler::FrameTargeters& frameTargeters,
                                            nsecs_t presentStartTime) {
    // ...

    const TimePoint presentTime = TimePoint::now();

    // ...

    // Set presentation information before calling Layer::releasePendingBuffer, such that jank
    // information from previous' frame classification is already available when sending jank info
    // to clients, so they get jank classification as early as possible.
    mFrameTimeline->setSfPresent(presentTime.ns(), pacesetterPresentFenceTime,
                                 pacesetterGpuCompositionDoneFenceTime);

    // ....

2.3.3 mSurfaceFlingerActuals.presentTime 的更新

FrameTimeline::setSfPresent() 函数还会调用 FrameTimeline::flushPendingPresentFences() 函数。FrameTimeline::flushPendingPresentFences() 函数会遍历 mPendingPresentFences,给其中每一个 DisplayFramemSurfaceFlingerActuals.presentTime 赋值。

void FrameTimeline::DisplayFrame::onPresent(nsecs_t signalTime, nsecs_t previousPresentTime) {
    mSurfaceFlingerActuals.presentTime = signalTime;
    // ...
}

void FrameTimeline::flushPendingPresentFences() {
    // ...
    for (size_t i = 0; i < mPendingPresentFences.size(); i++) {
        const auto& pendingPresentFence = mPendingPresentFences[i];
        nsecs_t signalTime = Fence::SIGNAL_TIME_INVALID;
        if (pendingPresentFence.first && pendingPresentFence.first->isValid()) {
            signalTime = pendingPresentFence.first->getSignalTime();
            if (signalTime == Fence::SIGNAL_TIME_PENDING) {
                break;
            }
        }

        auto& displayFrame = pendingPresentFence.second;
        displayFrame->onPresent(signalTime, mPreviousActualPresentTime);
        // ...
    }
}

void FrameTimeline::setSfPresent(nsecs_t sfPresentTime,
                                 const std::shared_ptr<FenceTime>& presentFence,
                                 const std::shared_ptr<FenceTime>& gpuFence) {
    // ...
    flushPendingPresentFences();
    finalizeCurrentDisplayFrame();
}

2.3.4 小结

actual_timeline_release.png

三、预期时间线的计算

前文 2.2 小节分析过,SurfaceFlinger 的预期时间线是在 MessageQueue::vsyncCallback() 函数中创建的。接下来我们分析 MessageQueue::vsyncCallback() 三个入参的来源和计算过程。

3.1 MessageQueue::vsyncCallback() 的入参来源

MessageQueue::vsyncCallback() 是从 VSyncDispatchTimerQueueEntry::callback() 调用而来的,可以进一步定位到是从 VSyncDispatchTimerQueue::timerCallback() 函数调用过来的。

VSyncDispatchTimerQueue::timerCallback() 函数中,会创建 Invocation 结构体,将 mCallbacks 的元素的时间信息传递给它。

// [services/surfaceflinger/Scheduler/VSyncDispatchTimerQueue.cpp]
void VSyncDispatchTimerQueue::timerCallback() {
    SFTRACE_CALL();
    struct Invocation {
        std::shared_ptr<VSyncDispatchTimerQueueEntry> callback;
        nsecs_t vsyncTimestamp;
        nsecs_t wakeupTimestamp;
        nsecs_t deadlineTimestamp;
    };
    std::vector<Invocation> invocations;
    {
        // ...
        auto const now = mTimeKeeper->now();
        mLastTimerCallback = now;
        for (auto it = mCallbacks.begin(); it != mCallbacks.end(); it++) {
            auto& callback = it->second;
            auto const wakeupTime = callback->wakeupTime();
            if (!wakeupTime) {
                continue;
            }

            traceEntry(*callback, now);

            auto const readyTime = callback->readyTime();
            auto const lagAllowance = std::max(now - mIntendedWakeupTime, static_cast<nsecs_t>(0));
            if (*wakeupTime < mIntendedWakeupTime + mTimerSlack + lagAllowance) {
                callback->executing();
                invocations.emplace_back(Invocation{callback, *callback->lastExecutedVsyncTarget(),
                                                    *wakeupTime, *readyTime});
            }
        }

        mIntendedWakeupTime = kInvalidTime;
        rearmTimer(mTimeKeeper->now());
    }

    for (auto const& invocation : invocations) {
        ftl::Concat trace(ftl::truncated<5>(invocation.callback->name()));
        SFTRACE_FORMAT("%s: %s", __func__, trace.c_str());
        invocation.callback->callback(invocation.vsyncTimestamp, invocation.wakeupTimestamp,
                                      invocation.deadlineTimestamp);
    }
}

3.2 VSyncDispatchTimerQueueEntry

mCallbacksVSyncDispatchTimerQueue 类的一个成员变量,是一个键为 CallbackToken,值为 std::shared_ptr<VSyncDispatchTimerQueueEntry> 的哈希表。

// [services/surfaceflinger/Scheduler/VSyncDispatchTimerQueue.h]
class VSyncDispatchTimerQueue : public VSyncDispatch {
    // ...
    // The static capacity was chosen to exceed the expected number of callbacks.
    using CallbackMap =
            ftl::SmallMap<CallbackToken, std::shared_ptr<VSyncDispatchTimerQueueEntry>, 5>;
    // ...
    CallbackMap mCallbacks GUARDED_BY(mMutex);
    // ...
};

VSyncDispatchTimerQueueEntry 定义了一个 mCallback 变量,用于执行保存的回调,其类型为 VSyncDispatch::CallbackVSyncDispatchTimerQueueEntry 还定义了一个 mArmedInfo 变量,用于保存时间戳信息,它的类型为内部类 ArmingInfo

// [services/surfaceflinger/Scheduler/VSyncDispatchTimerQueue.h]
class VSyncDispatchTimerQueueEntry {
    // ...
    void callback(nsecs_t vsyncTimestamp, nsecs_t wakeupTimestamp, nsecs_t deadlineTimestamp);
    // ...
    struct ArmingInfo {
        nsecs_t mActualWakeupTime;
        nsecs_t mActualVsyncTime;
        nsecs_t mActualReadyTime;
    };
    // ...
    const VSyncDispatch::Callback mCallback;
    // ...
    std::optional<ArmingInfo> mArmedInfo;
    // ...
};

3.3 ArmingInfo

更新 VSyncDispatchTimerQueueEntry::mArmedInfo 的地方有两处,分别是 VSyncDispatchTimerQueueEntry::schedule()VSyncDispatchTimerQueueEntry::update()

  • VSyncDispatchTimerQueueEntry::schedule() 会直接计算时间戳信息
  • VSyncDispatchTimerQueueEntry::update() 的时间戳信息是在 VSyncDispatchTimerQueueEntry::getArmedInfo() 中计算的
ScheduleResult VSyncDispatchTimerQueueEntry::schedule(VSyncDispatch::ScheduleTiming timing,
                                                      VSyncTracker& tracker, nsecs_t now) {
    SFTRACE_NAME("VSyncDispatchTimerQueueEntry::schedule");
    auto nextVsyncTime =
            tracker.nextAnticipatedVSyncTimeFrom(std::max(timing.lastVsync,
                                                          now + timing.workDuration +
                                                                  timing.readyDuration),
                                                 timing.committedVsyncOpt.value_or(
                                                         timing.lastVsync));
    auto nextWakeupTime = nextVsyncTime - timing.workDuration - timing.readyDuration;

    bool const wouldSkipAVsyncTarget =
            mArmedInfo && (nextVsyncTime > (mArmedInfo->mActualVsyncTime + mMinVsyncDistance));
    bool const wouldSkipAWakeup =
            mArmedInfo && ((nextWakeupTime > (mArmedInfo->mActualWakeupTime + mMinVsyncDistance)));
    SFTRACE_FORMAT_INSTANT("%s: wouldSkipAVsyncTarget=%d wouldSkipAWakeup=%d", mName.c_str(),
                           wouldSkipAVsyncTarget, wouldSkipAWakeup);
    if (FlagManager::getInstance().dont_skip_on_early_ro()) {
        if (wouldSkipAVsyncTarget || wouldSkipAWakeup) {
            nextVsyncTime = mArmedInfo->mActualVsyncTime;
        } else {
            nextVsyncTime = adjustVsyncIfNeeded(tracker, nextVsyncTime);
        }
        nextWakeupTime = std::max(now, nextVsyncTime - timing.workDuration - timing.readyDuration);
    } else {
        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 ScheduleResult{TimePoint::fromNs(nextWakeupTime), TimePoint::fromNs(nextVsyncTime)};
}

void VSyncDispatchTimerQueueEntry::update(VSyncTracker& tracker, nsecs_t now) {
    SFTRACE_NAME("VSyncDispatchTimerQueueEntry::update");
    if (!mArmedInfo && !mWorkloadUpdateInfo) {
        return;
    }

    if (mWorkloadUpdateInfo) {
        const auto workDelta = mWorkloadUpdateInfo->workDuration - mScheduleTiming.workDuration;
        const auto readyDelta = mWorkloadUpdateInfo->readyDuration - mScheduleTiming.readyDuration;
        const auto lastVsyncDelta = mWorkloadUpdateInfo->lastVsync - mScheduleTiming.lastVsync;
        const auto lastCommittedVsyncDelta =
                mWorkloadUpdateInfo->committedVsyncOpt.value_or(mWorkloadUpdateInfo->lastVsync) -
                mScheduleTiming.committedVsyncOpt.value_or(mScheduleTiming.lastVsync);
        SFTRACE_FORMAT_INSTANT("Workload updated workDelta=%" PRId64 " readyDelta=%" PRId64
                               " lastVsyncDelta=%" PRId64 " committedVsyncDelta=%" PRId64,
                               workDelta, readyDelta, lastVsyncDelta, lastCommittedVsyncDelta);
        mScheduleTiming = *mWorkloadUpdateInfo;
        mWorkloadUpdateInfo.reset();
    }

    mArmedInfo = getArmedInfo(tracker, now, mScheduleTiming, mArmedInfo);
}

auto VSyncDispatchTimerQueueEntry::getArmedInfo(VSyncTracker& tracker, nsecs_t now,
                                                VSyncDispatch::ScheduleTiming timing,
                                                std::optional<ArmingInfo> armedInfo) const
        -> ArmingInfo {
    SFTRACE_NAME("VSyncDispatchTimerQueueEntry::getArmedInfo");
    const auto earliestReadyBy = now + timing.workDuration + timing.readyDuration;
    const auto earliestVsync = std::max(earliestReadyBy, timing.lastVsync);

    const auto nextVsyncTime =
            adjustVsyncIfNeeded(tracker, /*nextVsyncTime*/
                                tracker.nextAnticipatedVSyncTimeFrom(earliestVsync,
                                                                     timing.lastVsync));
    const auto nextReadyTime = nextVsyncTime - timing.readyDuration;
    const auto nextWakeupTime = nextReadyTime - timing.workDuration;

    if (FlagManager::getInstance().dont_skip_on_early_ro()) {
        bool const wouldSkipAVsyncTarget =
                armedInfo && (nextVsyncTime > (armedInfo->mActualVsyncTime + mMinVsyncDistance));
        bool const wouldSkipAWakeup =
                armedInfo && (nextWakeupTime > (armedInfo->mActualWakeupTime + mMinVsyncDistance));
        SFTRACE_FORMAT_INSTANT("%s: wouldSkipAVsyncTarget=%d wouldSkipAWakeup=%d", mName.c_str(),
                               wouldSkipAVsyncTarget, wouldSkipAWakeup);
        if (wouldSkipAVsyncTarget || wouldSkipAWakeup) {
            return *armedInfo;
        }
    }

    return ArmingInfo{nextWakeupTime, nextVsyncTime, nextReadyTime};
}

在这两处计算时间戳信息的地方,总是先计算出 nextVsyncTime,再结合 workDurationreadyDuration 计算出 nextWakeupTimenextReadyTime。具体计算过程不做详细分析,请感兴趣的读者仔细阅读源码。

3.4 小结

expected_timeline_release.png

四、SurfaceFlinger vsync 流程

基于前文对时间线的分析,不难梳理出 SurfaceFlinger vsync 流程,SurfaceFlinger 帧时间线的计算和更新与 vsync 流程密切相关。

4.1 TimerDispatch 触发 vsync

MessageQueue::scheduleFrame()/MessageQueue::onNewVsyncScheduleLocked()
  ->VSyncCallbackRegistration::schedule()
    ->VsyncDispatchTimerQueue::schedule()
      ->VsyncDispatchTimerQueue::scheduleLocked()
        ->VSyncDispatchTimerQueue::rearmTimerSkippingUpdateFor()
          ->VSyncDispatchTimerQueue::setTimer()
            ->TimeKeeper:alarmAt()
              ->Timer::alarmAt()

4.2 MessageQueue 发送消息

VsyncDispatchTimerQueue::timerCallback()
  ->VSyncDispatchTimerQueueEntry::callback()
    ->MessageQueue::vsyncCallback()
      ->MessageQueue::Handler::dispatchFrame()

4.3 MessageQueue 处理消息

MessageQueue::Handler::handlebessage()
  ->MessageQueue::onFrameSignal()
    ->Scheduler::onFrameSignal()
      ->FrameTargeter::beginFrame()
        Surfacerlinger::commit()
          ->FrameTimeline::setSfWakeUp()
            ->FrameTimeline::DisplayFrame::onSfWakeUp()
        SurfaceFlinger::composite()
          ->SurfaceFlinger::onCompositionPresented()
            ->FrameTimeline::setSfPresent()
              ->FrameTimeline::flushPendingPresentFences()
        FrameTargeter::endFrame()